Как антифрод-системы вычисляют прокси по RTT и TCP window scaling
Содержание
- RTT: что это и почему оно важно
- Измеряем RTT до сервера
- Смотрим мин/ср/макс — разброс должен быть > 5 мс для реального пользователя
- TCP window scaling: скрытый отпечаток пальца
- Извлекаем window scale из TCP-опций SYN-пакета
- Реальный парсер сложнее, но суть понятна
- Пример: сравниваем window scale клиента и прокси
- Как антифрод собирает данные
- Проверяем RTT до разных географических точек
- Если разброс < 20 мс — вы через прокси
- Window scaling в комбинации с другими параметрами
- Кейс: как Netflix ловил прокси через RTT
- Кейс: прокси с фиксированным window scale
- Кейс: двойной прокси и RTT-коллапс
- Как защититься от детекта по RTT и window scale
- Добавляем случайный jitter 5-15%
- Пример для прокси-сервера
- Почему это всё не работает на 100%
Антифрод-системы давно перестали полагаться только на IP-репутацию. Они копают глубже — прямо в TCP-стек. RTT и window scaling — два параметра, которые выдают прокси быстрее, чем вы успеете сказать "Hello".
RTT: что это и почему оно важно
RTT (Round-Trip Time) — время, за которое пакет доходит до сервера и обратно. Для обычного пользователя с прямым соединением это значение стабильно. Домашний интернет даёт RTT 10-50 мс до локального сервера, 100-200 мс до европейского.
Прокси добавляет лишний прыжок. Пакет идёт: клиент → прокси → целевой сервер → прокси → клиент. Каждый прыжок — дополнительные миллисекунды. Но фишка не в абсолютных значениях — их легко подделать. Фишка в **вариативности**.
У реального пользователя RTT колеблется в пределах 5-15% от среднего. Загрузка канала, расстояние до вышки, погода — всё влияет. Прокси же даёт подозрительно ровный RTT. Плюс-минус 1-2 мс от запроса к запросу. Слишком идеально для реального мира.
```bash
Измеряем RTT до сервера
ping -c 10 target-server.com
Смотрим мин/ср/макс — разброс должен быть > 5 мс для реального пользователя
```
TCP window scaling: скрытый отпечаток пальца
TCP window scaling — параметр, определяющий размер окна перегрузки. Он передаётся при установке соединения в SYN-пакете. Каждая ОС и даже версия ядра использует своё значение.
Windows 10 — window scale 8 (фактор 256). Linux 5.x — window scale 7 (фактор 128). macOS — window scale 3 (фактор 8). Прокси-серверы чаще всего крутятся на Linux с дефолтными настройками. Если у клиента Windows, а window scale говорит о Linux — тревога.
Но антифрод смотрит не только на абсолютное значение. Он анализирует **dynamic window scaling** — как меняется окно при перегрузке. Реальный пользователь адаптируется: уменьшает окно при потерях, увеличивает при свободном канале. Прокси часто держит окно константным или меняет слишком резко.
```python
import socket
import struct
def get_window_scale(packet):
Извлекаем window scale из TCP-опций SYN-пакета
Реальный парсер сложнее, но суть понятна
tcp_options = packet[20:40]
for i in range(len(tcp_options)):
if tcp_options[i] == 3: # Window Scale option
return tcp_options[i+1]
return None
Пример: сравниваем window scale клиента и прокси
client_ws = get_window_scale(client_syn)
proxy_ws = get_window_scale(proxy_syn)
if client_ws != proxy_ws:
print("Подозрительно: window scale не совпадает")
```
Как антифрод собирает данные
Системы вроде Cloudflare Bot Management или PerimeterX не ждут, пока вы что-то сделаете. Они встраивают JavaScript-сниффер, который собирает TCP-метрики на этапе рукопожатия. Без вашего ведома.
Сервер отправляет клиенту специальный пакет с timestamp. Замеряет время ответа. Повторяет 3-5 раз. Строит профиль RTT. Если профиль совпадает с известными прокси-провайдерами — бан.
Дополнительно проверяют **RTT до разных IP**. Прокси часто маршрутизирует весь трафик через один выходной узел. RTT до сервера в США и до сервера в Европе у прокси-пользователя будет почти одинаковым. У реального — разница в 50-100 мс.
```bash
Проверяем RTT до разных географических точек
for target in "us-server.com" "eu-server.com" "asia-server.com"; do
ping -c 3 \ | tail -1 | awk '{print \\$4}'
done
Если разброс < 20 мс — вы через прокси
```
Window scaling в комбинации с другими параметрами
Один параметр — плохой детектор. Комбинация — смертельное оружие. Антифрод строит **fingerprint** из 10-15 TCP-параметров:
- MSS (Maximum Segment Size) — обычно 1460 для Ethernet, 1400 для PPPoE
- TTL (Time To Live) — 128 для Windows, 64 для Linux
- SACK permitted — есть не у всех ОС
- Timestamps — включаются не везде
Прокси обычно форвардит TCP-параметры клиента как есть. Но некоторые настройки (например, TTL) прокси меняет. Клиент отправляет TTL=128, прокси уменьшает до 64. Антифрод видит: TTL=64, но window scale от Windows. Несостыковка.
| Параметр | Реальный пользователь (Windows) | Прокси (Linux) |
|----------|--------------------------------|----------------|
| TTL | 128 | 64 |
| Window scale | 8 | 7 |
| MSS | 1460 | 1460 (часто) |
| SACK | Да | Да |
| Timestamps | Да | Нет (если отключено) |
Кейс: как Netflix ловил прокси через RTT
Netflix использовал простую схему. Они замеряли RTT до CDN-серверов. Если пользователь в Москве показывал RTT 5 мс до немецкого сервера — это прокси. Нормальный RTT Москва-Франкфурт — 40-50 мс.
Проблема: некоторые прокси начали эмулировать задержку. Добавляли случайные 30-50 мс к каждому пакету. Netflix ответил: они начали анализировать **jitter** — вариацию задержки. Эмулировать человеческий jitter (5-15%) сложно. Прокси давали либо 0%, либо >30%.
Кейс: прокси с фиксированным window scale
Один провайдер прокси (не будем тыкать пальцем) использовал кастомную сборку Linux с window scale 8 — как у Windows. Думали, что обманули систему. Но антифрод заметил: window scale не меняется при перегрузке. У реального пользователя окно плавает. У прокси — статика.
Решение: пришлось патчить ядро, добавлять случайные флуктуации window scale. Но это породило новую проблему — window scale начал меняться слишком хаотично, что тоже выглядит подозрительно.
Кейс: двойной прокси и RTT-коллапс
Схема: клиент → прокси-1 (Россия) → прокси-2 (Нидерланды) → целевой сервер. Ожидалось, что RTT будет суммой задержек. Но антифрод заметил странность: RTT до сервера в США оказался меньше, чем до сервера в Германии. Физически это невозможно.
Оказалось, прокси-2 маршрутизировал трафик через CDN, который кешировал ответы. RTT до США падал до 10 мс из-за кеша. Антифрод засёк аномалию: RTT не соответствует географическому расстоянию.
Как защититься от детекта по RTT и window scale
Полностью не защититься. Антифроды становятся умнее. Но можно снизить риск:
1. **Эмулировать человеческий jitter**. Добавлять случайную задержку 5-15% от базового RTT. Не константную — нормально распределённую.
2. **Использовать несколько выходных узлов**. Один узел на регион. RTT до разных серверов должен различаться.
3. **Патчить window scale**. Не использовать дефолтные значения. Менять их динамически в зависимости от нагрузки.
4. **Не использовать дешёвые прокси**. Они обычно имеют характерные TCP-профили. Дорогие — эмулируют реальных пользователей.
```python
import random
import time
def emulate_human_rtt(base_rtt):
Добавляем случайный jitter 5-15%
jitter = base_rtt * random.uniform(0.05, 0.15)
if random.random() > 0.5:
jitter = -jitter
return base_rtt + jitter
Пример для прокси-сервера
for request in range(100):
current_rtt = emulate_human_rtt(40) # базовый RTT 40 мс
time.sleep(current_rtt / 1000)
```
Почему это всё не работает на 100%
Антифрод тоже не дураки. Они знают про эти трюки. Поэтому добавляют **поведенческий анализ**. Если TCP-профиль идеален, но поведение пользователя ботовое — бан всё равно придёт.
RTT и window scale — лишь часть пазла. Реальная защита — мимикрия под реального пользователя на всех уровнях: TCP, HTTP, JavaScript, мышь, скролл.
Но если ваш прокси даёт RTT = 5 мс до сервера за 10 000 км — вы уже в базе. Даже не пытайтесь.