Pinterest через IPv6 прокси: парсинг и почему IPv6 не поддерживается на www
Содержание
Почему Pinterest ломается на IPv6
Pinterest — один из тех сервисов, где IPv6 формально есть, но работает через одно место. Проверяем:
```bash
dig AAAA pinterest.com +short
dig AAAA www.pinterest.com +short
```
Первая команда вернёт адрес из диапазона 2600:1f18::/33 (AWS us-east-1). Вторая — пустоту. Именно тут начинается боль: основной домен отдаёт AAAA-запись, а www — нет. И это не случайность, а осознанное решение инфраструктурной команды.
Причина в том, как устроен фронтенд. www.pinterest.com сидит за CDN, которая исторически настроена на IPv4-only для определённых регионов. Apex-домен резолвится в балансировщики AWS, у которых IPv6 включён по умолчанию. Отсюда рассинхрон: клиент думает, что IPv6 доступен, стучится по нему, а получает таймаут или редирект на IPv4-эндпоинт.
Что реально отдаёт DNS
Смотрим глубже. Запрос AAAA к разным поддоменам:
```bash
for h in pinterest.com www.pinterest.com api.pinterest.com ru.pinterest.com; do
printf "%-25s " "\$h"
dig AAAA \$h +short | head -1 || echo "no AAAA"
done
```
Типичный вывод на момент проверки:
| Хост | AAAA-запись | Поведение |
|------|-------------|-----------|
| pinterest.com | 2600:1f18:... | отвечает по IPv6 |
| www.pinterest.com | — | только IPv4 |
| api.pinterest.com | 2600:1f18:... | отвечает, но с ограничениями |
| ru.pinterest.com | — | только IPv4 |
Разница между apex и www — не баг, а следствие миграции. Основной домен перевели на dual-stack в 2021-м, а www оставили на legacy-конфиге CDN. За три года никто не почесался, потому что IPv4-трафик всё ещё доминирует.
Как парсить, если IPv6 отваливается
Классический сценарий: у вас пул IPv6-прокси, вы хотите дёргать Pinterest. Половина запросов к www падает с `Connection timed out` через 30 секунд. Решение — форсить IPv4 для www и IPv6 для остального.
На Python с `requests` это выглядит так:
```python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.connection import allowed_gai_family
import socket
class ForceIPv4(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
kwargs['socket_options'] = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
super().init_poolmanager(*args, **kwargs)
def send(self, request, **kwargs):
host = request.url.split('/')[2]
if host.startswith('www.'):
original = allowed_gai_family
allowed_gai_family = lambda: socket.AF_INET
try:
return super().send(request, **kwargs)
finally:
allowed_gai_family = original
return super().send(request, **kwargs)
session = requests.Session()
session.mount('https://', ForceIPv4())
r = session.get('https://www.pinterest.com/resource/BaseSearchResource/get/')
```
Хак с `allowed_gai_family` — единственный способ заставить urllib3 игнорировать AAAA. Monkey-patching глобального символа выглядит уродливо, но работает стабильно на urllib3 1.26 и 2.x.
Прокси-слой: где IPv6 даёт преимущество
Если www не поддерживает IPv6, зачем вообще IPv6-прокси для Pinterest? Ответ в объёме адресов. У IPv4-пула на 1000 адресов вы упрётесь в rate limit за пару часов. У IPv6-подсети /64 — 18 квинтиллионов адресов, и Pinterest не может банить по /64 целиком, потому что под одним префиксом сидят легитимные пользователи.
Рабочая схема: IPv6-прокси для api.pinterest.com (там AAAA есть) и IPv4-выход для www. Если используете lexic.ml, у них в пуле есть оба типа, можно ротировать по хосту.
```bash
curl -6 -x http://[2001:db8::1]:8080 \
'https://api.pinterest.com/v3/search/pins/?query=design' \
-H 'User-Agent: Mozilla/5.0' \
--max-time 15
curl -4 -x http://192.0.2.10:8080 \
'https://www.pinterest.com/resource/BaseSearchResource/get/' \
-H 'User-Agent: Mozilla/5.0' \
--max-time 15
```
Второй запрос уйдёт по IPv4, потому что www просто не примет IPv6-соединение. Первый — по IPv6, и это даёт вам ровно тот адресный запас, ради которого всё затевалось.
Тайминги и MTU
IPv6-соединение к Pinterest имеет одну неприятную особенность: MTU. AWS-эндпоинты часто отдают ICMPv6 «Packet Too Big» с MTU 1400, а не 1500. Если у вашего прокси Path MTU Discovery сломан, крупные ответы (JSON на 50-100 КБ) будут зависать.
Проверка:
```bash
ping6 -M do -s 1372 pinterest.com
ping6 -M do -s 1452 pinterest.com
```
Первая команда проходит, вторая возвращает `Message too long`. Значит PMTU = 1400. На прокси-сервере нужно выставить:
```bash
ip link set dev eth0 mtu 1400
sysctl -w net.ipv6.conf.eth0.accept_ra_mtu=1
```
Без этого вы получите рандомные таймауты на 10% запросов. Не потому что Pinterest блокирует, а потому что пакеты молча теряются.
Ротация и rate limit
Pinterest считает лимиты по комбинации IP + fingerprint. IPv6-адрес из /64 меняется мгновенно, но fingerprint остаётся. Если крутить только адрес, бан прилетит через 200-300 запросов.
Пример: сервер на Python 3.11 с `curl_cffi` 0.6.2, ротация IPv6 каждые 50 запросов, TLS-фингерпринт фиксированный (Chrome 120). Результат — 1800 успешных запросов до первого 429. С ротацией фингерпринта тоже — 8000+.
```python
from curl_cffi import requests
import random
def pick_proxy():
suffix = random.randint(1, 65535)
return f"http://user:pass@[2001:db8::{suffix:x}]:8080"
for i in range(1000):
proxy = pick_proxy() if i % 50 == 0 else proxy
r = requests.get(
'https://api.pinterest.com/v3/search/pins/',
params={'query': 'interior'},
proxies={'https': proxy},
impersonate='chrome120',
timeout=20,
)
```
Смена `impersonate` раз в 200 запросов добавляет ещё запас. Комбинация IPv6 + JA3-ротация держит сессию живой часами.
Заголовки, которые Pinterest проверяет
IPv6-адрес сам по себе ничего не решает, если заголовки палят автоматизацию. Pinterest смотрит на `X-Forwarded-For`, `X-Real-IP`, `CF-Connecting-IP` и сверяет с реальным source IP. Если через IPv6-прокси вы шлёте заголовок с IPv4-адресом — мгновенный флаг.
Правильно: либо не слать эти заголовки вообще, либо слать тот же IPv6, с которого идёт соединение.
```bash
curl -6 -x http://[2001:db8::a]:8080 \
'https://api.pinterest.com/v3/search/pins/?query=x' \
-H 'X-Forwarded-For: 2001:db8::a' \
-H 'Accept-Language: en-US,en;q=0.9' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Sec-Fetch-Mode: cors'
```
Согласованность заголовков и source IP — базовое требование. Без неё любой прокси, хоть IPv4, хоть IPv6, сгорит за минуты.
Что делать с www
Три рабочих подхода, каждый со своими граблями.
Первый — форсить IPv4 только для www, как в примере выше. Просто, но теряете адресный пул на этом хосте.
Второй — использовать `ru.pinterest.com` и другие региональные поддомены, где AAAA иногда есть. Нестабильно, зависит от региона.
Третий — ходить через мобильное API (`api.pinterest.com` с мобильным User-Agent). Там IPv6 работает стабильно, rate limit мягче, но структура ответов другая и часть эндпоинтов закрыта.
Комбинация: 70% трафика на api.pinterest.com по IPv6, 30% на www по IPv4. Такой микс даёт максимальную пропускную способность без банов.
Итог по инфраструктуре
Pinterest — классический пример «IPv6 есть, но не везде». Apex-домен и API поддерживают, www — нет. Парсер должен уметь переключаться на уровне хоста, а не глобально. PMTU 1400 на IPv6-пути — обязательная настройка, иначе теряете пакеты. Ротация адреса без ротации фингерпринта бесполезна. Заголовки должны совпадать с source IP, иначе любой прокси палится за минуты.