← К библиотеке
Обход блокировок Теория

Активный пробинг: как тебя проверяют

Пассивную инспекцию все более-менее понимают. А вот что цензор умеет сам, от своего имени, постучаться к тебе на порт и проверить — для многих сюрприз. Разберём, зачем он это делает, что именно сверяет в ответе и почему честный self-steal бьёт пробинг там, где обычный Reality начинает потеть.

Перейти к практике

Что такое активный пробинг

Пассивная инспекция смотрит на трафик, который и так течёт мимо. Активный пробинг — принципиально другое: цензор сам инициирует соединение к твоему серверу и наблюдает за реакцией. Заподозрил соединение — не блокирует сразу, а через секунду-другую отправляет к тебе свой собственный запрос и сравнивает ответ с эталоном «как должен вести себя тот сайт, за который ты себя выдаёшь».

Логика убийственно простая. Если по адресу заявлен обычный HTTPS-сайт, значит на голый запрос он и ответит как сайт: отдаст страницу, редирект, ошибку, TLS-алерт — что-то узнаваемо-веб-серверное. А если по адресу сидит прокси, который ждёт секретного рукопожатия, он на «неправильный» запрос выдаст себя: повиснет молча, оборвёт соединение странным образом, ответит чем-то, чего у нормального сайта не бывает. Вот это расхождение между «заявлено» и «отвечает на самом деле» пробинг и ловит.

Почему это опаснее пассивного анализа

Пассивную статистику можно размывать: наматывать транспорт, подгонять длины и тайминги, растворяться в фоне. Пробинг так не обманешь, потому что он не про форму трафика, а про факт: живёт ли по адресу настоящий сервис или самозванец.

И тут возникает фундаментальная развилка любого стелс-протокола. Твоя нода обязана отличать своего клиента от чужого запроса — иначе кто угодно подключится. Значит, где-то есть проверка «свой/чужой». Вопрос в том, что нода делает с чужим:

  • Наивный прокол: чужому отвечают «не понял, до свидания» — обрывом, ошибкой протокола, тишиной. Ровно этот ответ пробинг и ждёт. Ты сам себя выдал.
  • Правильный подход: чужому отвечают ровно так, как ответил бы настоящий сайт, за который ты маскируешься. Пробинг стучится — и получает нормальный веб-ответ. Отличить нельзя.

Вся конструкция Reality построена вокруг второго пункта. Клиент без валидного ключа (короткого shortId, публичного ключа пары) не получает отлуп — нода прозрачно проксирует его запрос на настоящего донора и отдаёт клиенту настоящий ответ. Снаружи выглядит так, будто по адресу и правда живёт заявленный сайт. Пробинг ловит воздух.

Где обычный Reality всё-таки палится

Reality хорош, но у классической схемы есть тонкая щель. Обычно донор — чужой крупный сайт: ставишь serverName: www.microsoft.com, а нода при пробинге проксирует на настоящий microsoft. Работает. Но при глубоком анализе всплывает рассинхрон, которого у настоящего сайта быть не может:

  • Клиент заявляет SNI www.microsoft.com.
  • Но лезет он на твой IP.
  • А www.microsoft.com в DNS резолвится совсем в другие адреса, не в твой.

У честного сайта имя, IP и контент согласованы: www.microsoft.com и живёт на инфраструктуре Microsoft. У твоей ноды — имя чужое, IP свой. Умная инспекция может это сопоставить: «на этом IP кто-то отвечает от имени microsoft, хотя microsoft тут не хостится». Это не мгновенная смерть, но лишний рассинхрон, а рассинхроны — это то, из чего складывается решение заблокировать.

Идея self-steal: украсть собственный сайт

Self-steal («самокража») закрывает именно эту щель. Идея в том, чтобы донором был твой собственный сайт, а не чужой:

  • serverNames = твой домен, у которого A-запись честно указывает на твою ноду.
  • А донор (target/dest), на который нода проксирует чужие запросы при пробинге, — это сайт-обманка, поднятый прямо здесь же, на этой ноде (локальный веб-сервер).

Теперь всё сходится идеально. SNI — твой домен. IP — твой. Контент по этому адресу — настоящий работающий сайт (обманка). Пробинг стучится на https://твой-домен — и попадает на реальную живую страницу, которая физически хостится ровно там, куда указывает DNS. Никакого рассинхрона «имя от одного, IP от другого». Открой этот адрес в браузере — увидишь обычный сайт. И цензор при активном прозвоне увидит ровно то же самое: обычный веб-сервер на обычном домене.

Ключевая деталь, которую часто упускают: сайт-обманка должен быть правдоподобным. Пустая страница «It works» — это тоже сигнал: настоящий домен, за которым «ничего», подозрителен. Лендинг, блог, что угодно живое — вот что нужно. Чем обычнее выглядит сайт, тем скучнее нода для пробинга.

Что маскировка не решает

Честно про границы. Self-steal бьёт пробинг и рассинхрон «имя vs IP», но он не отменяет два других измерения инспекции:

  • Фингерпринт рукопожатия всё равно должен быть браузерным (fp), иначе ты палишься ещё до того, как дело дойдёт до пробинга.
  • Статистику потока self-steal не размывает — этим занимается транспорт (XHTTP/gRPC поверх).

И ещё: сам IP может быть уже отравлен независимо от того, как идеально настроена маскировка. Тогда режут на подлёте, и никакой self-steal не поможет — лечится ротацией адреса или CDN.

Так что self-steal — это не «серебряная пуля», а закрытие одной конкретной двери, самой неудобной. Пробинг — единственный слой, где нельзя «размыть», можно только честно быть настоящим сайтом. Self-steal и делает тебя настоящим.

Дальше — в практике: как поднять сайт-обманку на локальном сокете, как связать его с Reality-инбаундом через PROXY-protocol и как проверить, что пробинг видит нормальный сайт. Пошагово — в статье «Устойчивость к активному пробингу: настройка».

Следующий гайд Устойчивость к активному пробингу: настройка → Не понравилась статья или что-то непонятно? Напишите мне — помогу или поправлю. @notrealvpn →
Материал носит образовательный характер и посвящён инженерии сетевой инфраструктуры. Вы отвечаете за соблюдение законов своей юрисдикции.