Что внутри и почему данные не утекают

Техническое описание схемы: транспорт, что видит узел, чего он увидеть не может, и что проверялось.

Транспорт

Два узла: Даллас и Алматы. На каждом Xray 26.2.6.

СлойЧто используется
Основной входVLESS → WebSocket → TLS 1.3, сертификат Let's Encrypt на поддомене узла. Снаружи неотличим от обычного HTTPS-сайта
Резервный входVLESS → TCP → REALITY на 8443, маскировка под сторонний домен с валидным сертификатом
АутентификацияUUID v4 на пользователя, свой у каждого
Исходящийfreedom с domainStrategy: UseIPv4

Почему пароли и карты не видны узлу

Главный вопрос — отвечаю по слоям.

Внутри туннеля идёт ваш собственный TLS до конечного сайта. Узел терминирует только внешний слой (свой TLS) и передаёт дальше байты, которые для него непрозрачны: ключи сессии согласованы между вашим браузером и банком, на сервере их нет и быть не может.

[браузер] --TLS до банка--------------------------> [банк]
          \__ VLESS/WS/TLS до узла __/
                   узел видит: SNI, объём, тайминги
                   узел НЕ видит: тело, заголовки, пароли, номера карт

Чтобы узел увидел содержимое, потребовалось бы подменить сертификат банка, а это заметит браузер: pinning, CT-логи, предупреждение о недоверенном сертификате. Никакого MITM-прокси в схеме нет, CA в систему не ставится.

Что узел действительно видит: имя хоста из SNI (то есть «было соединение с sberbank.ru»), объём и время. Это метаданные, а не содержимое. И даже их он не записывает — см. ниже.

Банковский трафик вообще не доходит до узла

Разделение делается на клиенте, до туннеля.

В профиле прописаны правила: зона .ru, .рф, .su, плюс явный список доменов банков, госуслуг и маркетплейсов, плюс GEOIP,RU — всё это идёт DIRECT, минуя туннель. Для этих соединений сервер не видит даже SNI: трафик физически не доходит до него.

Отдельно разведён DNS: русские имена резолвятся российским резолвером напрямую (nameserver-policy), иначе был бы домашний IP при иностранном резолвере — заметное несоответствие.

Логирование

Ответ на «а что, если сервер изымут».

Xrayloglevel: none, access: none, error: none — журнал соединений не ведётся
systemd-journaldStorage=volatile — журнал только в tmpfs, на диск не пишется, при перезагрузке исчезает
nginx (раздача подписок)access_log off — токены не попадают в логи

Диагностические логи включались днём при отладке и были затёрты через shred.

Изоляция и защита узла

RoutingБлокируются 127.0.0.0/8, RFC1918, 100.64.0.0/10, 169.254.0.0/16, ULA, link-local и собственные адреса узла. Закрывает SSRF из туннеля к локальным службам
Протоколыbittorrent → blackhole, исходящий 25 → blackhole; на файрволе также 465, 587
SSHТолько ed25519-ключ. PasswordAuthentication no, PermitRootLogin prohibit-password, fail2ban
Файрволufw, default deny incoming; снаружи открыты только 22, 443, 8443
Обновленияunattended-upgrades включены, все текущие security-обновления установлены
КлиентыНе объединены в L2/L3-сегмент, видеть друг друга не могут

Раздача ключей

Токен20 hex-знаков, secrets.token_hex(10) — 80 бит, перебор нереален
Отдачаnginx отдаёт только по regex ^/sub/[0-9a-f]+/[0-9a-f]{20}\.(txt|json|yaml)$, autoindex off, всё остальное 404
СтраницаКлюч передаётся во fragment — не уходит в Referer и не попадает в логи сервера. Валидация origin: принимается только свой адрес подписки, чужой отклоняется
ЗаголовкиCSP default-src 'self', frame-ancestors 'none', Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff. Внешних ресурсов на странице нет
ОтзывUUID удаляется с обоих узлов, файл подписки стирается. Сначала узлы, потом реестр — чтобы сбой не оставил рабочий ключ

Что проверялось на пролом

Ограничения, о которых честно