REALITY vs XTLS Vision: Why the Handshake and Transport Layer Are Faster

REALITY changes the TLS handshake so the server no longer presents a certificate of its own; XTLS Vision changes what happens after the handshake, skipping the duplicate encryption of the inner TLS layer. They solve different problems, so you can use either one on its own or stack both on the same VLESS node.

At a glance

This article splits REALITY and XTLS Vision into two parts — handshake and transport. It covers how REALITY obtains a certificate chain from the target site to complete the handshake and where unauthorized connections get forwarded, and how XTLS Vision recognizes TLS records and passes them straight through, and which encryption layer that saves. By the end you can judge which combination suits your node, understand why CDN relay, WebSocket transport, and the v2fly core are out of the picture in these setups, and fill in the REALITY fields and the flow parameter correctly in v2rayN and v2rayNG.

Bottom line: one changes the handshake, the other changes the transport

REALITY is one way VLESS handles transport security, and it works at the handshake stage. The server holds no certificate for a domain of its own; instead it pulls a certificate chain from a target site (dest) to complete the handshake. Clients don't validate the server through a public CA — they verify identity with a public key preloaded in the config. Connections that fail verification are forwarded wholesale to dest, where visitors see the target site's real pages and real certificate chain.

XTLS Vision works after the handshake. When proxying HTTPS traffic there is already a TLS layer between the client and the destination website; once the outer handshake finishes, XTLS stops wrapping those inner TLS records inside the outer record layer for a second round of encryption and forwards the already-encrypted records directly. The server recognizes them and forwards them to the destination site the same way. What gets skipped is the duplicate layer, not the only layer.

Both are implemented by the Xray core and can be used separately or combined: VLESS + TCP + REALITY + flow=xtls-rprx-vision is the common server-side setup today. With REALITY alone and no flow, the handshake camouflage is unchanged — you just pay for one extra encrypt/decrypt pass under heavy traffic.

1-RTT
Full TLS 1.3 handshake
0-RTT
Session resumption handshake
443
Recommended listen port
TCP
Transport restrictions for both

The TLS handshake: where latency and fingerprints come from

A full TLS 1.3 handshake takes one round trip, and session resumption can reach 0-RTT. The SNI, cipher suite list, extension order, and key share groups in the handshake messages together form the client fingerprint; the certificate chain, signature algorithms, and session tickets returned by the server form the server fingerprint. Any item that doesn't match an ordinary HTTPS site can become a distinguishing feature.

The traditional self-hosted approach is to apply for a certificate for a domain you own, or to use a self-signed certificate. The former costs money for the domain and renewals; the latter often ends up with an incomplete certificate chain or an SNI that doesn't match the certificate, which is easy to spot without a proper fallback configuration.

What to checkSelf-signed certificate + fallbackREALITY
Certificate presented by the serverSelf-signed; browsers flag it as untrustedThe target site's real certificate chain
Does the SNI match the certificateOften mismatchedMatches
Unauthorized access to port 443Depends on the fallback config; may reveal proxy behaviorForwarded to dest; the real page is returned
How the client verifies identityCertificate chain validation, or skipped entirelyPreloaded public key + X25519 key exchange
Domain and certificate costDomain required; certificate needs renewalNo domain or certificate of your own needed

The differences in the table all come down to the first few handshake messages. REALITY's goal is to make those messages indistinguishable from visiting the target site directly — not to hide the traffic. The traffic is still standard TLS: record format, version numbers, and extensions match regular HTTPS. Only the certificate source and the verification method change.

REALITY: borrowing a real site's certificate chain

Configuring REALITY on the server takes four key values: dest (the target site, for example www.python.org:443), serverNames (the domain list matching dest), privateKey (the server private key, generated with the xray x25519 command), and shortIds (a list of short IDs used to tell clients apart). The client holds the matching publicKey, serverName, and shortId — all three map one-to-one to the server side.

When a connection arrives, the server runs an X25519 operation with its private key and the ephemeral public key in the ClientHello. If the expected result comes out, the connection is handled as a proxy; if not, the whole connection is forwarded to dest and the target site responds normally. That's also how to pick a target site: it should really exist, support TLS 1.3 and X25519, serve a normal web page, and ideally support HTTP/2 so the fallback looks natural.

REALITY + VLESS TCP

Recommended

No domain or certificate of your own needed; a single port 443 handles both handshake camouflage and proxying, and unauthorized visitors see the target site's real pages.

Best for: direct connections, single-server setups, resistance to active probing

Domain certificate + TLS + WebSocket

Straightforward to configure, though the certificate needs periodic renewal; WebSocket can be layered on the transport, which makes it easy to put a CDN relay in front later.

Best for: you already own a domain and want standard TLS on 443

Self-signed certificate + WebSocket + CDN

The origin IP is hidden behind the CDN, but the certificate chain is usually incomplete, so the fallback needs careful configuration — otherwise the handshake still stands out.

Best for: hiding the origin IP when extra setup steps are acceptable

Bottom line: decide on the CDN first, then pick a handshake scheme

Both REALITY and XTLS Vision rely on direct RAW (TCP) connections. Once you decide to relay through a CDN, neither can be layered on, and you should go back to the domain certificate + WebSocket combination. If you're staying on a direct connection, REALITY is the way to get a real certificate chain without buying a domain.

