🥷 NaiveProxy: прокси, который копирует настоящий Chrome

О чём заметка

Разбор NaiveProxy — прокси, построенного на сетевом стеке Chromium: вместо того чтобы придумывать очередную маскировку, он буквально повторяет поведение настоящего браузера. Здесь: как устроена схема с фронтенд-сервером, что даёт набивка первых пакетов, почему протокол поддерживается далеко не всеми ядрами и кому он подходит. Карта протоколов — в обзоре.

TL;DR

  • NaiveProxy использует сетевой стек Chromium, поэтому TLS-рукопожатие и поведение HTTP/2 у него не «похожи на браузер», а совпадают с настоящим Chrome — подделывать отпечаток не требуется.
  • Транспорт — туннель HTTP/2 (или HTTP/3) CONNECT внутри обычного TLS-соединения к веб-серверу. Со стороны это выглядит как визит на сайт с постоянным соединением.
  • Защита от активного зондирования сделана фронтингом приложения: фронтенд-сервер (обычно Caddy с плагином forwardproxy) маршрутизирует запрос по заголовку авторизации — без верных данных посетитель получает обычный сайт.
  • Набивка первых восьми чтений и записей случайными 0–255 байтами сглаживает распределение длин пакетов; дальше трафик идёт без набивки ради скорости.
  • Поддержка в ядрах ограничена: есть в sing-box (и входящий, и исходящий), нет в mihomo и Xray-core. Это тот случай, когда протокол диктует выбор ядра.
  • Цена подхода — вес и негибкость: клиент тянет за собой кусок Chromium, а сервер требует отдельной связки с веб-сервером.

Логика: не имитировать браузер, а быть им

Большинство протоколов обхода решают задачу маскировки так: «сделаем трафик похожим на обычный HTTPS». Проблема в том, что похожесть всегда неполная. Программа на Go или Rust строит TLS-рукопожатие своей библиотекой, и набор шифров, расширений и их порядок отличается от браузерного — так рождается отпечаток, по которому инструмент опознают без всякой расшифровки (механика разобрана в заметке про JA4-отпечатки). Отсюда целая индустрия подделки отпечатков — библиотека uTLS и параметр client-fingerprint в mihomo.

NaiveProxy заходит с другой стороны: берёт сетевой стек Chromium целиком и работает через него. Рукопожатие делает тот же код, что в браузере, HTTP/2 ведёт себя как в браузере, приоритеты потоков и служебные кадры — браузерные. Подделывать нечего, потому что это не подделка.

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

Как устроена схема

Цепочка выглядит так: браузер → клиент NaiveProxy → сеть (цензор) → фронтенд-сервер → сервер NaiveProxy → интернет.

Клиент поднимает у вас локальный прокси-порт и устанавливает к вашему серверу обычное TLS-соединение, внутри которого открывает туннель методом CONNECT по HTTP/2 (поддерживается и HTTP/3). Все ваши соединения мультиплексируются в этом туннеле — то есть в сеть уходит одно длинное соединение с сервером, а не десятки коротких.

Фронтенд-сервер — обычный веб-сервер, чаще всего Caddy с плагином forwardproxy (есть форк, добавляющий набивку в стиле NaiveProxy). Он смотрит на заголовок авторизации в запросе: если данные верные — запрос уходит в прокси-часть, если нет — обслуживается как обычный веб-запрос. Отсюда и устойчивость к активной проверке: цензор, постучавшийся на ваш домен, увидит сайт, а не прокси.

Набивка. Первые 8 операций чтения и записи в каждом потоке дополняются случайным количеством байтов (0–255), чтобы сгладить характерное распределение длин пакетов в начале соединения. Дальше набивка отключается — она нужна там, где формируется узнаваемый почерк, а не на всём объёме трафика, иначе пострадала бы скорость.

По README проекта, такая конструкция направлена против четырёх угроз: определения посещаемых сайтов по «отпечатку трафика» (мешает мультиплексирование), отпечатка TLS-параметров (решается стеком Chromium), активного зондирования (решается фронтингом) и анализа по длинам пакетов (решается набивкой и фрагментацией).

Сильные и слабые стороны

Сильные.

  • Отпечаток не отличается от браузерного — самый принципиальный плюс, и он не требует поддержки со стороны цензора «поверить» в маскировку.
  • Поведение трафика похоже на веб-сёрфинг: одно долгое HTTP/2-соединение с мультиплексом — ровно то, что делает браузер на современном сайте.
  • Проверенная временем схема: проект существует давно и используется в жёстко цензурируемых сетях.

Слабые.

  • Вес. Клиент несёт в себе часть Chromium, поэтому бинарник большой, а сборка под нестандартные платформы — отдельная задача. Для сравнения: клиент Trojan — это единицы мегабайт.
  • Серверная часть сложнее. Нужен домен, сертификат и веб-сервер с плагином — а не «один бинарник с конфигом», как у Hysteria или VLESS.
  • Ограниченная поддержка в ядрах — главный практический ограничитель, о нём ниже.
  • Свой домен обязателен, а значит, остаются следы: регистрация домена и запись сертификата в публичных логах прозрачности. Прикрыться чужим сайтом, как это делает REALITY, NaiveProxy не умеет.

Отпечаток решает не всё

Совпадение TLS-отпечатка с Chrome снимает один класс детекта, но не отменяет остальные: наблюдатель по-прежнему видит, что вы держите долгое соединение с одним доменом и гоните через него весь трафик. В сетях, где смотрят на объёмы и на репутацию адреса назначения, это остаётся заметным. Ни один протокол не закрывает все уровни анализа сразу.

Поддержка в ядрах — почему это важно

NaiveProxy — самый наглядный пример того, что список поддерживаемых протоколов при выборе ядра проверять обязательно:

ЯдроПоддержка naive
sing-boxЕсть, и входящий, и исходящий (в свежих версиях — с QUIC и ECH)
mihomoНет
Xray-coreНет

Иначе говоря, если сервер выдаёт вам naive, вопрос «какое ядро удобнее» не стоит: подойдёт то, где протокол реализован. Никакие достоинства маршрутизации в mihomo этого не компенсируют. Подробнее логика выбора ядра — в сравнении mihomo, sing-box и Xray.

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

Кому подходит

NaiveProxy разумен, когда приоритет — устойчивость к отпечаткам, а не гибкость: в сетях с жёстким DPI, который отбирает соединения по TLS-почерку и добивает активным зондированием. Он же удобен, если у вас уже есть сайт на Caddy и добавить прокси-функцию к нему — небольшое изменение.

Если же вам нужны десятки узлов, сложная маршрутизация и подписки — экосистема вокруг VLESS с REALITY или mihomo даст больше удобства. Разумный компромисс — держать naive-узел запасным каналом на случай, когда основную схему начинают распознавать.

📚 См. также


🤖 Эти статьи открыты — можно обучать на них ИИ

При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: исходник этой заметки · весь репозиторий.