Тунель падає, аварійний вимикач повідомляє, що спрацював, а завантаження триває. У правилах IPv4 нічого не зламано. Застосунок просто перейшов на шлях, для якого ці правила ніколи не писалися.

Пристрої з подвійним стеком мають два незалежні виходи. Блокування одного з них — половина блокування.

Два набори правил, дві політики за замовчуванням

У Linux iptables та ip6tables — окремі таблиці з окремими політиками. Встановлення ланцюгів INPUT і OUTPUT таблиці IPv4 у DROP нічого не змінює в таблиці IPv6, де політика за замовчуванням зазвичай ACCEPT. Таке саме розділення існує в nftables, де можна перевірити одну родину й виявити, що ваші правила несе лише одна з них. Ця асиметрія нормальна, і в ній уся проблема.

Ось чому аварійний вимикач може виглядати ґрунтовно, а діяти частково. Скрипт, який написав правила IPv4, виконався, лічильники зростають, рядок журналу з’являється, а пакет IPv6 виходить через фізичний інтерфейс цілком недоторканим.

Читайте, що ваш клієнт насправді встановлює, а не що обіцяє маркетингова сторінка. Одні клієнти спрямовують IPv6 у тунель, інші навмисно його блокують, а треті залишають як є, поки блокування на рівні платформи застосовує інше правило. Документація виробника — єдине джерело, якому тут варто довіряти.

Що вам каже конфігурація інтерфейсу

Сторінка довідки wg-quick включає правила IPv6 у приклад конфігурації, і причина — саме ця прогалина. Приклад не оздоблення. Він існує тому, що самі правила IPv4 залишили б другу родину відкритою.

Копіювання половини прикладу дає половину політики. Це найпоширеніше джерело цього витоку. Одна публікація в блозі скоротила приклад заради довжини. Потім скорочена версія стала шаблоном, який усі використовували повторно.

# what is actually installed, per family?
sudo iptables -S OUTPUT | head -20
sudo ip6tables -S OUTPUT | head -20

# nftables: inspect each family separately
sudo nft list ruleset inet | head -40

# does this host even have a usable IPv6 path?
ip -6 route show default

Якщо друга команда виводить дозвільну політику, а перша виводить DROP, ви знайшли відповідь, не торкаючись клієнта. Ця асиметрія і є помилкою.

Чому одного запиту недостатньо

Одне ім’я може повернути і запис A, і запис AAAA, а застосунки вибирають не всі однаково. Браузер може віддати перевагу IPv6, коли мережа його пропонує, і відкотитися при збої, тоді як фонова синхронізація або програма оновлення використовує власний резолвер і власні уподобання. Тому один успішний тест через IPv4 доводить один шлях, а не політику.

Переходи між мережами теж змінюють відповідь. Підключення до іншої мережі Wi-Fi, пробудження зі сну або перехід на мобільну мережу може дати пристрою новий префікс IPv6, і політика, що виглядала достатньою в офісній LAN, може його не покривати.

Перевірте стан, коли тунель вимкнено

Тестування під час підключення каже, що тунель працює. Цікавий тест — стан недоступності, бо саме тоді аварійний вимикач має тримати. Зупиніть тунель навмисно, потім спробуйте важливі призначення із застосунку, який ви захищаєте.

# with the tunnel stopped, does anything still leave?
ip -6 route get 2606:4700:4700::1111
curl -6 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv6.example.net/
curl -4 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv4.example.net/

Обидві родини мають відмовляти закрито. Якщо запит IPv4 завершується тайм-аутом, а запит IPv6 повертає код стану, політика неповна, і жодне повторне тестування тунелю це не змінить.

Збережіть у цьому тесті й задокументовані винятки. Виявлення локальної мережі, поновлення DHCP або завантажувальний шлях до кінцевої точки VPN можуть потребувати залишатися доступними, і ці винятки слід називати в політиці, а не виявляти під час збою. Тест на витік, який провалюється тому, що тунель не може піднятися знову, — це не знахідка в безпеці, а знахідка в зв’язності.

Схожі статті