Активное зондирование: почему сервер должен молчать одинаково
Обсуждая маскировку, обычно думают о пассивном наблюдателе: что он видит в проходящем трафике. Но есть вторая половина задачи, о которой вспоминают позже. Цензор не обязан ограничиваться наблюдением: он может подключиться к серверу сам и по одной лишь манере отказа отличить его от обычного веб-сервера.
Двухступенчатая схема#
Полный анализ каждого соединения дорог. Поэтому применяется дешёвая схема из двух ступеней.
1. ПАССИВНО: дешёвые признаки на потоке
энтропия, длины первых пакетов, отсутствие маркеров
│
▼ адрес помечен подозрительным
│
2. АКТИВНО: отдельная инфраструктура подключается сама
отправляет подготовленные запросы, смотрит на ответ
│
▼
ответ отличительный? ──► адрес в блок-лист
Первая ступень отсеивает почти всё и работает на потоке. Вторая дорогая, но применяется к малой доле адресов.
Исследование блокировки Shadowsocks описало эту схему в деталях: подозрение возникало по длине и энтропии первого пакета данных, после чего к адресу шли зонды нескольких типов, причём с тысяч разных адресов.
Почему наивной защиты мало?#
Очевидный ответ — не отвечать на неверный запрос. Закрыть соединение, ничего не отправив. Этого недостаточно, потому что различимо не только содержимое ответа, но и то, как именно соединение закрывается.
Этого недостаточно, и причина тонкая.
Работа, представленная на NDSS в 2020 году, показала: несколько систем, специально спроектированных против зондирования, всё равно различались — не по содержимому ответа, а по поведению сетевого стека при закрытии соединения. Флаги TCP и тайминги закрытия давали достаточно, чтобы отличить их друг от друга и от обычных сервисов.
Иначе говоря: сервер, который правильно молчит на прикладном уровне, выдаёт себя тем, как именно он молчит.
| Что сравнивает зонд | Почему различает |
|---|---|
| Через сколько закрылось соединение | таймаут — характерная константа реализации |
| Какими флагами закрылось | RST против FIN — разные стеки ведут себя по-разному |
| Сколько байт успело прийти до закрытия | выдаёт, сколько парсер успел прочитать |
| Одинаково ли на разные типы мусора | различие само является признаком |
Три требования#
Отсюда вырастают конкретные правила, и все три встречаются в спецификациях зрелых протоколов.
Читать дальше при ошибке. Не завершать соединение в момент обнаружения неверной аутентификации, а продолжать читать. Завершение в характерный момент — сигнал само по себе.
Закрывать консистентно. Одинаковые флаги и тайминги для любого некорректного входа. Различие между «неверный пароль» и «мусор» не должно быть наблюдаемым.
Не раскрывать, сколько прочитано. Спецификация Shadowsocks 2022 прямо требует, чтобы поведение при закрытии не выдавало число потреблённых парсером байт — иначе побайтовая проба находит длину секретного префикса двоичным поиском.
ПЛОХО — оракул длины
зонд: 1 байт мусора → мгновенный RST
зонд: 16 байт мусора → мгновенный RST
зонд: 32 байта мусора → пауза 3 с, потом FIN ← парсер дошёл сюда
длина префикса найдена
ХОРОШО — поведение не зависит от входа
зонд: любой мусор → одинаковое поведение, одинаковый тайминг
Защита от повтора#
Отдельный вектор: захваченное рукопожатие законного пользователя — готовый зонд.
Цензор может воспроизвести записанный обмен и посмотреть, ответит ли сервер так же. Наблюдения показывают, что воспроизведение случается и немедленно, и спустя недели.
Отсюда требование к фильтру повторов: он проверяет и одноразовое значение, и метку времени. Только по времени — не поймает немедленный повтор. Только по одноразовому значению — не переживёт перезапуск сервера.
Смежная тонкость про часы: строгий допуск по времени защищает от повторов лучше, но делает сервер хрупким к расхождению часов. Протоколы, допускающие сдвиг в пределах часа, компенсируют это отдельным кэшем — то есть применяют оба механизма вместе, а не выбирают между ними.
Запасной путь: свой сайт или чужой#
У маскировки под TLS есть развилка, влияющая на устойчивость к зондированию.
| Схема | Что отвечает зонду | Риск |
|---|---|---|
| Свой сайт за тем же адресом | ваш веб-сервер, поведение под контролем | нужен работающий сайт |
| Заимствованный чужой сайт | чужой сервер, поведение вам не подчиняется | смена его политики уводит вас в серый список |
Второй вариант зависит от третьей стороны. Наблюдения за иранской инфраструктурой описывают ведение серого списка по признаку «сервер не ответил как ожидалось» — а ответит ли заимствованный сайт, вы не контролируете.
Практический критерий при выборе цели маскировки: отвечает ли она стабильно и предсказуемо на запрос произвольного клиента. Единичная проверка тут ничего не доказывает — нужна серия.
Что проверить у себя#
Короткий список, проверяемый за один сеанс:
Одинаково ли поведение на разные типы неверного входа. Пустой запрос, случайные байты, обрезанное рукопожатие, корректный префикс с неверным окончанием.
Совпадает ли поведение с эталонным веб-сервером. Сравнивать не «отвечает или нет», а распределение: коды, флаги закрытия, задержки.
Переживает ли фильтр повторов перезапуск. Кэш в памяти обнуляется при рестарте — и окно повтора открывается.
Стабильна ли цель маскировки. Серия запросов, а не один.
Вывод#
Зондирование — вторая половина задачи маскировки, и она про сервер, а не про трафик.
Ключевая формулировка короткая: отсутствие ответа — тоже ответ. Сервер, который молчит характерным образом, различим не хуже, чем сервер, который отвечает характерным баннером.
Цель не в том, чтобы молчать, а в том, чтобы молчать так же, как молчит что-то обычное — и одинаково на всё, что не является законным клиентом.
Термины#
- Активное зондирование - подключение цензора к серверу напрямую с целью определить, что на нём работает.
- Оракул длины - различие в поведении при закрытии, по которому определяется, сколько байт успел прочитать парсер.
- Фильтр повторов - механизм, отвергающий воспроизведение ранее записанного рукопожатия.
FAQ: частые вопросы#
Достаточно ли просто не отвечать?#
Нет. Различимы тайминги и флаги закрытия соединения, поэтому сервер выдаёт себя тем, как именно он молчит.
Зачем фильтру повторов и метка времени, и одноразовое значение?#
Только по времени не ловится немедленный повтор, только по одноразовому значению фильтр не переживает перезапуск сервера.
Свой сайт или чужой в качестве запасного пути?#
Свой. Поведение чужого сервера вам не подчиняется, и смена его политики уводит вас в серый список.
Что читать дальше#
- Как выбирают транспорт
- Почему «выглядит случайно» не значит «выглядит нормально»
- Тихие отказы: когда отвергает сервер
- Пройдите маршрут от настройки до диагностики в VPN-гайдах GigaTap.
- Выберите следующий шаг с помощью помощника VPN start.
- Импорт профиля под конкретное устройство — в хабе настройки клиентов.