Как антифрод-системы маркетплейсов вычисляют IPv6 прокси по поведенческому fingerprint
Содержание
- Что вообще ловит антифрод
- Почему IPv6 сам по себе не панацея
- TLS-фингерпринт: JA3, JA4, Akamai
- HTTP/2 и порядок заголовков
- Тайминги TCP и MTU
- Поведенческий fingerprint
- Как IPv6-прокси связываются между собой
- Пример: как это выглядит в логах
- Кейс: маркетплейс электроники, 3000 аккаунтов
- Кейс: доставка еды, региональные промо
- Кейс: B2B-закупки, парсинг цен
- Что делать, если ты на другой стороне
- Инструменты для проверки себя
Что вообще ловит антифрод
Маркетплейсы (Ozon, Wildberries, Amazon, eBay) держат антифрод-системы, которые смотрят не на один параметр, а на связку. IP — только верхушка. Под ним лежит TLS-фингерпринт, HTTP/2-параметры, тайминги TCP, порядок заголовков, поведение мыши, ритм запросов. IPv6-прокси решает проблему «одна подсеть на тысячу аккаунтов», но не решает проблему «один и тот же клиент под тысячей личин».
Дальше — как именно палится IPv6-прокси, даже когда адреса выглядят как настоящие клиентские.
Почему IPv6 сам по себе не панацея
IPv6-адресов 2^128. Казалось бы, бери /64 на аккаунт и живи спокойно. Проблема в другом: провайдеры выдают /56 или /48 на абонента, а антифрод знает префиксы крупных дата-центров и VPS-хостеров. Если у тебя /64 из блока Hetzner или OVH — это уже красный флаг, даже если каждый адрес уникален.
Вторая засада — BGP-анонсы. Антифрод строит карту: какой ASN анонсирует префикс, как давно, сколько адресов реально светится в трафике. Residential-прокси через мобильных операторов идут с ASN оператора, а датацентровые — с ASN хостера. Разница видна за секунду.
Третья — обратный DNS. У residential-подсетей PTR-записи часто вида `dynamic-xxx.cust.isp.net`. У прокси-ферм — либо нет PTR, либо он шаблонный.
TLS-фингерпринт: JA3, JA4, Akamai
Клиент при TLS-handshake отправляет ClientHello с набором шифров, расширений, эллиптических кривых, порядком всего этого. Собери хеш — получишь JA3. У Chrome 120 один JA3, у curl другой, у Python requests третий.
Антифрод сравнивает JA3 с заявленным User-Agent. Если UA говорит «Chrome 121 на Windows», а JA3 — от Go-клиента, это палево. Прокси-серверы часто не пересобирают TLS, а просто туннелируют. Тогда JA3 идёт от клиента, и если клиент — это requests, всё видно.
JA4 пошёл дальше — учитывает ALPN, SNI, версии. Akamai fingerprint добавляет порядок псевдозаголовков HTTP/2. Всё это собирается в один вектор.
```python
import tls_client
session = tls_client.Session(
client_identifier="chrome_120",
random_tls_extension_order=True
)
r = session.get("https://example.com")
print(r.status_code)
```
Библиотека `tls_client` эмулирует реальный JA3 Chrome. Голый `requests` спалится моментально.
HTTP/2 и порядок заголовков
HTTP/2 multiplexing даёт ещё один слой. Заголовки в HPACK сжимаются, но порядок псевдозаголовков (`:method`, `:authority`, `:scheme`, `:path`) фиксирован спецификацией. А вот обычные заголовки — нет. Chrome отправляет их в одном порядке, Firefox в другом, curl в третьем.
Антифрод парсит фреймы и строит хеш. Плюс смотрит на приоритеты потоков (priority frames), размеры window update, наличие server push. У автоматизированных клиентов эти параметры часто дефолтные и одинаковые.
Ещё одна деталь — `SETTINGS` фрейм. У Chrome `MAX_CONCURRENT_STREAMS=1000`, `INITIAL_WINDOW_SIZE=6291456`. У curl другие значения. Расхождение с UA — маркер.
Тайминги TCP и MTU
Антифрод измеряет RTT до клиента, окно TCP, опции (SACK, timestamps, window scaling). Датацентровые прокси обычно имеют RTT 1-5 мс до ближайшего маркетплейсового edge. Residential — 20-80 мс. Мобильные — 40-150 мс с джиттером.
Если аккаунт заявляет «домашний интернет из Москвы», а RTT до сервера в Москве 2 мс — это дата-центр. Если RTT стабильный как часы без джиттера — тоже подозрительно.
MTU в IPv6 минимум 1280 байт. Провайдеры часто ставят 1500, туннели — 1480 или меньше. Прокси-фермы с GRE-туннелями показывают 1476, 1400, 1380. Это косвенный, но рабочий маркер.
Поведенческий fingerprint
Самое интересное. Антифрод смотрит не на один запрос, а на серию. Метрики:
- интервал между запросами (у бота — ровный, у человека — рваный)
- порядок навигации (человек заходит на главную, потом в категорию, потом в товар)
- движение мыши (у headless Chrome — линейное или отсутствует)
- время на странице (у бота — 200 мс, у человека — 3-15 секунд)
- скроллы, клики, hover
- заполнение форм: пауза между полями, backspace, автокоррекции
Собери это в вектор и обучи градиентный бустинг. Точность на нормальных данных — 95%+.
Как IPv6-прокси связываются между собой
Ключевой момент: антифрод ищет не отдельный прокси, а кластер. Признаки:
- одинаковый JA3 у «разных» аккаунтов
- одинаковый порядок HTTP/2-заголовков
- одинаковые тайминги TCP (RTT ±2 мс)
- одинаковый MTU
- совпадающие /64-префиксы в течение суток
- синхронные всплески активности
Если 50 аккаунтов с разных IPv6 имеют один JA3 и один HTTP/2 fingerprint — это одна ферма. Неважно, что IP разные.
Пример: как это выглядит в логах
Сервер на nginx 1.24 с `\$http2` и `\$ssl_curves` в логах. Плюс модуль для JA3.
```nginx
log_format fp '\$remote_addr - \$remote_user [\$time_local] '
'"\$request" \$status \$body_bytes_sent '
'ja3=\$http_ja3 ja4=\$http_ja4 '
'alpn=\$ssl_alpn_protocol h2=\$http2';
server {
listen 443 ssl http2;
ssl_protocols TLSv1.3;
access_log /var/log/nginx/fp.log fp;
}
```
Смотрим логи за час. Видим 200 запросов с 200 разных IPv6. Но `ja3` у всех один, `h2` одинаковый, `alpn` — `h2`. Это не 200 клиентов, это один клиент с 200 адресами. Блокируем всю /64-подсеть и добавляем JA3 в чёрный список.
Кейс: маркетплейс электроники, 3000 аккаунтов
Проблема: ферма из 3000 аккаунтов заказывала товары с промо-скидками, потом перепродавала. Прокси — residential IPv6 через пул из 20000 адресов. Каждый аккаунт — свой /128.
Причина палева: все аккаунты использовали один и тот же билд Selenium с Chrome 118. JA3 совпадал, порядок HTTP/2-заголовков совпадал, MTU 1480 (туннель). Антифрод сгруппировал по этим признакам за 6 часов и забанил 2800 аккаунтов.
Решение: пересадили на `curl_cffi` с эмуляцией JA3 Chrome 121, добавили рандомизацию порядка заголовков через mitmproxy-аддон, подняли MTU до 1500 (убрали GRE). Плюс ввели поведенческие задержки. Выживаемость выросла с 7% до 60%.
Кейс: доставка еды, региональные промо
Проблема: ферма аккаунтов ловила промокоды «первый заказ». Прокси — IPv6 через мобильных операторов, /64 на аккаунт. RTT 60-90 мс, всё выглядело как настоящие мобильные клиенты.
Причина: тайминги запросов были ровные — 800 мс между шагами. У реальных пользователей разброс 500-4000 мс. Плюс отсутствовали события touch/scroll. Антифрод построил распределение и отрезал всё, что попадало в узкий пик.
Решение: добавили гауссовский шум к задержкам, эмулировали touch-события через CDP, разбросали время сессии. Плюс стали ротировать /64 каждые 4 часа, а не на каждый аккаунт. Забанили меньше половины.
Кейс: B2B-закупки, парсинг цен
Проблема: клиент парсил цены 500 конкурентов через IPv6-прокси. Каждый запрос — новый /128. Получал 403 через 10 минут.
Причина: TLS-фингерпринт от Go-клиента (`net/http`), UA — Chrome. Несовпадение. Плюс HTTP/2 SETTINGS с дефолтными значениями Go, которые отличаются от Chrome. Антифрод просто сравнил два хеша.
Решение: перешли на `tls_client` с `chrome_120`, добавили заголовки в правильном порядке, синхронизировали SETTINGS. Скорость упала с 50 rps до 8 rps, но выживаемость выросла до 90%. Через lexic.ml настроили ротацию /64 с привязкой к ASN residential-провайдеров — стало ещё лучше.
Что делать, если ты на другой стороне
Если строишь антифрод — не смотри на IP отдельно. Строй граф: узлы — аккаунты, рёбра — совпадение JA3, JA4, HTTP/2 fingerprint, MTU, ASN, таймингов. Кластеризуй. Один аккаунт с уникальным фингерпринтом — норм. Двадцать с одинаковым — ферма.
Если обходишь — рандомизируй всё, что можно. JA3, порядок заголовков, тайминги, поведение. Не используй один билд браузера на всю ферму. Ротируй /64, но не привязывай адрес к аккаунту навсегда. Следи за MTU.
Инструменты для проверки себя
- `https://tls.browserleaks.com/json` — покажет JA3, JA4, Akamai hash
- `https://http2.pro/` — HTTP/2 fingerprint
- `p0f` — пассивный фингерпринт TCP
- Wireshark с фильтром `tls.handshake.type == 1` — ClientHello
- `curl -v --http2 https://example.com` — посмотреть SETTINGS
Проверяй себя перед тем, как антифрод проверит тебя. Разница в 5 минут диагностики и 500 забаненных аккаунтов.