XRAY (VLESS + REALITY + VISION)
Intro
VPNs were originally built to securely extend private networks across untrusted infrastructure, letting remote users or separate local networks communicate as if they were on the same internal network.
Today, the same tunneling model is also commonly used as a privacy layer for routing personal internet traffic more discreetly.
Comparing to the regular proxy, which just relays application traffic, a VPN is meant to securely extend a network boundary.
That matters because the original motivation behind VPNs was not “hide my IP,” but: “Make a remote device behave like it is securely attached to a private network.”
In this post, I’ll explain one of the simplest ways to set up a modern anti-sniffing VPN solution for personal use, without a VPC.
Hardware
Raspberry PI looks like a good option, since it’s a powerful mini-computer with all needed interfaces for the fair price.
The best option is to order it from Chinese marketplaces such as AliExpress. I used the Raspberry Pi 4B with 8 GB of RAM as an example, but you can choose a simpler model without Ethernet or USB-A and with 2 GB of RAM — it should serve the needs of dozens of users just fine.
I suggest to buy a complete set with the housing and a power unit, like this one.
The best choice will be to install there Ubuntu Server with Raspberry PI Imager. Don’t forget to add your ssh key during configuration, and connect Pi to the router via Ethernet.
XRay
The problem is that nowadays it’s pretty easy to sniff the traffic with dpi, detect packets of the popular VPN protocols and drop them.
The general solution is to built a proxy based on protocol like Shadowsocks, which is designed to be hard to detect, bypass firewalls and have traffic encryption.
My current pick is VLESS + REALITY transport with XTLS Vision on top of Xray-core.
What all that about:
- VLESS — a lightweight, stateless proxy protocol.
- REALITY — a transport layer for making traffic look like normal TLS/web traffic from the outside.
- XTLS Vision — the flow/control mode used with Xray to improve efficiency and performance.
That all is the part of Xray, a project that extends and enhances the capabilities of V2Ray. V2Ray can be compared with Shadowsocks protocol and can be called it’s successor (after the original Shadowsocks has been removed from the internet), rather than higher-level vpn/proxy solutions like Outline.
Xray supports VLESS, while V2Ray does not natively include it, making Xray the appropriate choice for this setup.
So, let’s configure XRay server and client.
Server (Ubuntu)
Install XRay:
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)"
Then, create a REALITY public/private key pair (X25519), generate it ONCE per inbound (server):
xray x25519
Generated key pair used by REALITY for the server/client cryptographic handshake.
Then generate a short uuid for that server:
openssl rand -hex 8
And finally - create the first client ID with xray uuid.
You should do it for every new client, and update the server config with the new client entry (see example below).
Create a config file at /usr/local/etc/xray/config.json:
{
"inbounds": [
{
"listen": "0.0.0.0",
"port": 4443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<USER_UUID>",
"level": 0,
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
//... or any other public, highly-available service
// which is reachable from the server
"dest": "www.cloudflare.com:443",
"xver": 0,
"serverNames": ["www.cloudflare.com"],
"privateKey": "<PRIVATE_KEY>",
"shortIds": [
"<SHORT_ID>"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}
Test that config is correct:
xray run -test -config /usr/local/etc/xray/config.json
Start the service: sudo systemctl start xray
Enable it to start on boot: sudo systemctl enable xray
Check the status: sudo systemctl status xray
Or check logs: journalctl -u xray
Don’t forget to setup port forwarding on your router for the specified port (e.g. 4443).
Ensure your firewall allows traffic on a selected port using ufw (allow 4443).
Clients
Mobile / Mac OS
Install V2BOX from the store.
The simplest way to configure would be just to construct a link and paste into the app:
vless://<UUID>@<SERVER_IPV4>:<PORT>?type=tcp&encryption=none&security=reality&flow=xtls-rprx-vision&sni=www.cloudflare.com&fp=chrome&pbk=<PUBLIC_KEY/PASSWORD>&sid=<SHORT_ID>#<CONNECTION_NAME>
Linux (Ubuntu)
Install the same xray executable the same way you did for the server:
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)"
Add generated ids and keys to the /usr/local/etc/xray/config.json:
{
"log": { "loglevel": "warning" },
"inbounds": [
{
"listen": "127.0.0.1",
"port": 1081,
"protocol": "socks",
"settings": { "udp": true }
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "<SERVER_IPV4>",
"port": 4443,
"users": [
{
"id": "<UUID>",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.cloudflare.com",
"publicKey": "<REALITY_PUBLIC_KEY/PASSWORD>",
"shortId": "<SHORT_ID>",
"fingerprint": "chrome"
}
}
}
]
}
NOTE: With that config, you only tunnel the traffic that you explicitly send into Xray’s local proxy ports.
Then enable and reload the daemon:
sudo systemctl enable xray
sudo systemctl start xray
sudo systemctl status xray
If everything is green — great, it means our proxy has started up at http://127.0.0.1:1081. Next, go check the IP using any public service:
HTTP_PROXY=http://127.0.0.1:1081 HTTPS_PROXY=http://127.0.0.1:1081 curl -s https://api.ipify.org
The IPv4 address should match the server ip.
In the example above you can see that it’s enough to use the default environment variables when running any process — and most likely they’ll be interpreted correctly by the apps you use. The most common ones are HTTP/S_PROXY and http/s_proxy.
Enjoy!