🐴 Trojan: прокси, который притворяется обычным HTTPS-сайтом

О чём заметка

Разбор протокола Trojan — минималистичного прокси поверх настоящего TLS, устроенного вокруг одной идеи: сервер должен вести себя как обычный веб-сайт для всех, кто не знает пароля. Здесь: как работает механизм отката (fallback), чем Trojan отличается от VLESS, что добавил Trojan-Go и где у схемы слабое место. Карта протоколов — в обзоре.

TL;DR

  • Trojan не изобретает своё шифрование: он работает внутри обычного TLS-соединения к вашему домену с настоящим сертификатом. Всё шифрование — это тот же TLS, которым пользуется весь веб.
  • Аутентификация предельно простая: первым делом клиент отправляет хеш пароля, и если он верный — сервер начинает проксировать.
  • Главная защитная идея — fallback: при неверном пароле или при обычном визите браузером сервер молча передаёт соединение настоящему веб-серверу. Активный зонд видит нормальный сайт, а не «странный порт».
  • Требуется домен и валидный сертификат — в этом отличие от REALITY, который позволяет прикрыться чужим сайтом без собственного домена.
  • Слабое место — не аутентификация, а статистика: связка «TLS внутри TLS» имеет узнаваемый почерк, и современный DPI ловит её независимо от корректности fallback.
  • Trojan-Go — форк с транспортом WebSocket, мультиплексированием и другими надстройками; исходный trojan-gfw/trojan — эталонная реализация на C++.

Идея: не выделяться, потому что ты и есть сайт

Trojan появился как реакция на слабость протоколов «случайных байтов» вроде раннего Shadowsocks: их выдавал сам факт того, что трафик не похож ни на что известное. Ответ автора Trojan звучал так: не надо изобретать маскировку — надо просто быть настоящим HTTPS-сервером.

Устройство минимально. На сервере стоит веб-сайт с доменом и обычным сертификатом (Let’s Encrypt подойдёт). Клиент устанавливает к нему обычное TLS-соединение — то же самое рукопожатие, которое делает браузер. Внутри установленного канала клиент первым же сообщением отправляет: хеш пароля (SHA-224 в шестнадцатеричном виде), команду (TCP/UDP), адрес назначения — и дальше данные.

Сервер, получив соединение, смотрит на первые байты. Пароль верный — работает как прокси. Пароль неверный или это вообще обычный HTTP-запрос браузера — сервер отдаёт соединение настоящему веб-серверу, и посетитель видит нормальный сайт.

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

Fallback: почему это главное в протоколе

Механизм отката заслуживает отдельного объяснения, потому что именно он отличает Trojan от протоколов, которые «просто шифруют».

Классический сценарий обнаружения прокси — активное зондирование: цензор видит подозрительное соединение, запоминает адрес и позже сам подключается к серверу, пробуя разные варианты. Протокол без защиты выдаёт себя реакцией: обрывает соединение, отвечает мусором, ведёт себя не как веб-сервер. Так в своё время ловили и Shadowsocks, и уязвимую реализацию VMess.

Trojan на такую проверку отвечает содержимым настоящего сайта — не эмуляцией, а буквально ответом реального веб-сервера, который стоит рядом. Отличить это от обычного хостинга по одному запросу нельзя.

Fallback защищает от зонда, но не от статистики

Устойчивость к активной проверке — половина задачи. Вторая половина — пассивный анализ: у соединения, внутри которого работает ещё одно шифрованное соединение («TLS внутри TLS»), характерные размеры первых пакетов и ритм обмена, отличающиеся от обычного просмотра сайта. Именно этот класс детекта разобран в заметке про DPI-почерк TLS, и против него в мире Xray придуманы XTLS Vision, а в соседних экосистемах — AnyTLS с его набивкой. У Trojan своего ответа на эту проблему нет.

Второе ограничение — нужен настоящий домен с сертификатом. Это и деньги (домен), и след: домен регистрируется, сертификат попадает в публичные логи Certificate Transparency, а сайт-прикрытие должен выглядеть правдоподобно. Именно эту цепочку требований снял REALITY, позволивший прикрываться чужим сайтом без собственного домена — поэтому новые установки чаще делают на нём.

Trojan против VLESS

Вопрос возникает постоянно, потому что оба протокола работают внутри TLS и оба почти не добавляют собственного шифрования.

СвойствоTrojanVLESS
АутентификацияХеш пароля в начале потокаUUID пользователя
Собственное шифрованиеНет, только TLSНет, только TLS (в новых версиях есть опциональное шифрование)
Защита от активного зондаFallback на настоящий веб-серверFallback у Xray-сервера, а с REALITY — прикрытие чужим сайтом
Свой домен и сертификатОбязательныОбязательны для обычного TLS, не нужны с REALITY
Борьба с «TLS внутри TLS»Не предусмотренаXTLS Vision
РазвитиеПрактически остановилосьАктивное, в Project X

Вывод из таблицы простой: Trojan — исторически важный и по-прежнему рабочий протокол, но VLESS покрывает те же сценарии и умеет больше. Если сервер уже работает на Trojan и не блокируется — менять ради самой смены незачем. Если поднимаете новое — почти всегда разумнее VLESS с REALITY.

Trojan-Go и варианты

Эталонная реализация — trojan-gfw/trojan на C++. Форк Trojan-Go добавил к протоколу то, чего не хватало на практике: транспорт WebSocket (позволяет прятать соединение за CDN), мультиплексирование нескольких потоков в одном соединении, обфускацию через плагины Shadowsocks, встроенный менеджер пользователей. Поддержка Trojan есть во всех универсальных ядрах — mihomo, sing-box, Xray-core, — поэтому клиент выбирается свободно.

«Trojan» в подписке не всегда значит одно и то же

В конфигах встречаются варианты: чистый Trojan поверх TLS, Trojan поверх WebSocket (наследие Trojan-Go), Trojan с обёрткой вроде ShadowTLS. Параметры транспорта должны совпадать на клиенте и сервере — при рассинхроне соединение не установится, хотя пароль и адрес верны. Это частая причина «ключ рабочий, а не подключается».

Практические выводы

  • Trojan имеет смысл там, где уже есть домен и сайт: прокси прячется за реальным веб-присутствием, и это выглядит естественно.
  • Держите сайт-прикрытие настоящим и осмысленным. Пустая страница «It works!» на домене, к которому идёт заметный трафик, — сама по себе подозрительная деталь.
  • Не рассчитывайте на fallback как на полную защиту: он закрывает активные проверки, а не поведенческий анализ.
  • Для новых развёртываний сравните с VLESS + REALITY: там не нужен свой домен и есть ответ на «TLS внутри TLS».

📚 См. также

  • Обзор протоколов — карта задач и поддержки в ядрах.
  • Протокол VLESS и REALITY — основная альтернатива и её преимущества.
  • Shadowsocks — протокол, недостатки которого Trojan исправлял.
  • VMess — третий ветеран эпохи и его уязвимость к активному зондированию.
  • AnyTLS — современный подход к проблеме «TLS внутри TLS».
  • VLESS + TLS: DPI-почерк — как выглядят такие соединения для DPI.

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

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