← Назад в базу знаний

Как антифрод-системы маркетплейсов вычисляют IPv6 прокси по поведенческому fingerprint

Как антифрод-системы маркетплейсов вычисляют IPv6 прокси по поведенческому fingerprint

Что вообще ловит антифрод

Маркетплейсы (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 забаненных аккаунтов.

✔️Купить прокси