Как антифрод-системы вычисляют прокси по MTU и MSS: разбор на уровне пакетов
Содержание
- TCP-рукопожатие как отпечаток пальца
- Как выглядит нормальный MSS
- Кейс: nginx и странный MSS
- PMTUD и его грабли
- Кейс: ICMP-тишина на IPv6
- TCP timestamps и их аномалии
- Кейс: разрыв в последовательности
- TTL и его искажение
- Кейс: TTL=64 на Windows
- Window Scale и его странности
- Кейс: Window Scale=0 на macOS
- Как защититься от детекта
- Итог
TCP-рукопожатие как отпечаток пальца
Антифрод-системы не гадают на кофейной гуще. Они анализируют TCP-пакеты. Самый простой способ определить прокси — посмотреть на MSS (Maximum Segment Size) в SYN-пакете.
MSS — это параметр TCP-рукопожатия. Клиент отправляет SYN, в котором указывает максимальный размер сегмента данных. Обычно это MTU минус 40 байт (20 байт IP-заголовка + 20 байт TCP-заголовка). Для Ethernet MTU=1500, значит MSS=1460.
Прокси-серверы меняют этот параметр. Особенно IPv6-прокси. Почему? Потому что IPv6-заголовок больше — 40 байт вместо 20. Плюс опциональные расширения. Итоговый MTU тоннеля может быть меньше стандартного.
Пример: клиент за прокси с MTU 1280 (минимальный для IPv6). MSS будет 1280 - 40 (IPv6) - 20 (TCP) = 1220. Сервер видит SYN с MSS=1220 и сразу понимает — трафик идёт через туннель.
Как выглядит нормальный MSS
Разные сети дают разные значения. Вот реальные цифры:
| Тип подключения | MTU | MSS | Примечание |
|----------------|-----|-----|------------|
| Ethernet | 1500 | 1460 | Стандарт |
| PPPoE | 1492 | 1452 | Домашние сети |
| VPN (OpenVPN) | 1500 | 1450-1460 | Зависит от оверхеда |
| IPv6-прокси | 1280-1500 | 1220-1460 | Диапазон |
| Мобильный 4G | 1500 | 1430-1460 | Иногда меньше |
Проблема в том, что прокси часто используют фиксированное значение MSS. Например, все клиенты одного прокси-провайдера шлют SYN с MSS=1452. Это выдаёт их с головой.
Кейс: nginx и странный MSS
Берём сервер на nginx 1.24. Логи tcpdump показывают SYN с MSS=1452. Провайдер клиента — обычный PPPoE. Но трафик приходит не напрямую, а через CDN. CDN использует IPv6-прокси.
Почему MSS=1452? PPPoE добавляет 8 байт заголовка. MTU снижается до 1492. MSS = 1492 - 40 (IPv6) - 20 (TCP) = 1432. Но tcpdump показывает 1452.
Разгадка: прокси-сервер CDN переписывает MSS. Он берёт значение для Ethernet (1460) и вычитает 8 байт PPPoE. Получает 1452. Но не учитывает, что сам работает через IPv6-туннель.
Антифрод-система видит: SYN приходит с IP, принадлежащим CDN, но MSS не соответствует стандартному для Ethernet. Вывод — трафик идёт через прокси.
PMTUD и его грабли
Path MTU Discovery — механизм, который определяет максимальный размер пакета на всём пути. Работает через флаг DF (Don't Fragment) и ICMP-сообщения "Fragmentation Needed".
Прокси-серверы часто ломают PMTUD. Почему? Потому что они меняют IP-адреса. Клиент отправляет пакет с DF=1 через прокси. Прокси получает ICMP-ответ от промежуточного маршрутизатора, но не передаёт его клиенту. Клиент продолжает слать большие пакеты, которые теряются.
Антифрод-системы отслеживают это. Если клиент не получает ICMP-сообщения при нормальном MTU, значит трафик идёт через прокси, который фильтрует ICMP.
Пример: сервер с MTU 1500. Клиент шлёт пакет 1500 байт. Прокси с MTU 1280 не может передать такой пакет. Он либо фрагментирует (если DF=0), либо отбрасывает (если DF=1). В любом случае — аномалия.
Кейс: ICMP-тишина на IPv6
Клиент использует IPv6-прокси от lexic.ml. Сервер пытается отправить пакет 1500 байт. Прокси имеет MTU 1280. Сервер получает ICMPv6 "Packet Too Big" с новым MTU=1280.
Клиент уменьшает размер пакетов. Всё работает. Но антифрод-система замечает: клиент слишком быстро адаптируется. Обычные пользователи не меняют MSS мгновенно. Прокси-клиенты — да, у них это встроено в софт.
Дополнительный признак: ICMPv6-сообщения приходят с IP-адреса, который не принадлежит ни одному маршрутизатору на пути. Это IP прокси. Антифрод видит несоответствие.
TCP timestamps и их аномалии
Опция TCP timestamps в SYN-пакете — ещё один маркер. Прокси-серверы часто модифицируют или добавляют эту опцию.
Нормальный клиент может не отправлять timestamps. Прокси — почти всегда отправляет. Почему? Потому что ему нужно синхронизировать два TCP-соединения: с клиентом и с сервером.
Антифрод-системы проверяют: если SYN содержит timestamps, а последующие пакеты нет — это подозрительно. Или наоборот: SYN без timestamps, а ACK с ними.
Кейс: разрыв в последовательности
Клиент отправляет SYN без опции timestamps. Прокси добавляет её на лету. Сервер отвечает SYN-ACK с timestamps. Клиент не поддерживает timestamps. Прокси вынужден удалить их из ответа перед отправкой клиенту.
Антифрод-система видит: SYN-ACK содержит опцию timestamps, но клиентский ACK — нет. Несоответствие. Плюс клиент не учитывает timestamp в расчёте RTT. Это тоже видно.
Пример: curl с опцией `--tcp-nodelay` на клиенте. Прокси добавляет timestamps. Сервер отвечает. Клиент игнорирует timestamps. Антифрод вычисляет разницу.
TTL и его искажение
Time To Live — простой, но эффективный маркер. Каждый маршрутизатор уменьшает TTL на 1. Прокси-сервер может менять TTL в пакетах.
Начальное значение TTL зависит от ОС:
- Windows: 128
- Linux: 64
- macOS: 64
- Cisco: 255
Прокси обычно устанавливает TTL=64 или 128. Если клиент с Windows (TTL=128) идёт через прокси, который уменьшает TTL до 64, сервер видит несоответствие.
Антифрод-система анализирует: TTL пакета не соответствует количеству хопов до клиента. Если до клиента 10 хопов, а TTL=54 (64-10), это нормально для Linux. Но если TTL=118 (128-10), а клиент использует Linux — аномалия.
Кейс: TTL=64 на Windows
Клиент с Windows 10 (TTL=128) использует прокси. Прокси на Linux (TTL=64). Сервер видит TTL=54 (64 - 10 хопов). Антифрод проверяет fingerprint ОС по другим параметрам (Window Scale, MSS, SACK) и определяет Windows.
Несоответствие: Windows с TTL=54. Вывод — трафик идёт через прокси.
Решение для прокси: не менять TTL, а передавать оригинальное значение. Но это сложно, если прокси сам является точкой маршрутизации.
Window Scale и его странности
Опция Window Scale в SYN-пакете определяет множитель для окна TCP. Прокси-серверы часто меняют это значение.
Нормальные значения: 7 (множитель 128), 8 (256), 9 (512). Прокси могут ставить 0 или 1 — это редкость для современных ОС.
Антифрод-системы проверяют: Window Scale соответствует fingerprint ОС. Если клиент с Linux (обычно 7-9) имеет Window Scale=0 — это прокси.
Кейс: Window Scale=0 на macOS
Клиент на macOS 12 (Window Scale=3 по умолчанию) использует прокси. Прокси устанавливает Window Scale=0. Сервер видит: SYN с Window Scale=0, но fingerprint macOS.
macOS никогда не использует Window Scale=0. Это невозможно. Вывод — трафик изменён.
Прокси делает это, чтобы уменьшить оверхед. Но антифрод-системы давно знают такие трюки.
Как защититься от детекта
Полностью скрыть прокси невозможно. Но можно усложнить детект:
1. **Не менять MSS**. Передавать оригинальное значение от клиента.
2. **Не добавлять опции**. Если клиент не отправляет timestamps — не добавлять их.
3. **Сохранять TTL**. Передавать оригинальное значение, уменьшая на 1 только за себя.
4. **Не фильтровать ICMP**. Передавать все ICMP-сообщения клиенту.
5. **Использовать правильный Window Scale**. Соответствовать fingerprint клиента.
Пример настройки nginx для сохранения MSS:
```nginx
stream {
upstream backend {
server 192.168.1.10:443;
}
server {
listen 443;
proxy_pass backend;
proxy_protocol on;
set_real_ip_from 10.0.0.0/8;
real_ip_header proxy_protocol;
}
}
```
Но даже это не гарантирует защиту. Антифрод-системы анализируют сотни параметров. Один прокси-сервер может быть вычислен по комбинации MSS+Window Scale+TTL+timestamps.
Итог
Антифрод-системы вычисляют прокси на уровне TCP-пакетов. MSS, PMTUD, timestamps, TTL, Window Scale — каждый параметр может выдать прокси.
Прокси-серверы изменяют сетевые параметры. Это неизбежно. Вопрос только в том, насколько хорошо они это делают.
lexic.ml с 2015 года решает эти проблемы. Но идеального решения нет. Каждый новый трюк антифрода требует нового ответа от провайдеров прокси.
Главный совет: если используете прокси — проверяйте его fingerprint. curl с опцией `--verbose` покажет все параметры SYN-пакета. Анализируйте, сравнивайте с нормальными значениями. И помните: антифрод-системы тоже читают эту статью.