← Back to library
Protocols Theory

Choosing an SNI and a donor: how not to blow your cover

Reality is only as good as the donor you pick. A bad SNI negates all the masking — the node gets burned not because of the protocol, but because of who it's pretending to be. I break down — without commands — which donor to take, what to avoid, and why rotation is mandatory.

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

What a donor and an SNI even are

A quick recap of the mechanics. Reality masks your node as someone else's big website — that's the donor. At the moment of the handshake the client sends a TLS ClientHello with the donor's name in the SNI (Server Name Indication) field — that name goes in plaintext, and it's exactly what DPI reads. Your job is to make that name so "whitelisted" and ordinary that no one will bother cutting it.

Two config parameters are tied to the donor: serverNames (the name the client shows in the SNI) and target/dest (where the node actually proxies someone else's traffic and active probes). In classic Reality they point to the same someone-else's site and must match. All the stealth rests on how well that site is chosen.

What a good donor should be

From practice — the criteria that actually matter, not "looks nice at a glance":

  • TLS 1.3. The donor must support modern TLS 1.3. On old TLS the masking won't assemble correctly, and the handshake profile will differ from what the client expects.
  • Large, live, neutral. A big popular resource that DPI is known not to nitpick. The more mundane a visit to this site is from your region, the better — traffic to it raises no questions.
  • Stable. The donor must always be reachable. If it goes down or changes its infrastructure, your node stops masking correctly — an active probe lands nowhere.
  • Not behind a CDN. This is an important and non-obvious point. A donor behind Cloudflare or another CDN is a bad choice: a CDN has its own certificate logic and its own behavior, which breaks handshake reuse. Take a domain on its own infrastructure, not behind a front.
  • Not yours. In classic Reality the donor is precisely someone else's site. Your own domain doesn't participate in this scheme at all (except in the selfsteal variant, where the logic is reversed — more on that below).

What a donor must not be

Mistakes that kill the masking:

  • A blocked or contentious domain. If the donor itself is cut in your region, or DPI already has grievances with it — you're masking under something that's already under suspicion. That's worse than no masking at all.
  • A small or rare site. A visit to an obscure resource is statistically unusual on its own. A donor should be one that people flock to en masse.
  • A donor behind a CDN. Repeating this because people often trip on it: a CDN breaks the scheme. Verify that the domain resolves to its own addresses, not to Cloudflare ranges.
  • The same one on all nodes. More on this separately, because it's the most common and most expensive mistake.

Why you can't use one SNI on all nodes

The temptation is understandable: found a good donor — put it everywhere. You can't do that, and here's why. If you have twenty nodes and all of them have the same serverNames, then from an observer's standpoint twenty different IPs in different data centers all suddenly mask under one and the same site. That's a statistical anomaly: a real site lives on its own infrastructure, not "smeared" across twenty random addresses. As soon as DPI links that SNI to a "VPN" pattern, all your nodes go down under a single block at once.

Hence the rule: rotate donors across nodes. Different nodes — different serverNames. Then blocking one donor takes out one node, not the whole service. And after each wave of blocks, change the donors and ports on the affected ones — don't wait until the next one gets poisoned.

The "SNI ≠ IP owner" mismatch

The main conceptual catch of classic Reality that you have to understand. You set serverNames = someone else's donor name, but that domain does not resolve to your node's IP. Under deep enough analysis DPI can compare: "the SNI claims microsoft.com, but the IP belongs to some host in an odd country, and microsoft.com doesn't resolve to this address." That's a mismatch between the claimed name and the address owner.

For most scenarios that's too little to warrant a block — there would be too many false positives, since there are plenty of legitimate reasons for such a discrepancy too. But under the harshest DPI it's a handle, and it needs closing off.

It's closed off with selfsteal: instead of someone else's donor, the node masquerades as your own site on the same IP. Then serverNames is your domain, it resolves to the node, a real page lives on it, and an active probe lands on a real site at exactly that address. SNI, IP, and content are consistent — no mismatch. This is the sturdiest option; it has its own pair of articles. The price — you need your own domain and a decoy site on the node.

How to decide

Boiled down to a working checklist:

  • Under ordinary DPI, someone else's donor is enough — a large neutral site with TLS 1.3, not behind a CDN, not yours, live and stable.
  • Under harsh DPI, move to selfsteal — your own domain, your own site on the node, no mismatch.
  • Always rotate donors and SNIs across nodes — one SNI on all of them kills the whole service with a single block.
  • After each wave, change donors and ports on the affected nodes.

Choosing a donor isn't a trifle at the end of setup — it's half the resilience of the whole scheme. How selfsteal technically removes the mismatch and makes the masking perfect — is in the articles on selfsteal.

Next guide Inbounds: assembling protocol configs by hand → 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.