Ви уявляєте, що 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.

Якщо обидва захоплення збігаються щодо кортежу, а тунель усе одно не працює, трансляція — не ваша проблема; переходьте до рукостискання й до таблиці маршрутизації всередині тунелю.

Схожі статті