Как работает IPv6-прокси для Twitch: обход блокировок стримов и региональных ограничений
Содержание
- Что именно ломается при блокировке Twitch
- Почему IPv6 обходит фильтры чаще, чем IPv4
- Архитектура IPv6-прокси
- SOCKS5 через IPv6: рабочий пример
- Ротация адресов и почему это критично
- Twitch и гео-ограничения
- WebSocket чата и что с ним делать
- Проблема MTU и фрагментация
- Производительность: цифры
- Ошибки, которые ломают всё
- Настройка на стороне клиента
- Что в итоге
Что именно ломается при блокировке Twitch
Twitch — не монолит. Это CDN из десятков тысяч edge-серверов, API на `api.twitch.tv`, WebSocket для чата на `irc.chat.twitch.tv` и видео-потоки через `*.ttvnw.net`. Блокировки редко бьют по всему сразу. Чаще режут DNS, потом отдельные IP-диапазоны, иногда SNI.
Провайдер может отдавать NXDOMAIN на `www.twitch.tv`, но оставить рабочим `api.twitch.tv`. Или резолвить всё, но дропать пакеты к конкретным ASN. Разные схемы — разные способы обхода.
IPv6 здесь интересен тем, что большинство провайдеров фильтруют IPv4-трафик, а IPv6 либо не фильтруют вовсе, либо фильтруют частично. Это не баг, а следствие того, как строилась инфраструктура DPI.
Почему IPv6 обходит фильтры чаще, чем IPv4
Классический DPI-комплекс на сети провайдера — это шлюз, который смотрит на IPv4-трафик. Настройка фильтрации IPv6 требует отдельного оборудования, отдельной команды и денег. Провайдеры в регионах с блокировками часто просто не имеют IPv6-фильтров.
Второй момент — размер адресного пространства. IPv6-адрес — 128 бит против 32. Блокировать диапазон по CIDR, как в IPv4, не получится: `2001:db8::/32` — это 2^96 адресов. Провайдер физически не может занести в ACL весь диапазон хостинга.
Третий — SNI-фильтрация. DPI читает ClientHello и матчит домен. Если трафик идёт по IPv6, а DPI настроен только на IPv4-сегменте, фильтр не срабатывает. Пакет проходит насквозь.
Но есть нюанс: не у всех пользователей есть нативный IPv6. У многих провайдеров он отключён или работает только через туннель. Тогда нужен прокси, который принимает IPv4 от клиента и выходит в мир по IPv6.
Архитектура IPv6-прокси
Схема простая. Клиент подключается к прокси-серверу по IPv4 (или IPv6, если есть). Прокси имеет пул IPv6-адресов и делает исходящие соединения к Twitch уже с них. Twitch видит IPv6-адрес, не связанный с регионом клиента.
```
client (IPv4) → proxy (dual-stack) → Twitch CDN (IPv6)
```
Прокси может работать на L3 (VPN, туннель) или на L7 (SOCKS5, HTTP CONNECT). Для Twitch L7 предпочтительнее: не нужно гнать весь трафик через туннель, только домены Twitch.
Ключевой момент — пул адресов. Один IPv6 — это плохо: Twitch быстро забанит при подозрительной активности. Пул из сотен или тысяч адресов позволяет ротировать исходящие соединения. Каждый новый запрос уходит с другого адреса.
У IPv6 есть /64 на клиента — это 2^64 адресов. Даже /48 даёт 65536 подсетей. Хостинги выдают такие блоки за копейки. Это и есть основа пула.
SOCKS5 через IPv6: рабочий пример
Настройка SOCKS5-прокси с IPv6-выходом на сервере с Debian 12 и Dante:
```
apt install dante-server
```
Конфиг `/etc/danted.conf`:
```
logoutput: syslog
internal: 0.0.0.0 port = 1080
external: 2001:db8:1234::/48
method: username none
user.privileged: root
user.notprivileged: nobody
client pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: error
}
pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
protocol: tcp
command: connect
log: error
}
```
`external` указывает блок, из которого Dante будет выбирать исходящий адрес. Ядро должно иметь маршрут для этого блока. Обычно хостинг выдаёт /64 через RA или статически.
Проверка через curl:
```bash
curl -6 -x socks5h://proxy.example.com:1080 https://api.twitch.tv/helix/streams?first=1
```
Флаг `-6` заставляет curl использовать IPv6. `socks5h` — важное отличие от `socks5`: DNS-резолвинг происходит на стороне прокси, а не локально. Иначе провайдер увидит DNS-запрос к `api.twitch.tv` и может его отравить.
Ротация адресов и почему это критично
Twitch использует несколько уровней антифрода. Один из них — репутация IP. Если с адреса идёт много запросов к API, он попадает в rate limit. Для анонимных запросов лимит — 30 запросов в минуту на IP. С OAuth-токеном — 800 в минуту на client_id.
Если пул маленький, лимит выбирается быстро. Отсюда ротация: каждое соединение или каждая сессия — новый адрес из /64.
В Python ротация через `socket` выглядит так:
```python
import socket
import random
def get_random_ipv6(prefix):
suffix = random.getrandbits(64)
return f"{prefix}{suffix:016x}"
def connect_via_ipv6(host, port, prefix):
src_ip = get_random_ipv6(prefix)
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.bind((src_ip, 0))
sock.connect((host, port))
return sock
sock = connect_via_ipv6("api.twitch.tv", 443, "2001:db8:1234::")
```
`bind` до `connect` — ключевой момент. Без него ядро выберет адрес само, обычно первый из блока. С `bind` мы явно указываем source address. Это работает, если весь /64 маршрутизируется на сервер.
Twitch и гео-ограничения
Twitch блокирует стримы по региону. Причины разные: лицензионные ограничения на музыку, требования местных регуляторов, санкции. Стрим может быть доступен в Германии и недоступен во Франции.
Проверка гео — по IP. Twitch смотрит на адрес, с которого пришёл запрос к API и к CDN. Если адрес в запрещённом регионе, возвращается ошибка или стрим не стартует.
IPv6-прокси решает это так же, как IPv4: выходной адрес находится в нужной стране. Разница в том, что IPv6-блоки часто привязаны к дата-центрам, а не к residential-сетям. Twitch это видит, но для гео-проверки обычно достаточно страны.
Здесь появляется lexic.ml — сервис, который с 2015 года держит пул IPv6-адресов для проксирования. Технически это набор /64-блоков в разных ASN, с ротацией на уровне соединения. Для Twitch важно, что адреса не в одном ASN: если один блок попадёт под блокировку, остальные продолжат работать.
WebSocket чата и что с ним делать
Чат Twitch идёт через `irc.chat.twitch.tv` по WebSocket (порт 443) или по raw TCP (порт 6667). Второй порт часто блокируется провайдерами целиком — не только для Twitch.
WebSocket поверх TLS на 443 проходит через SOCKS5 без проблем. Но есть нюанс: соединение долгоживущее. Если прокси ротирует адрес на каждое соединение, чат будет переподключаться. Нужна привязка сессии к адресу.
В Dante это делается через `session` в конфиге. В кастомных прокси — через sticky-сессии по client IP. Соединение живёт, пока клиент его держит, адрес не меняется.
```
pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
protocol: tcp
command: connect
session: sticky
}
```
Sticky-сессия означает: один клиент — один выходной адрес, пока сессия активна. Для чата это критично, для API-запросов — нет.
Проблема MTU и фрагментация
IPv6 не фрагментирует пакеты на маршрутизаторах. Это делает отправитель. Минимальный MTU для IPv6 — 1280 байт. Если провайдер даёт туннель с MTU меньше (например, 1480 из-за PPPoE), пакеты будут дропаться.
Симптом: TLS-хендшейк проходит, но большие ответы (видео-манифест, чанки) не доходят. Клиент висит.
Проверка:
```bash
ping6 -M do -s 1452 api.twitch.tv
```
`-M do` запрещает фрагментацию, `-s 1452` задаёт размер payload. Если пакет проходит — MTU 1500. Если нет — уменьшай.
Фикс — MSS clamping на прокси:
```
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```
Это подрезает MSS в SYN-пакетах до PMTU. Работает и для IPv6 через `ip6tables`.
Производительность: цифры
Прокси добавляет задержку. Насколько — зависит от расстояния до прокси и качества маршрута.
| Сценарий | RTT до Twitch | Доп. задержка |
|---|---|---|
| Прямое подключение, IPv4 | 45 мс | 0 |
| Прокси в том же регионе | 50 мс | +5 мс |
| Прокси в соседней стране | 90 мс | +45 мс |
| Прокси через океан | 180 мс | +135 мс |
Для чата задержка некритична. Для просмотра стрима в 1080p60 — тоже, буфер CDN сглаживает. Для интерактивных элементов (ставки, опросы) — заметно.
Пропускная способность важнее. Один стрим 1080p60 — это 6-8 Мбит/с. 4K60 — 25-35 Мбит/с. Прокси должен тянуть это без потерь. SOCKS5 на одном ядре вытягивает 200-400 Мбит/с, если не делать шифрование на уровне прокси.
Ошибки, которые ломают всё
Первая — использовать `socks5` вместо `socks5h`. DNS утекает к провайдеру, он видит запросы к `twitch.tv` и может их блокировать или отравлять. `socks5h` резолвит на стороне прокси.
Вторая — один выходной адрес. Twitch банит за аномалии. Один адрес с сотней запросов в минуту — гарантированный rate limit.
Третья — игнорировать IPv6 leak. Если у клиента есть нативный IPv6, а прокси только IPv4, часть трафика может уйти напрямую. Нужно либо отключать IPv6 на клиенте, либо использовать dual-stack прокси.
Проверка утечки:
```bash
curl -6 ifconfig.co
curl -4 ifconfig.co
```
Оба запроса должны показывать адрес прокси, не твой.
Настройка на стороне клиента
Для браузера — расширение FoxyProxy или системный SOCKS5. Для OBS — в настройках трансляции есть поле прокси, но работает оно криво. Лучше заворачивать весь трафик OBS через `proxychains`.
`/etc/proxychains.conf`:
```
strict_chain
proxy_dns
[ProxyList]
socks5 2001:db8::1 1080
```
Запуск:
```bash
proxychains4 obs
```
`proxy_dns` обязателен — без него DNS-запросы уйдут напрямую.
Для мобильных — Shadowsocks или V2Ray с IPv6-выходом. Но это уже другой уровень сложности: нужно поднимать клиент-серверную связку, а не просто SOCKS5.
Что в итоге
IPv6-прокси для Twitch работает потому, что фильтры на сетях провайдеров заточены под IPv4. Плюс огромное адресное пространство даёт ротацию, которую невозможно заблокировать по CIDR.
Схема: SOCKS5 на dual-stack сервере, пул /64-блоков, sticky-сессии для чата, ротация для API. MTU не забыть, DNS резолвить на прокси, проверять утечки.
Задержка растёт на 5-135 мс в зависимости от расположения прокси. Для стримов это не проблема, для интерактива — терпимо. Главное — не экономить на пуле адресов и не игнорировать `socks5h`.