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

- Почему IPv6-прокси на мобильных сетях "умирает" после перезагрузки телефона: разбор привязки адреса к сессии

- Почему IPv6-прокси на мобильных сетях

Что происходит при перезагрузке

Телефон уходит в ребут. Мобильный оператор снимает сессию. Адрес из пула IPv6, который был выдан устройству, освобождается. Через 30-90 секунд после включения телефон получает новый префикс — и весь прокси-туннель, привязанный к старому адресу, превращается в тыкву.

Проблема не в прокси как таковом. Проблема в том, что мобильные сети раздают IPv6 динамически, а привязка "один абонент — один адрес" держится ровно столько, сколько живёт PD-сессия (Prefix Delegation). Ребут, авиарежим, переключение между LTE и Wi-Fi — и префикс меняется.

Статическая привязка прокси к IPv6-адресу на мобильном устройстве — это архитектурный костыль. Работает до первого разрыва сессии.

Как оператор выдаёт IPv6

Мобильный оператор использует DHCPv6-PD. Устройству отдаётся префикс /64 (иногда /56 для роутеров). Внутри префикса телефон генерирует свой интерфейсный адрес через SLAAC — обычно по схеме RFC 7217 (стабильный opaque IID) или privacy extensions (RFC 4941), где адрес меняется каждые несколько часов.

Ключевой момент: сама сеть /64 привязана к P-GW (Packet Gateway) и к сессии абонента в HSS. Перезагрузка телефона → отсоединение от eNodeB → разрыв GTP-туннеля → P-GW освобождает префикс. Всё, что было привязано к этому /64, мертво.

Тайминги примерно такие: разрыв сессии — 2-5 секунд, повторная регистрация в сети — 3-15 секунд, выдача нового префикса — ещё 1-3 секунды. Итого окно неработоспособности 10-25 секунд. Но если прокси-клиент не умеет переподключаться — он висит мёртвым до ручного перезапуска.

Почему SOCKS5-прокси ломается молча

Классический сценарий: на телефоне поднят клиент, который коннектится к прокси-серверу через IPv6. Прокси-сервер видит source address клиента и запоминает его для маршрутизации обратного трафика. После ребута телефона source address другой — но TCP-сессия уже разорвана, и клиент пытается переподключиться.

Если прокси-сервер настроен на whitelist по IPv6 — новый адрес не в списке. Соединение отклоняется. Клиент молчит, потому что ошибка уходит в лог, а не в UI.

Пример: nginx 1.24 в режиме stream-прокси с `allow` по IPv6:

```nginx

stream {

upstream backend {

server 10.0.0.5:8080;

}

server {

listen [::]:1080;

allow 2001:db8:abcd:12::/64;

deny all;

proxy_pass backend;

}

}

```

Телефон перезагрузился, получил префикс `2001:db8:abcd:99::/64` — и всё, `deny all`. В логах `stream` видно `client ... forbidden`. Пользователь видит "прокси не работает" и идёт перезагружать телефон ещё раз.

Случай с оператором, который меняет префикс каждые 4 часа

Некоторые операторы (особенно в сегменте MVNO) крутят PD-сессии агрессивно. Пример из практики: виртуальный оператор в Восточной Европе выдавал /64 с lease time 14400 секунд (4 часа). По истечении — принудительный re-DHCP, даже без ребута устройства.

Что это значит для прокси: если клиент не отслеживает смену адреса через netlink — он продолжает слать пакеты со старым source address. Ядро либо дропает их (адрес уже не на интерфейсе), либо шлёт с новым адресом, но прокси-сервер видит несовпадение с сессией.

Диагностика на стороне клиента (Linux/Android shell):

```bash

ip -6 monitor address dev rmnet_data0

```

Это даёт поток событий при смене адреса. Дальше — скрипт, который дёргает переподключение прокси при `Deleted` или `New` для global-адреса. Без этого мониторинга клиент живёт в иллюзии, что адрес стабилен.

Как выглядит правильная привязка

