Ротация IP через IPv6: как настроить SLAAC и не словить бан по таймауту
Содержание
- Ротация IP через IPv6: как настроить SLAAC и не словить бан по таймауту
- Почему SLAAC, а не DHCPv6
- Как работает генерация адреса
- Настройка ротации через systemd-networkd
- !/bin/bash
- rotate-ipv6.sh
- Проблема с таймаутами
- !/usr/bin/env python3
- MTU и фрагментация
- Кейс: парсер с ротацией каждые 15 секунд
- Кейс: бан по таймауту из-за TCP Fast Open
- Кейс: антифрод по временным меткам
- Проверка работоспособности
- Итог
Ротация IP через IPv6: как настроить SLAAC и не словить бан по таймауту
IPv6-адрес — не приговор. В отличие от IPv4, где провайдер выдаёт один адрес и менять его — квест, здесь у вас целое /64 подсеть. Это 18 квинтиллионов адресов. Хочешь — меняй каждый запрос.
Но есть нюанс. Серверы и антифрод-системы давно научились сканировать подсети. Если вы дёргаете адреса хаотично — получите бан по таймауту. Разберём, как настроить SLAAC правильно и не спалиться.
Почему SLAAC, а не DHCPv6
DHCPv6 — это костыль для тех, кто не понял философию IPv6. Он хранит состояние, ведёт логи, назначает адреса централизованно. SLAAC работает иначе — каждый узел сам генерирует себе адрес из префикса, который рассылает роутер через ICMPv6 Router Advertisement.
Преимущество SLAAC для ротации — скорость. Адрес генерируется локально, без запроса к серверу. Задержка — миллисекунды. DHCPv6 требует round-trip к серверу, что при ротации каждые 10 секунд превращается в ад.
Второй момент — приватность. SLAAC использует алгоритм RFC 7217 для генерации стабильной части адреса. Это значит: сменился префикс — сменился адрес. И никакой привязки к MAC.
Как работает генерация адреса
RFC 7217 — это не просто хеш от MAC. Это хеш от секретного ключа, префикса, network_id и счётчика. Формула:
```
addr = F(prefix, secret_key, network_id, counter)
```
Секретный ключ хранится в системе. Меняете ключ — меняется адрес. При этом привязка к MAC исчезает полностью. Антифрод-системы, которые строят цепочки по OUI производителя сетевой карты, — в пролёте.
В Linux это реализовано в `NetworkManager` через параметр `addr-gen-mode=stable-privacy`. По умолчанию он включён. Но для ротации нужен другой режим — `random`.
Настройка ротации через systemd-networkd
Забудьте про NetworkManager для серьёзных задач. `systemd-networkd` легче, быстрее и управляется текстовыми конфигами.
Создайте файл `/etc/systemd/network/20-eth0.network`:
```
[Match]
Name=eth0
[Network]
DHCP=no
IPv6AcceptRA=yes
[IPv6AcceptRA]
UseDNS=no
UseDomains=no
[Link]
RequiredForOnline=no
```
Теперь ключевой момент — скрипт ротации. Каждые N секунд он меняет секретный ключ и перезапускает интерфейс:
```bash
!/bin/bash
rotate-ipv6.sh
INTERFACE="eth0"
PREFIX_FILE="/run/ipv6-prefix"
while true; do
NEW_SECRET=\$(openssl rand -hex 32)
sysctl -w net.ipv6.conf.\$INTERFACE.addr_gen_mode=1
echo \$NEW_SECRET > /etc/ipv6-secret
systemctl restart systemd-networkd
sleep 30
done
```
Почему 30 секунд? Это оптимальный интервал. Слишком часто — серверы начнут блокировать за аномальную активность. Слишком редко — теряется смысл ротации.
Проблема с таймаутами
Классическая ошибка — ротация адреса при активной TCP-сессии. Вы меняете адрес, а сервер продолжает держать соединение со старым. Через 60-90 секунд — таймаут, соединение рвётся.
Решение — ротация только в момент установки нового соединения. Не рвите активные сессии. Вот скрипт, который делает это правильно:
```python
!/usr/bin/env python3
import socket
import subprocess
import time
def get_current_ipv6():
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
s.connect(("2606:4700:4700::1111", 80))
return s.getsockname()[0]
finally:
s.close()
def rotate_address():
subprocess.run(["sysctl", "-w", "net.ipv6.conf.eth0.addr_gen_mode=1"])
subprocess.run(["systemctl", "restart", "systemd-networkd"])
time.sleep(2)
return get_current_ipv6()
current = get_current_ipv6()
print(f"Current: {current}")
for i in range(10):
time.sleep(5)
new_addr = rotate_address()
print(f"New: {new_addr}")
```
Заметьте паузу в 2 секунды после перезапуска. Без неё вы получите адрес из старой генерации.
MTU и фрагментация
Вот где многие обжигаются. IPv6 не поддерживает фрагментацию на промежуточных маршрутизаторах. Если пакет больше MTU — он просто отбрасывается, а отправитель получает ICMPv6 Packet Too Big.
Стандартный MTU для Ethernet — 1500 байт. Но туннели и VPN снижают его до 1400 и ниже. При ротации адресов вы можете попасть на маршрут с другим MTU.
Проверка:
```bash
ping6 -c 3 -M do -s 1452 2606:4700:4700::1111
```
Если пакеты не проходят — снижайте MTU. Настройка в systemd-networkd:
```
[Link]
MTUBytes=1400
```
Кейс: парсер с ротацией каждые 15 секунд
Пример: парсер на Python, который делает 1000 запросов к API. Каждые 15 секунд — новая сессия с новым адресом.
```python
import aiohttp
import asyncio
import subprocess
async def fetch(session, url):
async with session.get(url) as resp:
return await resp.text()
async def main():
for i in range(100):
if i % 20 == 0:
subprocess.run(["bash", "/opt/rotate.sh"])
async with aiohttp.ClientSession() as session:
data = await fetch(session, "https://api.example.com/data")
print(f"Request {i}: {len(data)} bytes")
asyncio.run(main())
```
Проблема: при ротации каждые 15 секунд DNS-кэш может вернуть старый адрес. Решение — сброс кэша:
```bash
systemd-resolve --flush-caches
```
Кейс: бан по таймауту из-за TCP Fast Open
TCP Fast Open — штука полезная, но опасная при ротации. Клиент отправляет данные в SYN-пакете. Сервер запоминает cookie. Сменился адрес — cookie не совпадает, сервер ждёт повторного SYN. Таймаут.
Отключайте TFO при ротации:
```bash
sysctl -w net.ipv4.tcp_fastopen=0
```
В коде приложения:
```python
import socket
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_FASTOPEN, 0)
```
Кейс: антифрод по временным меткам
Cloudflare и другие CDN отслеживают время жизни адреса. Если адрес живёт меньше 5 минут — помечают как подозрительный. Решение — не ротируйте чаще, чем раз в 60 секунд, и используйте HTTP/2 multiplexing для нескольких запросов в одной сессии.
Пример: 100 запросов через одну сессию HTTP/2:
```python
import httpx
client = httpx.Client(http2=True)
for i in range(100):
resp = client.get("https://api.example.com")
print(resp.status_code)
client.close()
```
Проверка работоспособности
После настройки — тест. Проверяем, что адрес действительно меняется:
```bash
watch -n 5 "curl -6 ifconfig.co"
```
И проверяем отсутствие таймаутов:
```bash
for i in {1..20}; do
curl -6 -s -o /dev/null -w "%{http_code} %{time_total}\n" https://api.example.com
sleep 10
done
```
Если все 20 запросов вернули 200 — ротация работает. Если есть 408 или 504 — ищите проблему в MTU или TCP-настройках.
Итог
SLAAC — мощный инструмент, но требует дисциплины. Настройте интервал ротации, следите за MTU, отключите TCP Fast Open и не рвите активные сессии. Тогда антифрод-системы не заметят вашей активности.
А если нужен готовый прокси-сервер с ротацией — посмотрите на lexic.ml. Там уже всё настроено и проверено годами работы.