There are dozens of Reality configurations on the forum, but few explain why it actually works. And understanding this matters: when you know the mechanics, you consciously tune the dest/serverNames, not just copy someone else’s JSON at random. Let’s break down the REALITY (XTLS) protocol in human terms — no fluff, but to the point.
The problem Reality solves
Classic “TLS-wrappers” (Trojan, VMess+TLS) are vulnerable from several angles:
- TLS-in-TLS. Inside your TLS, another TLS travels from the proxy — DPI can recognize this “double” pattern.
- Your certificate = your fingerprint. To run a legitimate TLS, you need a domain and a certificate, and the combo “domain + certificate + server behavior” forms an identifiable signature.
- SNI is visible. The domain name in ClientHello is open — censors can easily block by SNI.
- Active probes. A censor hits your server and, based on an non-standard response, realizes it’s a proxy.
The key idea: not to set up TLS, but to borrow someone else’s
Reality does not implement its own TLS — it borrows the handshake from a real third-party site. In the config you specify the real target (dest, for example www.microsoft.com:443), and the client makes it look like it’s connecting to that site. From the outside it appears as a regular visit to a popular site with a valid certificate for that site.
Next comes authentication with X25519:
- the server generates an X25519 key pair; the public key is effectively the client password (
publicKey); - the client, inside a legitimate TLS stream, proves knowledge of the key — covertly to an observer;
- authenticated client obtains a temporary certificate signed by an ephemeral key, and continues to ride the proxy;
- unauthenticated request (censor probe, random scanner) fails against the real target site and gets its real content.
That’s the magic: the server is indistinguishable from the site it impersonates. If it doesn’t have its own certificate — there’s nothing to fingerprint; no TLS-in-TLS — nothing to catch; an active probe bounces off the real microsoft.com.
The main config parameters
From the server side:
dest(target) — the real site donor of the handshake,domain:port;serverNames— list of SNI that the client is allowed to present (must correspond todest);privateKey— the private key for X25519;shortIds— short identifiers for differentiating clients/groups.
From the client side:
serverName— which SNI to present (fromserverNames);publicKey— the server’s public key;shortId— corresponding identifier;fingerprint— uTLS profile (chrome,firefox, etc.) so that the TLS fingerprint matches real browser traffic.
A sober assessment: not a silver bullet
Reality is strong, but it has rigid requirements that trip up beginners.
- Choosing
destis critical. The donor should be a “foreign”, popular site that supports TLS 1.3 and X25519, geographically close to your server, and not behind Cloudflare or your own host. A baddest— masking collapses. serverNamesmust matchdest. Desynchronization is the typical reason for “not connecting.”- This is not a cure-all for blocks. Reality masks the fingerprint, but does not shield from IP-based blocking of your server or from traffic volume/timeing heuristics. Fresh blocks sometimes require combining transports (see forum topic about xHTTP).
- Compatibility. Reality is part of the XTLS/Xray ecosystem; both client and server must support it (current Xray-core, sing-box, clients like v2rayN/Throne/Streisand).
What to do
- Choose
destconsciously: a large third-party site with TLS 1.3 and X25519, geographically near your server, not behind Cloudflare. You can verify support, for example, via online TLS checkers. - Keep
serverName= one of theserverNames= thedestdomain. This fixes about 90% of the “not connecting” issues. - Set
fingerprint: chrome(or the current browser profile) on the client — so the uTLS fingerprint matches the mass of traffic. - Don’t rely solely on Reality: with strong DPI, keep a backup transport and remember about IP-based blocks.
Sources
- Official XTLS/REALITY repository (protocol and parameters)
- Xray-core — implementations and config examples
Which dest are you using and what criteria did you use to select it? And have you noticed any degradation of Reality under recent DPI — what helped: changing the donor, IP, or combining transports?
