← Back to library
Protocols Practice

VLESS + Reality: a config that doesn't get spotted

Reality is what keeps your node alive under DPI in 2026. Not "yet another protocol", but a way to look like some popular site that isn't yours. Below is a working config and a breakdown of every field. Fill in your keys in the constructor above (or generate them with the 🎲 button), then just copy.

Read the theory

This material is about engineering your own infrastructure and is educational in nature. Complying with the laws of your own jurisdiction is your responsibility.

Why Reality when plain TLS exists

Classic VLESS+TLS gets spotted in a heartbeat: you've got a self-signed or fresh Let's Encrypt cert on some obscure domain, DPI sees a rare SNI and tears down the handshake. Reality solves this elegantly — it doesn't stand up its own TLS at all. It presents itself as some big site that isn't yours (a donor) and reuses that site's genuine certificate. From the outside it's indistinguishable from you visiting www.microsoft.com.

The key idea: the donor is someone else's large resource with TLS 1.3 that nobody will find fault with. Not your domain. Your domain doesn't take part at all.

Generating keys

Reality rests on an x25519 pair and a short identifier. They're generated in a second:

bash
# an x25519 key pair (privateKey → to the server, publicKey → to the client)
xray x25519

# shortId — a short hex of even length
openssl rand -hex 8

# client UUID
xray uuid

privateKey stays on the node; publicKey and shortId go into the client's subscription. Mix them up and the handshake won't come together, and you'll spend an hour staring at "why won't it connect".

Server config

Here's the inbound I use by default. Fill in your values in the constructor — they'll be substituted here and into the client side at the same time:

config.json
{
  "inbounds": [
    {
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          { "id": "CLIENT_UUID", "flow": "xtls-rprx-vision" }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "www.cloudflare.com:443",
          "serverNames": ["www.cloudflare.com"],
          "privateKey": "PRIVATE_KEY_X25519",
          "shortIds": ["REALITY_SHORT_ID"]
        }
      }
    }
  ]
}

Field-by-field breakdown:

  • flow: xtls-rprx-vision — Vision mode; it removes the double TLS-in-TLS encryption and, at the same time, breaks the statistical analysis of packet lengths. On TCP this is the mandatory minimum.
  • dest and serverNames — that same donor. They must match. Pick a site that is definitely alive and holds TLS 1.3.
  • privateKey — the private half of the pair you generated above.
  • shortIds — you can have several; handy for handing different clients different ones.

The client side

The client needs a mirror set, but with publicKey instead of privateKey:

vless-link
vless://CLIENT_UUID@your-domain.com:443?security=reality&encryption=none&pbk=REALITY_PUBLIC_KEY&fp=chrome&sni=www.cloudflare.com&sid=REALITY_SHORT_ID&flow=xtls-rprx-vision&type=tcp#my-node

fp=chrome is the TLS client fingerprint (uTLS). If the Chrome fingerprint starts getting throttled in your region — switch to firefox; it often helps ride out the wave.

Verification

Bring the node up with this config, connect with a client, and check two things: that egress goes through the node and that the handshake is actually masqueraded:

bash
# 1. egress through the node
curl -s https://api.ipify.org

# 2. from the outside — the server should respond like the donor
curl -sI https://your-domain.com | head -1

The second request to your domain should behave as if it's an ordinary site, not "something suspicious on 443". If Reality is assembled correctly, from the outside you're indistinguishable from a million HTTPS connections. That's exactly what we were after.

Next guide Vision (xtls-rprx-vision): why you need flow → Article unclear or something off? Message me and I will help or fix it. @notrealvpn →
This material is educational and covers network-infrastructure engineering. You are responsible for complying with the laws of your jurisdiction.