Антифрод и прокси: охота за MTU и Window Scale
Содержание
- Как MTU выдает прокси с головой
- TCP Window Scale — цифровой отпечаток
- Как это работает на практике
- Кейс 1: WireGuard и MTU 1420
- Кейс 2: Разные Window Scale на одном IP
- Кейс 3: MTU через IPv6 и туннели
- Как антифрод собирает данные
- Использование на сыром сокете
- Парсим IP и TCP заголовки, извлекаем опции
- Что делать, если нужно обойти детекцию
- Подмена MSS
- Почему это работает
- Итог
Антифрод-системы не дремлют. Они копают глубже, чем просто IP-репутацию. Два параметра на уровне TCP — MTU и Window Scale — превратились в мощные инструменты детекции прокси.
MTU (Maximum Transmission Unit) — размер пакета, который устройство готово принять. TCP Window Scale — множитель окна перегрузки. Эти значения выставляются на уровне ОС. И они уникальны для каждого типа системы.
Как MTU выдает прокси с головой
Стандартный Ethernet MTU — 1500 байт. Но VPN-туннели и прокси добавляют свои заголовки: 20-60 байт на IP, 20 байт на TCP, плюс служебные данные протокола. Итоговый MTU падает до 1400-1460 байт.
Сервер при установке TCP-соединения обменивается MSS (Maximum Segment Size) — это MTU минус заголовки. Клиент шлет свой MSS в SYN-пакете. Антифрод смотрит: если MSS сильно отличается от стандартного 1460 — стоп.
Пример: клиент с MSS 1350. Почему? Потому что за ним стоит прокси на VPS с MTU 1400. Или WireGuard туннель с MTU 1420. Антифрод видит: "О, это не обычный пользователь".
TCP Window Scale — цифровой отпечаток
Window Scale — параметр, который клиент передает в SYN-пакете. Он определяет максимальный размер окна приема (до 1 ГБ). Разные ОС выставляют разные значения по умолчанию:
| ОС | Window Scale | Типичное окно |
|---|---|---|
| Linux 5.x | 7 | 65535 * 128 = 8 МБ |
| Windows 10/11 | 8 | 65535 * 256 = 16 МБ |
| macOS | 6 | 65535 * 64 = 4 МБ |
| Android | 5 | 65535 * 32 = 2 МБ |
Прокси-серверы часто крутятся на Linux. Если антифрод видит Window Scale 7 с MSS 1350 — это прокси. Обычный пользователь с Windows 11 даст Window Scale 8 и MSS 1460.
Как это работает на практике
Клиент -> Прокси -> Сервер. Прокси пересылает SYN от клиента, но может подменить MSS на свой. Или прокси сам выступает как конечная точка TCP — тогда его параметры уходят на сервер.
Пример: curl через прокси с кастомным MTU:
```bash
curl --interface eth0 --mtu 1400 https://example.com
```
На сервере ловим tcpdump:
```bash
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'
```
Видим: MSS 1360, Window Scale 7. Сравниваем с базой — это Linux 5.x на VPS. Не Windows, не macOS. Подозрительно.
Кейс 1: WireGuard и MTU 1420
Проблема: пользователь жалуется, что сайт блокирует его запросы. Причина: он использует WireGuard с MTU 1420. Антифрод видит MSS 1380 — нестандартное значение. Плюс Window Scale 7 — типичный Linux.
Технические детали: WireGuard по умолчанию ставит MTU 1420. 1500 - 20 (IP) - 8 (UDP) - 4 (Type) - 4 (Key) - 8 (Nonce) = 1456. Но многие конфиги режут до 1420. MSS = 1420 - 40 = 1380.
Антифрод заносит MSS 1380 в черный список. Решение: поднять MTU на клиенте до 1500, но это может фрагментировать пакеты. Или использовать TCP MSS clamping на прокси:
```bash
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```
Кейс 2: Разные Window Scale на одном IP
Проблема: антифрод видит, что с одного IP приходят запросы с Window Scale 7 (Linux) и Window Scale 8 (Windows). Это признак прокси — несколько пользователей за одним IP.
Причина: SOCKS5 прокси или HTTP прокси не меняют TCP параметры. Клиенты подключаются к прокси, а прокси создает свои TCP-соединения к серверу. Если прокси на Linux — все соединения получат Window Scale 7. Но если прокси переиспользует соединения — может быть разнобой.
Решение для прокси: форсировать единый Window Scale через sysctl:
```bash
sysctl -w net.ipv4.tcp_rmem='4096 87380 16777216'
sysctl -w net.ipv4.tcp_wmem='4096 65536 16777216'
```
Но это не скроет MTU. Пример: сервер nginx 1.24 с настройками:
```
server {
listen 443 ssl;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1.2 TLSv1.3;
proxy_set_header X-Real-IP \;
}
```
В логах видим: remote_addr один, а User-Agent и Window Scale разные. Антифрод бьет тревогу.
Кейс 3: MTU через IPv6 и туннели
Проблема: провайдер использует 6in4 туннель (IPv6 поверх IPv4). MTU туннеля — 1480. Клиентские пакеты фрагментируются. Антифрод видит MSS 1440 — странно для обычного пользователя.
Причина: 6in4 добавляет 20 байт заголовка IPv4. 1500 - 20 = 1480. MSS = 1480 - 40 = 1440. Плюс IPv6 сам по себе не требует фрагментации, но туннель ее провоцирует.
Антифрод проверяет: если MSS 1440 и при этом клиент шлет IPv6 пакеты — это туннель. Вероятность прокси — 90%. Решение: использовать MTU path discovery на клиенте:
```bash
ping -M do -s 1472 google.com
```
Если не проходит — резать MTU. Но антифрод уже засек аномалию.
Как антифрод собирает данные
Сервер при SYN-пакете читает:
- MSS (TCP option, 4 байта)
- Window Scale (TCP option, 3 байта)
- Timestamp (TCP option, 10 байт)
- SACK permitted (TCP option, 2 байта)
Комбинация этих параметров дает отпечаток TCP/IP стека. Инструмент — p0f или собственные реализации. Пример на Python:
```python
import socket
import struct
def parse_tcp_options(data):
opts = {}
i = 0
while i < len(data):
kind = data[i]
if kind == 0:
break
if kind == 1:
i += 1
continue
length = data[i+1]
if kind == 2: # MSS
opts['mss'] = struct.unpack('!H', data[i+2:i+4])[0]
elif kind == 3: # Window Scale
opts['wscale'] = data[i+2]
i += length
return opts
Использование на сыром сокете
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
packet = s.recv(65535)
Парсим IP и TCP заголовки, извлекаем опции
```
Что делать, если нужно обойти детекцию
Самый простой способ — подменить MSS на прокси. nginx умеет:
```
server {
listen 443 ssl;
proxy_set_header X-Forwarded-For \;
proxy_set_header X-Real-IP \;
proxy_http_version 1.1;
proxy_set_header Connection "";
Подмена MSS
set \ 1460;
proxy_set_header TCP-MSS \;
}
```
Но это только заголовок. Реальная подмена — на уровне iptables:
```bash
iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1460
```
С Window Scale сложнее. Его нельзя подменить через iptables. Нужно модифицировать ядро или использовать DPI-прокси типа nDPI.
Почему это работает
Антифрод не ищет идеальное совпадение. Он ищет аномалии. Если 99% пользователей имеют MSS 1460 и Window Scale 8, а ваш клиент шлет MSS 1380 и Window Scale 7 — вы выпадаете из статистики. Дальше — проверка IP-репутации, поведенческий анализ.
Комбинация MTU + Window Scale дает точность 80-90%. Добавьте сюда Timestamp и SACK — получите 95%+. Прокси, которые не меняют эти параметры, вычисляются за пару запросов.
Итог
MTU и Window Scale — не единственные, но важные индикаторы. Антифрод собирает их при каждом SYN-пакете. Если вы крутите прокси — меняйте MSS на уровне ядра. Или используйте прокси, которые форсят единые TCP-параметры для всех клиентов.
Но помните: это гонка вооружений. Как только вы подмените MSS — антифрод начнет смотреть на что-то еще. Например, на TCP Timestamp или на задержки между пакетами.