← Back to library
Protocols Theory

Selfsteal: how a node pretends to be an ordinary website

Selfsteal is Reality in its sturdiest form. Ordinary Reality steals the handshake from someone else's site; selfsteal steals it from your own, on the same node. I break down — without commands — why it's better, why the consistency of SNI/IP/content breaks even deep analysis, and what the cost is. The step-by-step build is in the paired practice piece.

Go to practice

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

The problem selfsteal was invented for

Ordinary Reality with someone else's donor is good, but it has an inherent compromise, which I wrote about in detail in the donor breakdown. You set serverNames = someone else's site (say microsoft.com), and from the outside the handshake looks perfect. But there's a subtlety: that domain does not resolve to your node's IP. Under deep analysis DPI can compare the claimed name against the address owner and notice the mismatch — "the SNI says microsoft.com, but the IP belongs to a host in some odd country, and microsoft.com doesn't resolve here."

Under ordinary DPI this isn't critical — there would be too many false positives. But under the harshest DPI, which actively probes suspicious addresses and cross-checks the SNI against reality, it's a handle. Selfsteal removes it completely.

What selfsteal does

The idea flips Reality's logic. Instead of pretending to be someone else's site, the node pretends to be its own — a real site that lives on the same IP.

Here's the scheme. You have a domain whose A record points to the node. On the node itself a real decoy site runs — on a local socket or port, behind nginx or Caddy with a real certificate for your domain. In the Reality config:

  • serverNames = your domain (the one that resolves to the node);
  • target = your local decoy site (not someone else's donor, but a decoy on this same machine).

Now everything is consistent. The client shows your domain in the SNI. That domain resolves precisely to the node's IP. On that IP a real site actually lives at that domain, with a valid certificate. An active probe, poking at the address, lands on a real page at exactly the claimed name. No mismatch — SNI, IP, and content all match, just like any honest web server.

Why this breaks even deep analysis

Let's go through what DPI sees under each kind of check against a selfsteal node:

  • SNI in the handshake — your domain, an ordinary name, resolves to this same address. No anomaly.
  • Certificate — real, valid, issued for this domain via Let's Encrypt. Not self-signed, not the donor's, not suspicious.
  • Active probe — DPI opens a connection to the address and sees a real site at the claimed domain. There's content, the page is served, everything is as with an ordinary web server.
  • SNI ↔ IP match — perfect. The domain belongs to this IP, which is easily checked via DNS.

So along every axis by which DPI distinguishes a VPN from an honest site, a selfsteal node is an honest site — with the difference that a client with the right key gets a VPN inside that same connection. To an observer it's indistinguishable from an ordinary web server just running some website. This is the maximum level of stealth available without moving behind a CDN.

The role of PROXY protocol

One engineering detail worth understanding conceptually. When Reality proxies someone else's traffic (or an active probe) to the local decoy site, the site faces a question: what's the client's actual IP? After all, the connection arrives from the node's local address, not from the real visitor. So the decoy site sees the client's real IP, PROXY protocol is used between Reality and nginx — it passes the original client address in a separate header. In the config this is handled by the xver: 1 parameter on the Reality side and the corresponding proxy_protocol setting on the nginx side. Without a matched pair the decoy site won't see the client correctly. This doesn't affect stealth directly, but it's needed for the decoy to work right and to log real visits. The exact lines are in the practice piece.

What you pay for maximum stealth

Honest about the price, because selfsteal isn't a free upgrade:

  • You need your own domain. Unlike donor-based Reality, where no domain is needed at all, here a domain of your own with an A record to the node is mandatory.
  • You need a certificate. A real Let's Encrypt cert for that domain, with auto-renewal every 90 days.
  • You need a decoy site. And it must be believable. An empty "It works" page is a bad decoy: a real site doesn't look like that. A landing page, a blog, anything "alive" — so an active probe sees a normal resource, not a stub. This is extra fuss that ordinary Reality doesn't have.

In return you get stealth that survives even active probing and deep SNI/IP consistency analysis. Under harsh Russian DPI it's justified and often necessary; under mild DPI you can get by with donor-based Reality.

How to decide

The scheme is simple:

  • Harsh DPI, active probes, you have your own domain — go with selfsteal, it's the sturdiest option without a CDN.
  • Mild DPI or no domain of your own — donor-based Reality is enough; selfsteal is overkill.
  • They block by IP — selfsteal won't help (the handshake has nothing to do with it); you need to move behind a CDN over XHTTP.

Selfsteal is Reality taken to the limit: the node doesn't pretend to be someone else's site, it becomes an honest site at its own address. How to bring up a decoy site on nginx, configure the socket and PROXY protocol, and assemble the inbound per the official template — is in the paired practice piece "Selfsteal + nginx: step by step."

Next guide Selfsteal + nginx: step by step → 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.