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

- Почему IPv6-прокси «фонит» через PTR-запись: как обратная зона DNS раскрывает пул

- Почему IPv6-прокси «фонит» через PTR-запись: как обратная зона DNS раскрывает пул

Что такое PTR и почему он вообще существует

PTR-запись — обратное преобразование IP-адреса в доменное имя. Работает через специальную зону `in-addr.arpa` для IPv4 и `ip6.arpa` для IPv6. Запрос идёт по адресу, записанному в обратном порядке с точками между нибблами (4-битными группами).

Для IPv4 всё просто: `192.0.2.45` → `45.2.0.192.in-addr.arpa`. Для IPv6 — зверски длинно. Адрес `2001:db8:abcd::1` разворачивается в 32 ниббла: `1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa`. Именно эту строку резолвер шлёт в DNS.

Зачем это нужно? Исторически — для диагностики. `traceroute`, логи почтовых серверов, антиспам-фильтры. Сейчас PTR — это в первую очередь сигнал репутации: если у IP нет обратной записи или она указывает на `dynamic-pool-42.isp.example`, любой сервис делает стойку.

Как PTR выдаёт пул

Провайдеры прокси редко заморачиваются с PTR для каждого адреса. Настройка обратной зоны — это делегирование от RIR, потом зона у владельца блока, потом скрипт, который генерирует тысячи записей. Дешевле поставить одну шаблонную запись на весь /64 или /48.

Отсюда типичная картина: клиент приходит на сайт с адресом `2a01:4f8:c17:1a2f::5`, а PTR возвращает `customer-2a01-4f8-c17-1a2f.vps.hosting.example`. Всё, пул раскрыт. Хостер известен, диапазон известен, паттерн известен.

Второй сценарий — PTR вообще нет. Резолвер получает NXDOMAIN или SERVFAIL. Для антифрода это тоже сигнал: живой eyeball-адрес почти всегда имеет PTR от провайдера (Ростелеком, МТС, Comcast, Deutsche Telekom). Отсутствие PTR у IPv6-адреса — нетипично для конечного пользователя, зато типично для датацентра и прокси-фермы.

Почему IPv6 фонит сильнее IPv4

С IPv4 всё устоялось: пулы огромные, адреса переиспользуются годами, PTR часто рандомизирован или отсутствует у мелких провайдеров. IPv6-блоки выдаются крупными префиксами (/32, /48, /64), и провайдеры поначалу лепили PTR по одной схеме на весь блок.

Пример: сервер на nginx 1.24 с проверкой через `ngx_http_realip_module` и GeoIP2 показал, что из 5000 запросов с IPv6-адресов одного /48-префикса 4600 имели PTR вида `*.static.provider.example`. Один шаблон — весь пул на ладони.

Плюс сказывается длина адреса. IPv6-адрес сам по себе несёт информацию: префикс /32 говорит о провайдере, /48 — о площадке, /64 — о конкретной подсети. Даже без PTR по одному адресу можно прикинуть, откуда ноги растут. PTR добавляет к этому человекочитаемое имя.

Как это ловят на практике

Три уровня проверки, которые встречаются в антифрод-системах и WAF.

Первый — прямой DNS-запрос PTR при заходе. Дорого по latency (20–80 мс), поэтому кэшируют. Второй — офлайн-обогащение логов: раз в сутки прогоняют базу IP через PTR и строят карту «префикс → паттерн». Третий — сравнение PTR с rDNS-именем, которое клиент отдаёт в TLS SNI или HTTP-заголовках (редко, но бывает).

Вот как выглядит ручная проверка пула через `dig`:

```bash

!/bin/bash

for i in \$(seq 1 20); do

addr=\$(printf "2a01:4f8:c17:1a2f::%x" "\$i")

nibbles=\$(echo "\$addr" | sed 's/://g' | rev | sed 's/./&./g')

ptr=\$(dig +short -x "\$addr" @1.1.1.1)

echo "\$addr -> \${ptr:-NXDOMAIN}"

done

```

Прогон по 20 адресам из одной /64 покажет, одинаковая ли схема именования. Если 18 из 20 вернули `*.vps.hosting.example` — пул палится одним взглядом.

Что видит сайт: заголовки и цепочка

Сайт получает IP из TCP-соединения. За обратным прокси — из `X-Forwarded-For` или `Forwarded`. Дальше приложение (или edge-функция) делает PTR-запрос. В логах Cloudflare, к примеру, поле `ClientASN` и `ClientIP` уже есть, а PTR подтягивается отдельным воркером.

Типичная цепочка проверки на бэкенде:

```python

import dns.resolver

import dns.reversename

def enrich(ip: str) -> dict:

rev = dns.reversename.from_address(ip)

try:

answers = dns.resolver.resolve(rev, "PTR", lifetime=1.5)

names = [str(r.target).rstrip(".") for r in answers]

except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer,

dns.resolver.LifetimeTimeout):

names = []

return {

"ip": ip,

"ptr": names,

"suspicious": not names or any(

kw in n for n in names

for kw in ("vps", "proxy", "static", "dynamic", "pool", "hosting")

),

}

```

Таймаут 1.5 секунды — компромисс. Меньше — теряем медленные резолверы, больше — пользователь ждёт на пустом месте. Результат кэшируют в Redis на 6–24 часа: PTR меняется редко.

Кейс: парсинг маркетплейса через IPv6-пул

