Вы представляете, как VPN-сервер читает адрес вашего ноутбука из пакета и записывает его в журнал. На самом деле он читает то, что последний переход NAT поместил во внешний заголовок, а на телефоне, используемом как точка доступа, это часто адрес, разделяемый с сотнями других абонентов. Собственный адрес вашей машины 192.168.x.x никогда не пересекает интернет в этом заголовке, а адрес туннеля сервер выдаёт уже после установления соединения. Поэтому, когда журнал сервера и ip addr на ноутбуке расходятся, ни один из них не ошибается; они описывают разные уровни одной сессии.

Три адреса, и только один из них в журнале

Путаница возникает из-за сведения трёх адресов к одному. У каждого свой владелец, он живёт в своём заголовке и доходит до сервера своим путём.

AddressWho assigns itWhere it sitsVisible to the VPN server
Device address, e.g. 192.168.1.24Your router via DHCPOuter header, before translationNo, rewritten in place
Translated address and portRouter, ISP CGNAT, or bothOuter header, after translationYes, this is the tuple it logs
Tunnel address, e.g. 10.8.0.6The VPN server itselfInner header, after decapsulationYes, but it chose it

Только средняя строка неизвестна в момент подключения. Сервер записывает её в таблицу партнёров, файл состояния или журнал потоков в зависимости от демона: WireGuard называет её конечной точкой, файл состояния OpenVPN помечает её как Real Address, а strongSwan сообщает её как удалённый хост IKE_SA. Это значение обновляется каждый раз, когда приходит пакет из другого источника, поэтому меняется без чьего-либо перезапуска.

Нижняя строка — это то, что люди ошибочно читают как утверждение об идентичности. Она отмечает место в конфигурации сервера, а не человека, потому что сервер выбрал её из своего пула. Два пользователя могут получить один и тот же адрес туннеля в разные дни, а один может держать два с двух устройств.

Почему записанный кортеж меняется, пока туннель остаётся поднятым

Трансляция адресов — это таблица с таймером, а не постоянная привязка. Домашний маршрутизатор хранит своё UDP-сопоставление ещё некоторое время после последнего пакета, шлюз оператора перерабатывает порты по своему расписанию, а телефон, переходящий с Wi-Fi на LTE, возвращается с совершенно другим источником. Значения conntrack по умолчанию в Linux — полезный ориентир: nf_conntrack_udp_timeout составляет 30 секунд, а потоковый вариант 120, так что тихий туннель может потерять сопоставление задолго до того, как пользователь это заметит.

Туннель выживает потому, что протокол аутентифицирует партнёра, а не адрес. WireGuard после рукопожатия не хранит состояния, поэтому любой аутентифицированный пакет обновляет сохранённую конечную точку, и перепривязка исправляется на следующем пакете; именно для этого существует persistent-keepalive = 25 — чтобы сопоставление оставалось тёплым во время простоя. --float в OpenVPN делает то же самое и позволяет аутентифицированному клиенту продолжить с нового адреса и порта. В сборках 2.4 и 2.5, где float по умолчанию отключён, перепривязка сбрасывает сессию, и клиент подключается заново.

IPsec добивается этого с большим числом движущихся частей. IKEv2 замечает трансляцию, сравнивая хеши источника и назначения в полезной нагрузке обнаружения NAT, переходит на инкапсуляцию UDP 4500 и отслеживает keepalive до нового кортежа. Когда keepalive блокируются, SA остаётся поднятым лишь на бумаге, а трафик в одном направлении тихо останавливается.

Что сервер может приписать, а что нет

Миф, который стоит убить, состоит в том, что трансляция скрывает вас от оператора. Она меняет метку, а не наблюдение. Шлюз за NAT оператора видит пространство 100.64.0.0/10 или один публичный адрес, разделяемый многими абонентами, и всё же может связать поток с субъектом сертификата, открытым ключом WireGuard, выданным адресом туннеля, счётчиками байтов и временным окном. Ничему из этого не нужен ваш адрес LAN.

Ограничения работают и в обратную сторону. Общий адрес в журнале указывает на шлюз, а не на домохозяйство; две сессии с одного и того же транслированного адреса на разных портах — это разные устройства; один и тот же адрес в два разных дня может принадлежать двум несвязанным абонентам, если порт был переработан. Сервер, записывающий только ключи партнёров, не может сопоставить их с клиентом без базы данных учётных записей, а сервер, записывающий только адреса, не отличит ноутбук от телефона за одним маршрутизатором.

Сравните оба конца вместо догадок

Чтобы выяснить, что произошло, захватите одно и то же соединение на обоих концах в один момент и сравните кортеж, а не адрес. На клиенте, до любой трансляции:

ss -uapn 'dport = :51820'
ip -4 route get 203.0.113.10
wg show wg0 endpoints

Затем прочитайте запись трансляции на маршрутизаторе или шлюзе CGNAT и то, что в итоге приходит на сервер:

conntrack -L -p udp --dport 51820
tcpdump -ni eth0 udp port 51820

Три схемы объясняют большинство расхождений. Порт источника на сервере отличается от локального порта, а назначение совпадает: обычная трансляция портов. Адрес источника на сервере принадлежит блоку ISP, который не ваш: как минимум один дополнительный уровень NAT. Пакеты прекращаются после периода простоя и возобновляются с новым портом: сопоставление истекло, а не сбой маршрутизации. Если метки времени расходятся более чем на секунду-две, вы сравниваете две разные попытки.

Где разница ломает всё

Сбои, похожие на отказы сервера, обычно начинаются здесь. Правило доступа, привязанное к вашему домашнему адресу, перестаёт работать после смены аренды у ISP. Правило fail2ban, совпадающее с транслированным адресом, блокирует всех абонентов за этим шлюзом сразу. Партнёр «сайт-сайт» с фиксированным удалённым адресом перестаёт обновлять ключи после смены мобильного канала. Протокол туннеля был в порядке; предположение о внешнем кортеже — нет.

Та же путаница видна и на стороне сервера. Если сам VPN-бокс стоит за NAT, нужны проброс порта и работающий путь пересылки; руководство strongSwan по пересылке покрывает этот случай для IPsec. Сервер, доступный только по частному адресу, никогда не видит транслированный кортеж, который представляют его клиенты, и это другая проблема, чем трансляция клиентов.

Пройдите эти четыре проверки по порядку и остановитесь на первой неудачной:

  • Захватите на обоих концах одновременно; подтвердите, что порт источника, порт назначения и метки времени совпадают.
  • Прочитайте в списке партнёров сервера адрес, который он сейчас держит, а не тот, который вы ожидали.
  • Проверьте таблицу conntrack или NAT на запись и её оставшийся срок жизни.
  • Подтвердите, что адрес интерфейса туннеля на клиенте совпадает с выданным сервером, а не с адресом LAN.

Если оба захвата совпадают по кортежу, а туннель всё равно не работает, трансляция — не ваша проблема; переходите к рукопожатию и к таблице маршрутизации внутри туннеля.

Похожие статьи