Как антифрод-системы маркетплейсов детектируют IPv6 прокси по поведенческим паттернам сессии
Содержание
- Почему IPv6 вообще стал удобен для прокси
- Что такое поведенческий отпечаток сессии
- Тайминги: где IPv6-прокси выдаёт себя с потрохами
- Порядок навигации и глубина просмотра
- TLS и HTTP/2 фингерпринты поверх IPv6
- Часовые пояса и локаль против IP-геолокации
- Кейс: маркетплейс на nginx 1.24 и всплеск IPv6-сессий
- Кейс: подмена User-Agent и провал на canvas-хеше
- Кейс: одна /64, разные города, одинаковый ритм
- Что делать, если вы на стороне прокси
- Итог
Антифрод маркетплейсов давно перестал смотреть только на IP. Адрес — это лишь входной фильтр. Настоящая охота начинается на уровне поведения: как сессия двигается, где залипает, чем пахнет её тайминг. IPv6 тут даёт прокси-провайдерам красивую легенду — адрес уникален, пул огромен, репутация чистая. Но поведение врёт редко.
Дальше — про то, как именно маркетплейсы ловят IPv6-прокси по паттернам, а не по чёрным спискам.
Почему IPv6 вообще стал удобен для прокси
IPv4-пулы выжжены. Датацентровые диапазоны AWS, Hetzner, DigitalOcean, OVH сидят в репутационных базах годами. Антифрод видит /24 и сразу заворачивает. С IPv6 иначе: провайдер получает /48 или /64, и это 65 536 адресов минимум. Каждая сессия может уйти с нового адреса.
Плюс геолокация по IPv6 работает хуже. Базы GeoIP для v6 заполнены дырами, особенно на уровне города. Маркетплейс видит ASN, страну — и всё. Точный регион часто unknown.
Но у этого есть обратная сторона. Роутинг IPv6 в датацентрах обычно однородный: весь /64 приходит из одной стойки, одного маршрутизатора, с одинаковым RTT до точки присутствия. И вот это уже палево.
Что такое поведенческий отпечаток сессии
Поведенческий отпечаток — это набор метрик, снятых с живого пользователя за время сессии. Не статичных, а меняющихся. Антифрод собирает их через JS-телеметрию, логи сервера, иногда через WebRTC и TLS-фингерпринт.
Ключевые группы метрик:
- тайминги между запросами (inter-request intervals)
- порядок и скорость навигации по страницам
- движение мыши, скролл, фокус на элементах
- набор запросов к API относительно UI-действий
- консистентность часов, локали, шрифтов, canvas-хеша
По отдельности каждая метрика шумная. Вместе они дают вектор, который у живого юзера и у бота различается статистически значимо.
Тайминги: где IPv6-прокси выдаёт себя с потрохами
Человек не может кликать каждые 1.2 секунды ровно. Дисперсия человеческих интервалов огромна — от 200 мс до 30 секунд, с длинными паузами на чтение. Бот, даже с рандомизацией, часто даёт слишком узкое распределение.
Возьмём реальный пример. Python-скрипт с `time.sleep(random.uniform(1, 3))` даёт интервалы с σ ≈ 0.58 с. Живой пользователь на карточке товара показывает σ ≈ 4–8 с из-за пауз на чтение. Антифрод считает коэффициент вариации (CV = σ/μ). У бота CV < 0.5, у человека CV > 0.8. Порог простой, ловит на раз.
Ещё хуже — синхронность между сессиями. Если 50 IPv6-адресов из одного /64 показывают одинаковый тайминг-паттерн с точностью до 50 мс, это не пятьдесят людей. Это один скрипт.
```python
import time, statistics
intervals = []
last = time.time()
for _ in range(200):
do_request()
now = time.time()
intervals.append(now - last)
last = now
time.sleep(1.5)
mu = statistics.mean(intervals)
sigma = statistics.pstdev(intervals)
print(f"CV = {sigma/mu:.3f}") # ниже 0.5 — красный флаг
```
Порядок навигации и глубина просмотра
Живой покупатель на маркетплейсе ведёт себя нелинейно. Открывает категорию, возвращается, идёт в поиск, снова в категорию, открывает карточку, читает отзывы, закрывает, возвращается через день. Бот идёт по линейному маршруту: главная → категория → карточка → корзина.
Антифрод строит граф переходов. У бота он почти детерминированный, энтропия низкая. У человека — рваный, с петлями и тупиками.
Отдельный маркер — отсутствие referer-цепочек внутри SPA. Если маркетплейс на React, все переходы идут через `history.pushState`, и referer не меняется. Но антифрод смотрит на XHR-запросы: у человека они привязаны к видимым элементам, у бота — к прямым вызовам API без предшествующего рендера.
TLS и HTTP/2 фингерпринты поверх IPv6
IPv6-адрес сам по себе не выдаёт прокси. Выдаёт JA3/JA4-хеш. Если 5000 сессий с разных /128 внутри одного /48 дают одинаковый JA4 — это один клиент.
Смотри таблицу типичных расхождений:
| Метрика | Живой Chrome 126 | Python requests | curl 8.7 |
|---|---|---|---|
| JA4 | t13d1516h2_... | t13d1713h2_... | t13d1517h2_... |
| HTTP/2 SETTINGS | 6 полей, порядок A | 4 поля, порядок B | 5 полей, порядок C |
| ALPN | h2,http/1.1 | http/1.1 | h2,http/1.1 |
| Header order | sec-ch-ua первым | Host первым | Host первым |
Маркетплейс может не блокировать, но помечает сессию. Через 20 минут такой сессии прилетает капча — и вот тут поведение бота ломается окончательно.
Часовые пояса и локаль против IP-геолокации
Прокси на IPv6 из Франкфурта, а `Intl.DateTimeFormat().resolvedOptions().timeZone` в браузере — `Europe/Moscow`. Это классика. Антифрод сверяет три источника: IP-гео, таймзону JS, `Accept-Language`.
Расхождение на одну зону — подозрительно. На две и больше — почти гарантированный прокси. IPv6 тут усугубляет: GeoIP для v6 часто возвращает страну датацентра, а не реального клиента.
Ещё один маркер — время отклика. Если RTT до сервера 4 мс, а таймзона клиента говорит «Сибирь» — физика против легенды. Свет по оптоволокну идёт ~5 мкс на километр, Москва–Франкфурт это минимум 20 мс в одну сторону.
Кейс: маркетплейс на nginx 1.24 и всплеск IPv6-сессий
Проблема: за три дня число сессий с IPv6 выросло с 3% до 22% от общего трафика. Конверсия в заказ — 0.1% против 2.3% у IPv4. Капчи проходились, но корзины пустели.
Причина: парсеры цен запускались с прокси-пула через /48. Каждая сессия — новый /128, но все из одного ASN и с одинаковым TLS-фингерпринтом.
Технические детали: nginx 1.24 логировал `\$remote_addr`, `\$http_user_agent`, `\$request_time`. Анализ показал: 78% сессий имели `request_time` в диапазоне 40–60 мс с σ = 3 мс. У живых — 80–1200 мс с σ = 240 мс. Плюс все запросы шли без `Referer` внутри каталога, что для SPA-навигации ненормально.
Решение: nginx-конфиг с rate-limit по /64 и дополнительной проверкой заголовков:
```nginx
limit_req_zone \$binary_remote_addr zone=per_ip:10m rate=5r/s;
limit_req_zone \$ipv6_prefix zone=per_prefix:10m rate=50r/s;
map \$remote_addr \$ipv6_prefix {
~^(?
default \$remote_addr;
}
server {
listen [::]:443 ssl http2;
location /api/ {
limit_req zone=per_ip burst=10 nodelay;
limit_req zone=per_prefix burst=30 nodelay;
proxy_pass http://backend;
}
}
```
Плюс на бэкенде добавили проверку CV таймингов и рассинхрон таймзоны. Через неделю доля IPv6 упала до 4%, конверсия выровнялась.
Кейс: подмена User-Agent и провал на canvas-хеше
Проблема: сессии с IPv6 показывали свежий Chrome 126 в UA, но фейлили проверку WebGL и canvas.
Причина: прокси-клиент подделывал только заголовок. Реальный движок был headless Chromium 118 с дефолтными рендеринг-параметрами.
Технические детали: canvas-хеш у headless Chromium 118 совпадает с таковым у 118 в headful-режиме, но отличается от Chrome 126. Разница в антиалиасинге шрифтов и subpixel-рендеринге. WebGL vendor показывал `Google SwiftShader` вместо `Intel Inc.` или `NVIDIA Corporation`.
Решение: антифрод добавил правило — при расхождении UA и canvas-хеша старше двух мажорных версий сессия получает score +40 и уходит на усиленную проверку. Прокси-провайдеру пришлось обновлять профили браузеров.
Кейс: одна /64, разные города, одинаковый ритм
Проблема: 200 аккаунтов с IPv6-адресами, заявленных как разные города России. Все — с одной /64.
Причина: прокси-пул выдавал адреса из одного префикса, а легенда строилась на GeoIP-базе с рандомными городами.
Технические детали: RTT до маркетплейса у всех сессий — 12–14 мс. Для Новосибирска это физически невозможно (минимум 50 мс до Москвы). Плюс jitter одинаковый, что говорит об одном канале. `traceroute6` показал идентичные первые 8 хопов.
Решение: маркетплейс ввёл корреляцию RTT и заявленной геолокации. Отклонение больше 30% — блок. Прокси-провайдер, который хочет жить, вынужден либо разносить пулы по реальным ASN, либо честно указывать один регион.
Что делать, если вы на стороне прокси
Если вы используете IPv6-прокси для легальных задач — мониторинг цен, тестирование, региональные проверки — нужно маскировать не только IP, но и поведение.
Базовые шаги:
- рандомизировать тайминги с тяжёлым хвостом (log-normal, не uniform)
- подделывать не только UA, но и JA4, HTTP/2 SETTINGS, порядок заголовков
- синхронизировать таймзону, локаль и Accept-Language с GeoIP
- разносить сессии по разным /48, а не /128 внутри одной
- добавлять «человеческие» паузы на чтение и движение мыши
Без этого даже идеальный IPv6-адрес с чистой репутацией будет пойман за пару часов. Поведение — единственное, что нельзя подделать одним заголовком.
Итог
Антифрод маркетплейсов в 2024–2025 смотрит на IPv6 как на один из сигналов, а не как на вердикт. Решают поведенческие метрики: CV таймингов, энтропия навигации, консистентность фингерпринта, физика RTT. Прокси-провайдеры, которые это понимают, выживают. Те, кто продаёт «чистые IPv6» без работы над профилем, кормят своих клиентов банами. Кстати, на lexic.ml пул адресов раздаётся с привязкой к реальным ASN и гео, что снимает часть проблем с RTT — но поведение всё равно остаётся на стороне клиента.