Задача — собирать цены с площадки, которая блокирует по IP. Взяли пул /64 у провайдера, 500 адресов. Через сутки — бан 90% адресов.

Причина: у всего /64 стоял PTR `node-{index}.proxyfarm.example`. Антифрод-система площадки резолвила PTR при первом заходе, увидела общий суффикс, сгруппировала по нему и забанила префиксом. Один шаблон — 500 адресов в мусор.

Решение: разнесли пул по нескольким /48 разных провайдеров, для каждого адреса завели PTR, имитирующий eyeball-имена (`broadband-{hash}.isp-{n}.example`), часть адресов оставили вообще без PTR — как у мобильных операторов. Бан упал до 15%. Оставшиеся баны — по поведенческим факторам, не по DNS.

Кейс: утечка через SNI и PTR вместе

Сервис на nginx 1.24 с TLS-терминацией. Клиенты ходили через IPv6-прокси. В логах заметили корреляцию: адреса с PTR `*.ddos-guard.example` и `*.ovh.example` давали одинаковый JA3-отпечаток и одинаковый порядок HTTP/2-заголовков.

Причина: прокси-провайдер не менял TLS-стек между адресами. PTR подтвердил, что все адреса — из одной фермы, а JA3 показал, что и клиентское ПО одно. Два независимых сигнала сложились в один вывод.

Решение со стороны провайдера — рандомизировать PTR и TLS-фрейминг по адресам. Со стороны сервиса — не блокировать по одному PTR, но понижать trust-score при совпадении PTR-паттерна с известными фермами. На практике это дало снижение ложных срабатываний на 40%: реальные пользователи за CGNAT мобильных операторов тоже имеют шаблонные PTR, но у них другой TLS-профиль.

Кейс: PTR отсутствует — и это палит

Обратная история. Прокси-сервис настроил пул так, что PTR не было вообще. Расчёт был на «нет записи — нет информации». Вышло наоборот.

Антифрод-правило: если IPv6-адрес не имеет PTR и при этом не принадлежит известному eyeball-диапазону (проверка по ASN мобильных и residential-провайдеров) — повысить риск. Мобильные операторы почти всегда имеют PTR на IPv6. Датацентры — часто нет. Отсутствие PTR у адреса из хостинг-ASN — красный флаг.

Решение: завели PTR для 80% адресов, оставив «дыры» в паттерне для правдоподобия. Для residential-имитации использовали имена вида `{hex}.dynamic.{isp}.example`, для мобильных — `{hex}.mobile.{operator}.example`. Разница в латентности DNS при этом нулевая, а детект по отсутствию PTR перестал срабатывать.

Как проверить свой пул на «фон»

Минимальный чек-лист перед запуском.

Прогнать 30–50 адресов из пула через `dig -x` и глазами посмотреть на паттерны. Если больше половины имён имеют общий суффикс или общий префикс-шаблон — пул светится. Проверить, что PTR не содержит слов `proxy`, `vpn`, `vps`, `hosting`, `static`, `pool`, `node`, `farm`. Сверить ASN через `whois -h whois.cymru.com` — если весь пул в одной ASN хостинга, это тоже сигнал.

Второй шаг — проверить, что PTR резолвится быстро и стабильно. Если ваш DNS-провайдер отдаёт NXDOMAIN с задержкой 2 секунды, антифрод-система на той стороне получит таймаут и занесёт адрес в серую зону. Третье — сверить forward-confirmed reverse DNS (FCrDNS): PTR должен резолвиться обратно в тот же IP. Несовпадение — ещё один флаг.

Настройка PTR на своей зоне

Если у вас делегирован блок (например, /48 от хостера), обратную зону настраиваете сами. У хостера запрашиваете делегирование `ip6.arpa`-зоны для вашего префикса, дальше — обычные PTR-записи в вашем DNS.

Пример зоны BIND для /64 `2001:db8:abcd:1::/64`:

```

\$ORIGIN 1.0.0.0.d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.

\$TTL 3600

@ IN SOA ns1.example. hostmaster.example. (2024010101 7200 3600 1209600 300)

@ IN NS ns1.example.

@ IN NS ns2.example.

1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR broadband-a1b2.isp-example.net.

2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR broadband-c3d4.isp-example.net.

```

TTL 3600 — разумный дефолт. Меньше ставить смысла нет: PTR меняется редко, а лишние запросы бьют по резолверам. Больше — риск, что при смене пула старые записи будут висеть в кэшах сутки.

Что делать, если PTR у чужого пула

Если вы арендуете IPv6 у провайдера и не контролируете обратную зону — попросите делегирование или хотя бы кастомизацию PTR. Многие хостеры дают это в панели. Если не дают — меняйте хостера. Пул без контроля PTR — это пул, который светится чужим шаблоном.

Проверка простая: `dig -x <ваш_ip> +short`. Если вернулось что-то вроде `host-123-45.provider.example` и вы не можете это изменить — считайте, что вас опознали. Для скрейпинга, тестов, сбора данных это критично. Для внутренних задач — по барабану.

И последнее. PTR — не единственный канал утечки, но самый дешёвый для того, кто вас проверяет. DNS-запрос стоит копейки, кэшируется, работает без вашего участия. Если пул не продуман на этом уровне, остальные меры — рандомизация отпечатков, ротация User-Agent, распределение по ASN — работают вполсилы. Начните с PTR, дальше проще.

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