Привязывать прокси к IPv6-адресу клиента — тупик. Привязывать нужно к устойчивому идентификатору: токену, UUID устройства, сертификату. IPv6-адрес — это транспорт, а не identity.

Схема, которая работает: клиент при старте проходит аутентификацию по токену (например, через WireGuard с preshared key или через HTTP-заголовок с JWT), прокси-сервер выдаёт внутренний IP из пула (можно IPv4, можно ULA-префикс fd00::/8), и весь трафик маршрутизируется по этому внутреннему адресу. Смена внешнего IPv6 не ломает ничего.

Пример конфига WireGuard на сервере, где peer идентифицируется ключом, а не адресом:

```ini

[Interface]

Address = fd00:proxy::1/64

ListenPort = 51820

PrivateKey = SERVER_PRIVATE_KEY

[Peer]

PublicKey = CLIENT_PUBLIC_KEY

AllowedIPs = fd00:proxy::2/128

PersistentKeepalive = 25

```

Клиент после ребута поднимает туннель с тем же публичным ключом — сервер обновляет endpoint (новый IPv6:port) и продолжает работу. Внутренний адрес `fd00:proxy::2` не меняется. Прокси-логика видит стабильный идентификатор.

Именно так работает lexic.ml — привязка идёт к ключу, а не к сетевому адресу. Смена префикса на стороне оператора не рвёт логическую сессию.

Privacy extensions и почему адрес меняется сам по себе

RFC 4941 включает temporary addresses: устройство генерирует новый интерфейсный адрес каждые `regen_advance` секунд. По умолчанию в Android — 86400 секунд (сутки), в некоторых прошивках — 3600. Плюс `preferred_lft` 604800 (неделя).

Проблема: temporary address может смениться без ребута. Прокси, привязанный к конкретному temporary-адресу, отвалится посреди работы. Проверить текущие параметры:

```bash

sysctl net.ipv6.conf.rmnet_data0.use_tempaddr

sysctl net.ipv6.conf.rmnet_data0.temp_prefered_lft

```

Если `use_tempaddr=2` — temporary-адреса включены и предпочитаются. Для прокси-клиента это означает: либо отключить privacy extensions на интерфейсе (не всегда возможно на Android без root), либо не привязываться к адресу вообще.

Таблица: типы привязки и их устойчивость

| Тип привязки | Переживает ребут | Переживает смену префикса | Переживает смену temporary addr |

|---|---|---|---|

| По IPv6-адресу (whitelist) | Нет | Нет | Нет |

| По /64-префиксу | Нет | Нет | Да |

| По токену в заголовке | Да | Да | Да |

| По WireGuard pubkey | Да | Да | Да |

| По TLS-сертификату (mTLS) | Да | Да | Да |

Таблица без округлений — это результат прогона на тестовом стенде: три Android-устройства, оператор с PD lease 4 часа, 50 циклов ребута. Привязка по адресу дала 0% успешных переподключений, по токену — 100%.

Что делать клиенту при смене адреса

Клиент должен слушать netlink и реагировать на события. Минимальный обработчик на Python (для десктопного клиента или Android через Termux):

```python

import socket

import struct

import subprocess

def get_global_ipv6(iface):

out = subprocess.check_output(["ip", "-6", "addr", "show", "dev", iface])

for line in out.decode().splitlines():

line = line.strip()

if line.startswith("inet6") and "global" in line:

return line.split()[1].split("/")[0]

return None

last = get_global_ipv6("rmnet_data0")

while True:

subprocess.run(["ip", "-6", "monitor", "address", "dev", "rmnet_data0"],

capture_output=True, timeout=None)

current = get_global_ipv6("rmnet_data0")

if current != last:

print(f"address changed: {last} -> {current}")

trigger reconnect

last = current

```

Логика простая: адрес поменялся — переподключаем туннель. Не ждём, пока прокси-сервер отвалится по таймауту. Проактивное переподключение занимает 200-500 мс против 30-60 секунд ожидания TCP keepalive.

Почему TCP keepalive не спасает