The limits deserve spelling out too: dest and serverNames must match — get it wrong and the handshake completes but the page reports a certificate error; shortId and publicKey must be issued as a pair, and a client that fills them in wrong simply can't connect; WebSocket, gRPC, HTTP/2 and other transports can't be layered on, so a CDN is out; the v2fly core (V2flyNG) supports VLESS well but doesn't parse REALITY fields, so REALITY nodes need to run on the Xray core — and v2rayNG ships with the Xray core built in.

XTLS Vision: dropping one encryption layer after the handshake

When proxying HTTPS, the data path has two TLS layers: one between the client and the destination website, and another between the client and the proxy server. The outer TLS protects the client-to-proxy segment; the inner TLS records are already encrypted once when they leave the client, and a conventional implementation treats them as an ordinary byte stream and encrypts them again inside the outer record layer.

XTLS instead inspects the first application data after the outer handshake completes: if it's a TLS ClientHello, the data on that connection is already encrypted, so the outer layer skips re-encryption and forwards it directly. If it isn't TLS traffic — plain HTTP, for example — it's encrypted and sent as usual. The decision is based on the first packet's content, with no extra switch to flip.

Vision is an improved XTLS implementation that fixes compatibility issues in the earlier xtls-rprx-direct under some scenarios and adds UUID validation and first-packet detection. It shows up in the config as the flow field: the server's clients entry uses "flow": "xtls-rprx-vision", and the client outbound sets the same value. If the two ends don't match, the connection fails or falls back to plain VLESS.

Configuration checklist: keys, flow, and fallback checks

  1. Generate the key pair

    Run xray x25519 on the server to get a private key and a public key; the private key stays in the server config, and the public key goes out to clients with the node details.

  2. Fill in the inbound config

    The inbound listens on 443 with VLESS + TCP, sets streamSettings.security to reality, and fills in dest, serverNames, shortIds, and privateKey.

  3. Enter the public key on the client

    In the v2rayN node editor, enter the address, port 443, and UUID, choose xtls-rprx-vision for flow, then fill in publicKey, serverName, and shortId.

  4. Verify fallback behavior

    Open the domain and port directly in a browser — you should see the dest site's page. A certificate error means dest and serverNames don't match.

  5. Check the core logs

    When a connection fails, look for REALITY, invalid user, and flow keywords in the logs, and first confirm that the public key and shortId were issued as a pair.

{
  "port": 443,
  "protocol": "vless",
  "settings": {
    "clients": [
      { "id": "8f7a2c1e-5b3d-4a9f-9c21-7d6e4b0a1f33", "flow": "xtls-rprx-vision" }
    ],
    "decryption": "none"
  },
  "streamSettings": {
    "network": "tcp",
    "security": "reality",
    "realitySettings": {
      "dest": "www.python.org:443",
      "serverNames": ["www.python.org"],
      "privateKey": "aP3nQ8vK2sL7dF9xR4tY6uW1zC5bN0mJ2hG8kD3sQ1E",
      "shortIds": ["6ba85179e30d4fc2"]
    }
  }
}

In the snippet, dest and serverNames point to the same domain — that's the prerequisite for REALITY to complete a handshake. shortIds can list several entries, one per client, so you don't have to regenerate server keys when swapping clients. The publicKey on the client side is the pair of the private key above, not another random value; fill it in wrong and the connection simply fails.

FAQ: probing, compatibility, and core differences

What do others see if they hit my port 443 directly?

Connections that don't carry the right public key are forwarded to the dest site, so visitors see that site's real pages and certificate chain — provided serverNames matches dest and the fallback path hasn't been broken.

Can a REALITY node sit behind a CDN?

No. Both REALITY and XTLS Vision rely on direct RAW (TCP) connections, and WebSocket, gRPC, and HTTP/2 — the transports a CDN can carry — can't be layered on. You'd need to switch back to the domain certificate + WebSocket combination.

The client has flow set but can't connect?

First check that the server's clients entry sets the same flow, then confirm the client is running the Xray core. The v2fly core doesn't parse REALITY fields, so node parameters for it have no effect.

Can I run REALITY without Vision?

Yes. REALITY handles handshake camouflage and Vision handles duplicate encryption at the transport layer; they're independent. Without flow, the handshake behaves the same — CPU usage is just a bit higher under heavy traffic.

Does dest have to be a big site?

Any site that supports TLS 1.3 and X25519, serves a normal web page, and uses a different domain from your own node works. dest and serverNames must match, don't use your own domain, and avoid domains that only return API data.

Scenario combinations: direct, CDN, and core choice

Single server with its own IP and no need to hide the origin: VLESS + TCP + REALITY + xtls-rprx-vision. One port 443 handles both handshake camouflage and transport optimization, no domain or certificate is needed, the config is minimal, and either v2rayN or v2rayNG works on the client side.

Already have a domain and certificate and need to go through a CDN: VLESS + WebSocket + TLS. Here neither REALITY nor Vision applies — the optimization moves to the CDN side and the choice of transport, not the handshake and transport layers. The fork in the road is whether the origin IP should be exposed; answer that first, and the parameters that follow actually mean something.

Bottom line: choose the transport first, the handshake scheme second

If you need a CDN, neither REALITY nor Vision is on the table. Once you're on a direct connection, pick between the two based on whether you want to maintain a domain of your own: if not, use REALITY; if you already have a domain and prefer standard TLS, use a domain certificate. Both complete the handshake in 1-RTT, so the difference isn't latency — it's where the certificate comes from and what the probing signature looks like.

Download v2rayN