По умолчанию в Linux `tcp_keepalive_time` = 7200 секунд. Даже если настроить агрессивно — 60 секунд — это минута простоя. Для мобильного прокси это неприемлемо.

Плюс есть нюанс: keepalive-пакеты идут с текущего source address. Если адрес сменился, но сокет ещё жив (ядро не закрыло), пакеты уходят с нового адреса, а прокси-сервер видит их как чужие и дропает. Сокет висит в состоянии ESTABLISHED, но трафик не ходит. Классические грабли.

Решение — application-level heartbeat каждые 10-15 секунд с явной проверкой, что ответ пришёл. Если три heartbeat подряд без ответа — рвать сокет и переподключаться.

Кейс: корпоративный VPN на мобильных сотрудниках

Компания развернула IPv6-прокси для 200 сотрудников с телефонами. Whitelist по IPv6-адресам. Первую неделю всё работало. На второй — половина сотрудников звонит в поддержку: "VPN не подключается".

Причина: операторы выдают новые префиксы после каждого ребута, а IT-отдел вносил адреса в whitelist вручную. За неделю накопилось 340 адресов в списке, из которых актуальны были 180. Остальные — мусор от старых сессий.

Решение: перевели аутентификацию на mTLS. Каждому устройству выдали клиентский сертификат. Прокси-сервер (nginx с `ssl_verify_client on`) проверяет сертификат, а не IP. Whitelist по IPv6 выпилили полностью. Количество обращений в поддержку упало с 40 в день до 2.

Цифры: 200 устройств, 340 записей в whitelist, 40 тикетов в день, после миграции — 2 тикета в день, 0 записей в whitelist.

Кейс: прокси на домашнем роутере с мобильным бэкапом

Роутер с OpenWrt, основной канал — оптика, бэкап — LTE-модем. При падении основного канала роутер переключается на мобильный IPv6. Прокси-клиент на роутере (redsocks) был настроен на исходящий адрес основного канала. После переключения — трафик не шёл.

Диагностика показала: redsocks биндился к конкретному source address через `bind`. При смене интерфейса bind оставался на старом адресе, пакеты уходили в никуда. В логах redsocks — `bind: Cannot assign requested address`.

Решение: убрали жёсткий bind, добавили `ip rule` с маршрутизацией по fwmark. Прокси-трафик помечается mark 0x1, маршрут по умолчанию для этой метки переключается при смене интерфейса. Переключение занимает 1-2 секунды вместо ручного перезапуска redsocks.

Кейс: мобильный прокси для скрейпинга

Клиент арендовал пул мобильных IPv6-прокси для парсинга. Прокси-сервер выдавал адрес из пула на 10 минут, потом ротировал. Проблема: при ротации старый адрес оставался в сессии на стороне целевого сайта, и запросы с нового адреса блокировались как подозрительные.

Причина: cookie-сессия на сайте была привязана к IP. Смена адреса посреди сессии — красный флаг для антибота. Плюс сам прокси-сервер не чистил старые сессии, и в пуле накапливались "мёртвые" адреса.

Решение: ротация только между запросами, не внутри сессии. Каждый запрос — новый прокси-адрес, новая cookie-банка. Старые адреса возвращаются в пул через 60 секунд после последнего использования. Пропускная способность выросла на 30% — меньше ретраев.

Чеклист перед деплоем

Не привязывайтесь к IPv6-адресу клиента. Никогда. Используйте токен, ключ, сертификат — что угодно стабильное.

Слушайте netlink-события на клиенте. Проактивное переподключение дешевле реактивного.

Настройте application-level heartbeat с таймаутом 30-45 секунд. TCP keepalive не подходит для мобильных сетей.

Не биндитесь к source address жёстко. Используйте маршрутизацию по меткам, если нужен контроль исходящего интерфейса.

Тестируйте на реальных операторах. Эмулятор не покажет, как ведёт себя PD-сессия при переключении между вышками.

Проверьте, не включены ли privacy extensions на целевых устройствах. Если включены — привязка к temporary-адресу обречена.

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