Односторонній трафік через VPN сайт‑до‑сайту — це тип збоїв, який зовні виглядає «ніби працює». Тунель підключений. Фаза 1 і Фаза 2 зелені. Хтось може пропінгувати щось. І все ж додаток не працює, або працює лише в одному напрямку, або лише коли місяць у певній підмережі.
У продакшені односторонній трафік рідко буває «проблемою VPN». Це проблема маршрутизації в костюмі VPN, де NAT і MTU часто виконують допоміжні ролі. Це мій чекліст «маршрутизація першою», який я використовую, коли потрібні швидкі відповіді і немає часу милуватися графіком аптайму тунелю.
Ментальна модель: чому «тунель підключений» не означає «трафік проходить»
VPN сайт‑до‑сайту має дві окремі задачі:
- Обмін ключами та шифрування: аутентифікація пірів, узгодження алгоритмів, побудова Security Associations (SA).
- Пересилання трафіку: вирішити, які пакети входять у тунель, і куди повертаються пакети у відповідь.
Більшість NOC‑дашбордів одержимі задачею №1. Саме задача №2 приносить проблеми.
Односторонній трафік — це збій цілісності маршрутизації
«Односторонній» зазвичай означає одне з наступного:
- Асиметрична маршрутизація: пакет йде тунелем в одному напрямку, повертається через інтернет (або іншим шляхом) і відкидається.
- Неправильна область шифрування / селектори: адреси джерела/призначення не відповідають узгодженим політикам, тому трафік ніколи не потрапляє в тунель (або лише в одному напрямку).
- NAT у неправильному місці: прямий шлях має NAT, а зворотний шлях очікує оригінальні адреси (або навпаки).
- Несумісність зі stateful‑фільтром: пакети у відповідь не розпізнаються як встановлені, бо приходять по іншому інтерфейсу/шляху.
- PMTU / фрагментація: малі пінги працюють; TCP гальмує; певні додатки падають. На рівні L7 виглядає як «одностороннє».
- Перекривання підмереж: обидві сторони вважають 10.0.0.0/8 «локальною». Спойлер: це не локально на обох кінцях одночасно.
Ось найпростіше правило для продакшену, яке я знаю: для кожного VPN‑захищеного префікса на Стороні A Сторона B має мати однозначний маршрут повернення назад через тунель, і навпаки. Якщо ви не можете чітко це проговорити з точними CIDR, ви ще не закінчили.
Одна цитата, щоб залишатися чесним (ідея переказана): Werner Vogels: все ламається; проєктуйте, передбачаючи відмови, і перевіряйте поведінку замість того, щоб довіряти індикаторам стану.
Жарт №1: тунель VPN «підключений» без робочих маршрутів — це як вестибюль готелю без номерів: красивий, марний і якось все одно дорогий.
План швидкої діагностики (перше/друге/третє)
Якщо у вас є лиш 15 хвилин і вам надсилають скріншоти «Phase 2: up», робіть це. У порядку. Без відволікань.
Перше: підтвердіть шлях в обох напрямках
- Виберіть один хост‑джерело на Стороні A і один хост‑призначення на Стороні B.
- Тестуйте ICMP і TCP (лише ICMP — бреше, вічливо).
- Запустіть traceroute (або краще: tracepath) в обох напрямках і порівняйте.
Рішення: якщо будь‑який напрямок не заходить в очікуваний тунельний інтерфейс/шлюз, не звинувачуйте IPsec. Виправляйте маршрутизацію або вибір політик.
Друге: перевірте селектори / маршрути і маршрути повернення
- Policy‑based IPsec: перевірте, що traffic selectors (локальні/віддалені підмережі) на обох кінцях збігаються точно.
- Route‑based IPsec (VTI): перевірте, що маршрути в ядрі спрямовують віддалені префікси до VTI, і що зворотні шляхи роблять те ж саме.
- Шукайте перекриття, невідповідність супernet і «тимчасові» статичні маршрути, що залишились.
Рішення: якщо таблиці маршрутів виглядають правильно, але трафік у відповідь все ще не повертається, швидше за все причина в NAT, стані брандмауера або асиметричній маршрутизації через другий WAN.
Третє: PMTU/MSS та правила NAT
- Якщо пінг працює, а додатки — ні: підозрюйте MTU/MSS.
- Якщо лише певні підмережі відмовляють: підозрюйте винятки NAT, неправильний порядок ACL або невідповідність селекторів.
- Якщо працює лише в одному напрямку: підозрюйте stateful‑файрвол або маршрут повернення (так, знову).
Рішення: застосуйте MSS‑клэмпінг для TCP, перевірте PMTU через tracepath і переконайтеся, що винятки NAT охоплюють саме ті CIDR, що захищені VPN.
Чеклісти / покроковий план (робіть у цьому порядку)
Чекліст 1: Визначте домен шифрування як слід
- Запишіть префікси, захищені на Стороні A (точні CIDR) і на Стороні B.
- Підтвердіть, що немає перекриттів. Якщо є — припиніть і перенумеруйте або використайте NAT свідомо (не випадково).
- Визначте route‑based (VTI) або policy‑based. Якщо є вибір — обирайте route‑based для операційної простоти.
- Задокументуйте, які IP мають бути доступні через тунель, а які — ні.
Чекліст 2: Зробіть маршрутизацію симетричною за конструкцією
- Для кожного віддаленого префікса підтвердіть, що існує рівно один найкращий маршрут: через VPN.
- Якщо ви використовуєте динамічну маршрутизацію (BGP/OSPF), підтвердіть:
- маршрути рекламуються в обох напрямках
- фільтри дозволяють потрібні префікси
- метрики/спільноти віддають перевагу шляху через VPN
- Якщо використовуєте статичні маршрути, переконайтесь:
- вони налаштовані на обох сторонах
- їх не перекриває ширший маршрут (наприклад default)
- Обдумано ввімкніть reverse path filtering (
rp_filter) — строгий режим може зламати легітимний мульти‑хомінг.
Чекліст 3: Визначте, де дозволений NAT, і дотримуйтеся цього
- Сформуйте політику NAT: «Трафік між A‑захищеними і B‑захищеними мережами не NATиться.» (Це бажаний дефолт.)
- Реалізуйте винятки NAT перед загальними правилами маскараду в інтернет.
- Якщо потрібно NAT через тунель (через перекриття, вимоги вендора), робіть це послідовно і задокументуйте відображення діапазонів.
Чекліст 4: Зробіть MTU «нудним»
- Виміряйте path MTU через тунель (не вгадуйте).
- Застосуйте TCP MSS‑клэмпінг на тунельному інтерфейсі, якщо бачите зупинки.
- Дозвольте ICMP «fragmentation needed» — інакше PMTU‑виявлення ламається і ви отримаєте таємничі чорні діри.
Чекліст 5: Брандмауери та стан з’єднань
- Підтвердіть, що обидві сторони дозволяють:
- IKE (UDP 500)
- NAT‑T (UDP 4500) якщо NAT присутній на шляху
- ESP (IP proto 50) якщо не використовується NAT‑T
- Підтвердіть симетричну політику для захищених підмереж (в обох напрямках).
- На stateful‑фаєрволах переконайтесь, що трафік у відповідь повертається тим же логічним шляхом; якщо ні — спроєктуйте обхід.
Чекліст 6: Наблюваність, що ловить односторонній трафік рано
- Моніторте стан тунелю і плоску плоскость передачі: байти/пакети, дропи та лічильники по селекторах.
- Запускайте синтетичні тести в обох напрямках (ICMP + TCP).
- Логайте ключові зміни в маршрутах (BGP сесії, диф‑таблиці маршрутів) у вікнах інцидентів.
Практичні завдання з командами: виводи, значення та рішення
Нижче — перевірені в полі завдання, які можна виконати на типових Linux‑шлюзах та маршрутизаторах VPN. Кожне завдання включає: команду, що означає вивід, і рішення.
Завдання 1: Підтвердіть маршрут ядра до віддаленої підмережі (Linux)
cr0x@server:~$ ip route get 10.20.30.40
10.20.30.40 via 169.254.100.2 dev vti0 src 10.10.10.1 uid 0
cache
Значення: Система шле пакети до 10.20.30.40 через vti0 (route‑based тунель) через IP‑peer VTI.
Рішення: Якщо це не вказує на тунельний інтерфейс (або вказує на інтернет/default шлюз), виправляйте маршрути перед налаштуванням IPsec.
Завдання 2: Показати таблицю маршрутів та знайти «затемнені» маршрути
cr0x@server:~$ ip route show table main
default via 203.0.113.1 dev eth0
10.10.0.0/16 dev lan0 proto kernel scope link src 10.10.10.1
10.20.0.0/16 via 169.254.100.2 dev vti0 proto static metric 100
Значення: Віддалена 10.20.0.0/16 явно маршрутизована в тунель; добре. Якби був тільки default via, ви б мали рулетку шляху повернення.
Рішення: Якщо віддалений префікс відсутній — додайте його (або виправте динамічну маршрутизацію). Якщо він є, але ширший маршрут перемагає (неправильна метрика), скоригуйте метрики/політику маршрутизації.
Завдання 3: Перевірити, що IPsec SA існують і передають трафік (strongSwan)
cr0x@server:~$ sudo swanctl --list-sas
vpn-siteA-siteB: #12, ESTABLISHED, IKEv2, rekeying in 2 hours
local 'gw-siteA' @ 198.51.100.10[4500]
remote 'gw-siteB' @ 203.0.113.20[4500]
AES_GCM_16_256/PRF_HMAC_SHA2_256/ECP_256
CHILD_SA vpn-child{34}: INSTALLED, TUNNEL, reqid 1
10.10.0.0/16 === 10.20.0.0/16
bytes_i 1289021, bytes_o 1401122, packets_i 9801, packets_o 10210
Значення: SA підняті, лічильники показують пакети вхід/вихід. Якщо bytes_i зростає, а bytes_o ні (або навпаки), у вас одностороння плоска плоскость передачі.
Рішення: Якщо лічильники SA не рухаються при генерації трафіку, ваші селектори не збігаються або маршрутизація не направляє пакети в IPsec/VTI.
Завдання 4: Підтвердити policy‑based селектори в ядрі (XFRM policy)
cr0x@server:~$ sudo ip xfrm policy
src 10.10.0.0/16 dst 10.20.0.0/16
dir out priority 2345 ptype main
tmpl src 198.51.100.10 dst 203.0.113.20 proto esp reqid 1 mode tunnel
src 10.20.0.0/16 dst 10.10.0.0/16
dir in priority 2345 ptype main
tmpl src 203.0.113.20 dst 198.51.100.10 proto esp reqid 1 mode tunnel
Значення: Ядро зашифрує трафік з 10.10/16 до 10.20/16 при виході і прийме вхідний трафік у зворотньому напрямку.
Рішення: Якщо один напрямок відсутній або використовує інші CIDR, виправте IPsec‑політику/конфігурацію з’єднання. Несумісні селектори — класичний фактор «працює з A до B, але не назад».
Завдання 5: Перевірити асиметричну маршрутизацію через правила політики маршрутизації
cr0x@server:~$ ip rule show
0: from all lookup local
100: from 10.10.0.0/16 lookup 100
32766: from all lookup main
32767: from all lookup default
Значення: Трафік з 10.10/16 використовує таблицю маршрутів 100. Це може бути правильно (multi‑WAN, VRF), або прихована пастка.
Рішення: Якщо існує policy routing, підтвердіть, що віддалені префікси теж в тій самій таблиці. Інакше трафік повернення може вийти неправильним інтерфейсом.
Завдання 6: Переглянути таблицю 100, щоб підтвердити, що там теж є віддалені маршрути
cr0x@server:~$ ip route show table 100
default via 198.51.100.1 dev eth1
10.20.0.0/16 via 169.254.100.2 dev vti0 metric 50
Значення: Навіть під policy‑routing, 10.20/16 йде у vti0. Добре.
Рішення: Якщо 10.20/16 відсутній тут — додайте його; інакше певні потоки підуть в інтернет і загинуть на stateful‑фаєрволі або ACL пірa.
Завдання 7: Перевірити reverse path filtering (rp_filter), що відкидає асиметричний трафік
cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.vti0.rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.vti0.rp_filter = 1
Значення: Увімкнена строгіша перевірка джерела. Це може відкидати легітимні пакети, якщо маршрутизація асиметрична або якщо джерело виглядає доступним через інший інтерфейс.
Рішення: Якщо у вас мульти‑хомінг або policy routing, розгляньте встановлення rp_filter=2 (loose) на відповідних інтерфейсах, але тільки після розуміння причин асиметрії.
Завдання 8: Підтвердити виняток NAT (iptables), щоб VPN‑трафік не маскувався
cr0x@server:~$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.10.0.0/16 -d 10.20.0.0/16 -j RETURN
-A POSTROUTING -s 10.10.0.0/16 -o eth0 -j MASQUERADE
Значення: Трафік з 10.10/16 до 10.20/16 обходить NAT; все інше на eth0 маскується.
Рішення: Якщо правило RETURN відсутнє або стоїть після MASQUERADE (порядок важливий), виправте це. NAT‑ування VPN‑трафіку — легкий шлях отримати «пінгує, але все інше не працює».
Завдання 9: Підтвердити порядок NAT в nftables (якщо ви використовуєте nft)
cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.10.0.0/16 ip daddr 10.20.0.0/16 return
oifname "eth0" ip saddr 10.10.0.0/16 masquerade
}
}
Значення: Те саме, як в iptables: спочатку виняток для VPN‑трафіку.
Рішення: Якщо ваш виняток відсутній або занадто широкий (повертає більше, ніж потрібно), звузьте його. Слабкі винятки NAT — як випадково обійти межі безпеки.
Завдання 10: Переконатися, що фільтри брандмауера дозволяють захищені підмережі в обох напрямках
cr0x@server:~$ sudo iptables -S FORWARD
-P FORWARD DROP
-A FORWARD -i vti0 -o lan0 -s 10.20.0.0/16 -d 10.10.0.0/16 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i lan0 -o vti0 -s 10.10.0.0/16 -d 10.20.0.0/16 -j ACCEPT
-A FORWARD -i vti0 -o lan0 -s 10.20.0.0/16 -d 10.10.0.0/16 -j ACCEPT
Значення: Форвардинг за замовчуванням відкидається; є явні дозволи. Зверніть увагу, що правило established/related допомагає трафіку у відповідь, але все одно потрібні симетричні дозволи залежно від політики.
Рішення: Якщо дозволено лише в одному напрямку, ви побачите односторонній TCP (SYN йде, SYN/ACK гине). Виправте відсутній напрямок і підтвердіть, що трекінг стану бачить правильні інтерфейси.
Завдання 11: Захоплення трафіку на LAN та тунельних інтерфейсах, щоб довести, де він гине
cr0x@server:~$ sudo tcpdump -ni lan0 host 10.20.30.40 and '(icmp or tcp)'
14:22:01.112233 IP 10.10.10.50.51522 > 10.20.30.40.443: Flags [S], seq 1234567890, win 64240, options [mss 1460,sackOK,TS val 1 ecr 0], length 0
14:22:02.113344 IP 10.10.10.50.51522 > 10.20.30.40.443: Flags [S], seq 1234567890, win 64240, options [mss 1460,sackOK,TS val 2 ecr 0], length 0
Значення: SYN виходять на LAN‑інтерфейсі; немає повернених SYN/ACK. Тепер захопіть на vti0, щоб побачити, чи вони входять у тунель.
Рішення: Якщо пакети є на LAN, але не на тунелі — неправильна маршрутизація/вибір політики. Якщо вони є в тунелі, але не на LAN після декапсуляції — проблема з маршрутом повернення, брандмауером або селектором на віддаленій стороні.
Завдання 12: Захоплення на VTI, щоб підтвердити, що пакети проходять тунель
cr0x@server:~$ sudo tcpdump -ni vti0 host 10.20.30.40 and tcp port 443
14:22:01.112999 IP 10.10.10.50.51522 > 10.20.30.40.443: Flags [S], seq 1234567890, win 64240, options [mss 1360,sackOK,TS val 1 ecr 0], length 0
Значення: SYN у тунелі. Зверніть увагу, що MSS змінилося до 1360 — хтось кламерує MSS, що може бути корисно.
Рішення: Якщо пакет у тунелі, локальна сторона ймовірно в порядку; фокусуйтеся на шлюзі віддаленої сторони — маршрут повернення, фаєрвол, NAT або невідповідність селекторів.
Завдання 13: Перевірити PMTU через тунель за допомогою tracepath
cr0x@server:~$ tracepath -n 10.20.30.40
1?: [LOCALHOST] pmtu 1500
1: 169.254.100.2 1.023ms
2: 10.20.30.40 2.108ms reached
Resume: pmtu 1436 hops 2 back 2
Значення: Виявлений PMTU — 1436. Якщо ви відправляєте 1500‑байтові фрейми без обробки фрагментації, щось потемніє.
Рішення: Якщо PMTU нижчий за 1500 — кламеруйте MSS (Завдання 14) і переконайтеся, що ICMP «frag needed» не блокується.
Завдання 14: Застосувати TCP MSS‑клэмпінг на тунельному інтерфейсі (Linux, iptables)
cr0x@server:~$ sudo iptables -t mangle -A FORWARD -o vti0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
cr0x@server:~$ sudo iptables -t mangle -S FORWARD | tail -n 3
-A FORWARD -o vti0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Значення: Нові TCP‑з’єднання через vti0 матимуть MSS, підлаштований під PMTU, що зменшить проблеми з фрагментацією.
Рішення: Якщо після клэмпінгу TCP‑затримки зникли, ви підтвердили проблему MTU/PMTU. Залиште це, потім виправте базовий MTU або фільтрацію ICMP, якщо можливо.
Завдання 15: Перевірити досяжність IKE/ESP/NAT‑T (з боку шлюзу)
cr0x@server:~$ sudo ss -uapn | egrep ':(500|4500)\b'
UNCONN 0 0 0.0.0.0:500 0.0.0.0:* users:(("charon",pid=1234,fd=12))
UNCONN 0 0 0.0.0.0:4500 0.0.0.0:* users:(("charon",pid=1234,fd=13))
Значення: Демон слухає IKE і NAT‑T. Якщо 4500 відсутній, але NAT є, ви можете погано узгоджуватися або падати після початкових пакетів.
Рішення: Якщо слухачі відсутні — виправте конфігурацію сервісу. Якщо вони є, але трафік не надходить — зосередьтесь на upstream ACL/безпекових групах.
Завдання 16: Перевірити дропи на VTI‑інтерфейсі
cr0x@server:~$ ip -s link show dev vti0
10: vti0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1436 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
8821991 82310 0 212 0 0
TX: bytes packets errors dropped carrier collsns
9011122 84100 0 0 0 0
Значення: Є RX‑дропи. Дропи можуть бути через MTU, фаєрвол, черги або політику, але це твердий сигнал, що пакети не проходять чисто.
Рішення: Якщо дропи зростають під час тестів — корелюйте з tcpdump і логами; розгляньте MTU, лімітування або неправильний маршрут, що потрапляє на інший інтерфейс.
Завдання 17: Підтвердити, що форвардинг увімкнений (класика)
cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
Значення: Пристрій може маршрутизувати пакети. Якщо 0 — у вас може бути ідеальний тунель, а шлюз поводитиметься як дуже захищений камінь.
Рішення: Якщо 0 — увімкніть і збережіть налаштування; потім перетестуйте потоки.
Завдання 18: Перевірити обмін BGP через тунель (FRR)
cr0x@server:~$ sudo vtysh -c "show ip bgp summary"
BGP router identifier 10.10.10.1, local AS number 65010
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
169.254.100.2 4 65020 10422 10398 77 0 0 2d03h 12
Значення: BGP‑сусід по VTI піднятий і отримує префікси (12). Якщо він idle/active — у вас ще немає симетричної маршрутизації.
Рішення: Якщо отриманих префіксів 0 або вони несподівані — перевірте фільтри/route‑map. Якщо BGP down — перевірте доступність тунельного інтерфейсу і фаєрвол на TCP/179.
Завдання 19: Підтвердити, що конкретний префікс встановлено і є пріоритетним (BGP)
cr0x@server:~$ sudo vtysh -c "show ip route 10.20.0.0/16"
Routing entry for 10.20.0.0/16
Known via "bgp", distance 20, metric 0, best
* 169.254.100.2, via vti0, weight 1, 2d03h
Значення: Віддалений префікс найкращий через тунель. Якщо найкращий шлях — через інтернет next‑hop, ви створили машину одностороннього трафіку.
Рішення: Виправте local preference/метрики або додайте статичний маршрут більш високого пріоритету в VTI, поки стабілізуєте BGP‑політику.
Завдання 20: Перевірити, чи conntrack бачить потік (проблеми зі stateful шляхом)
cr0x@server:~$ sudo conntrack -L | grep "10.10.10.50.*10.20.30.40.*dport=443" | head -n 2
tcp 6 118 SYN_SENT src=10.10.10.50 dst=10.20.30.40 sport=51522 dport=443 [UNREPLIED] src=10.20.30.40 dst=10.10.10.50 sport=443 dport=51522
Значення: З’єднання застрягло в SYN_SENT з UNREPLIED. Це узгоджується з відсутністю трафіку у відповідь (маршрути/фаєрвол/селектор).
Рішення: Якщо бачите відповіді, але додаток все ще падає — рухайтеся вгору по стеку (TLS, ACL додатка). Якщо ні — зосередьтеся на шляху повернення і політиці віддаленої сторони.
Типові помилки: симптом → корінна причина → виправлення
1) Симптом: «Ping працює A→B, але B→A не працює»
- Корінна причина: маршрут повернення на Стороні B вказує на інший шлюз (зазвичай default або другий WAN), тому відповіді обходять тунель.
- Виправлення: встановіть явні маршрути для захищених префіксів Сторони A через тунель/VTI на Стороні B; переконайтесь, що таблиці policy routing теж їх містять. Перевірте за допомогою
ip route getобох сторін.
2) Симптом: «Тунель підключений, але нічого не проходить; лічильники не рухаються»
- Корінна причина: невідповідність селекторів (policy‑based) або маршрути не направляють трафік в тунель (route‑based).
- Виправлення: вирівняйте локальні/віддалені CIDR точно на обох пірів; перевірте XFRM‑політику або наявність маршрутів VTI і їх відповідність.
3) Симптом: «Малі пінги працюють; HTTPS зависає або завантажує половину сторінки»
- Корінна причина: MTU/PMTU‑чорна діра; ICMP frag‑needed блокується; TCP‑сегменти занадто великі після інкапсуляції.
- Виправлення: виміряйте PMTU за допомогою
tracepath; кламеруйте MSS на тунелі; дозвольте ICMP типу 3 код 4 там, де потрібно.
4) Симптом: «Лише деякі підмережі працюють через VPN»
- Корінна причина: неповні селектори, відсутні статичні маршрути або фільтрація маршрутів у BGP/OSPF.
- Виправлення: аудит префіксів від краю до краю: рекламуються, приймаються, встановлюються й дозволяються брандмауером/винятками NAT. Не довіряйте «ми додали /16». Доведіть це перевірками маршрутів.
5) Симптом: «Працює деякий час, потім одностороннє після фейловера»
- Корінна причина: HA‑переключення змінило IP джерела, порушило селектори, або перенаправило повернення на інший інтерфейс. Conntrack‑стан втрачається або не відповідає.
- Виправлення: забезпечте стабільні кінцеві точки тунелю (VIP), узгоджені маршрути і правила NAT на всіх вузлах HA, і тестуйте фейловер двобічними пробами.
6) Симптом: «BGP показує префікси, але трафік все одно односторонній»
- Корінна причина: маршрути встановлені, але асиметрія через інший найкращий шлях для повернення або rp_filter відкидає пакети, що приходять неочікуваним інтерфейсом.
- Виправлення: порівняйте рішення маршрутизації з
ip route getна обох сторонах; налаштуйте local preference/метрики; встановітьrp_filterвідповідно до дизайну.
7) Симптом: «Лише UDP працює; TCP нестійкий»
- Корінна причина: MTU/MSS і чутливість до повторних передач; або stateful‑фаєрвол з асиметричним шляхом повернення.
- Виправлення: MSS‑клэмпінг, підтвердження симетричності маршрутизації і перевірка, що conntrack бачить обидва напрямки послідовно.
8) Симптом: «Трафік входить у тунель, але віддалений хост його ніколи не бачить»
- Корінна причина: віддалена сторона маршрутизує трафік у тунель, але не має внутрішньої маршрутизації до кінцевого хоста, або віддалений фаєрвол блокує після декапсуляції.
- Виправлення: traceroute з віддаленого шлюзу до внутрішнього хоста; переконайтесь, що внутрішні маршрутизатори знають маршрут повернення до VPN‑захищених префіксів; виправте політику сегментації.
Три корпоративні міні‑історії (як це ламається в реальному житті)
Міні‑історія №1: Інцидент, спричинений неправильною припущенням
Два бізнес‑підрозділи об’єднали мережі, не узгодивши припущення. Одна команда керувала on‑prem брандмауером/VPN; інша — хмарною VPC. Вони погодили тунель IPsec і оголосили перемогу, коли UI сказав «Connected».
Неправильне припущення було тонким: хмарна команда вважала, що «маршрути автоматично розповсюджуються, бо тунель підключений». On‑prem команда вважала, що «хмара завжди має маршрут назад, бо це хмара». Жодне припущення не перевіряли двобічним потоком.
Прямий трафік з on‑prem у хмару працював, бо on‑prem мав явні статичні маршрути до хмарних CIDR. Повернення ж падало, бо таблиця маршрутів, пов’язана з підмережею робочого навантаження в хмарі, не включала CIDR on‑prem. Деякі підмережі використовували іншу таблицю маршрутів, тож один додаток працював, інший — ні. Це «часткове успішне» рішення подарувало їм повний день плутанини.
Виправлення було нудним: асоціювати правильну таблицю маршрутів з правильними підмережами, додати відсутні маршрути і потім виконати ті самі дві проби щоразу: ICMP і TCP в обох напрямках. Постійне покращення — культурна зміна: вони додали «підтвердити маршрут повернення» як чек‑бокс у зміні конфігурації, а не як усне правило.
Міні‑історія №2: Оптимізація, що дала зворотний ефект
Мережна команда хотіла швидшої конвергенції і менше рухомих частин. Вони замінили пару статичних маршрутів на BGP через IPsec‑тунель. Розумно. Вони також налаштували BGP так, щоб віддавати перевагу вторинній інтернет‑лінії як «резерв», використовуючи local preference і маршрут‑мапу, що виглядала елегантно під час рев’ю.
Потім під час технічного обслуговування змінилось, яка лінія стала «первинною». BGP переструктурувався так, як було налаштовано, що виявилося найгіршим видом правильно: він віддавав перевагу вторинній лінії для деяких префіксів, але IPsec‑кінцева точка була і досі прив’язана до публічної IP первинної лінії. Появилася асиметрія в даній площині: вихідний трафік йшов у тунель, а повернення виривався через інший вихід через те, що маршрут‑мапа так вирішила.
Користувачі описували це як «випадкові таймаути». Моніторинг показував тунель піднятим і BGP встановленим. Захоплення пакетів показало правду: SYN йшов, SYN/ACK повертався по іншому інтерфейсу і відкидався stateful‑правилами і rp_filter. «Оптимізація» не була в BGP; проблема була в припущенні, що площина керування автоматично гарантує симетрію в площині даних.
Виправлення: зробити дизайн явним — прив’язувати next‑hop BGP до тунельного інтерфейсу (VTI), а не до WAN‑залежного шляху; використовувати узгоджену policy routing; і тестувати фейловер як первинний сценарій. Вони залишили BGP, але перестали вважати його чарівною панеллю.
Міні‑історія №3: Нудна, але правильна практика, що врятувала ситуацію
Компанія з кількома сайтами мала правило: кожна зміна VPN включає знімок до/після трьох речей — маршрути, правила NAT, і результат двобічної перевірки. Без винятків. Інженери закочували очі, бо інженери частково заробляють на закочуванні очей.
Під час рутинного оновлення брандмауера у верхній частині порядку правил з’явилося нове дефолтне правило NAT. Тунель залишився підключеним, і базові пінги з самого брандмауера працювали. Але трафік додатків із LAN почав відмовлятися так, ніби віддалений сайт впав.
В тікеті на зміну були знімки. Порівняння таблиць NAT виявило проблему миттєво: VPN‑трафік почав маскуватися, що порушило селектори на іншому кінці і заплутало маршрут повернення. Вони відкотили порядок правил за кілька хвилин, а потім повторно ввели його вже з правильно розташованим винятком NAT. Інцидент ніколи не став серйозною аварією, бо діагностичні артефакти вже були під рукою.
Нудна практика — драматичний виграш. Секрет не в геніальності; секрет у відтворюваності. Ваше майбутнє «я» точно не згадає ту одну особливу NAT‑позицiю, яку ви «обов’язково» запам’ятаєте.
Жарт №2: Якщо хочете знайти приховане NAT‑правило — заплануйте вікно простою: NAT‑правила люблять увагу і з’являться миттєво.
Цікаві факти та коротка історія (контекст, що запобігає помилкам)
- Факт 1: Основні стандарти IPsec виникли у 1990‑х, і дизайн це показує: він потужний, гнучкий і алергічний до простого відлагодження.
- Факт 2: ESP (Encapsulating Security Payload) — це IP‑протокол 50, а не TCP/UDP‑порт — тож «відкривати порти» недостатньо, якщо ви не використовуєте NAT‑T.
- Факт 3: NAT‑T (UDP 4500) став поширеним, бо NAT ламає класичні припущення IPsec; інкапсуляція ESP в UDP зробила IPsec життєздатним в сучасному інтернеті.
- Факт 4: Policy‑based VPN (селектори/ACL визначають, що шифрується) історично були поширені на фаєрволах; route‑based VPN (VTI) стали популярними, коли мережі потребували динамічної маршрутизації і простішої операційності.
- Факт 5: Path MTU discovery залежить від ICMP. Повне блокування ICMP — це як зрізати дорожні знаки і дивуватися пробкам.
- Факт 6: Перевірки «тунель підключений» часто валідуюють лише IKE‑узгодження, а не те, що селектори збігаються або що існують маршрути; саме тому синтетичні проби важливі.
- Факт 7: Асиметрична маршрутизація сама по собі не є поганою. Вона стає проблемною, коли ви додаєте stateful‑фаєрволи, conntrack, rp_filter або суворі анти‑спуфінгові припущення.
- Факт 8: Перекриття RFC1918 мереж (10/8, 172.16/12, 192.168/16) — головний драйвер для «тимчасового NAT» через VPN, яке потім стає постійною архітектурною звичкою.
- Факт 9: Хмарні VPN часто мають окремі концепти для «підключення тунелю» і «асоціації таблиці маршрутів». Люди налаштовують одне і забувають інше, а потім дивуються, чому маршрут повернення зникає.
Поширені питання
1) Чому відбувається односторонній трафік, якщо Фаза 2 встановлена?
Бо встановлення Фази 2 означає, що SA існують, але не гарантує, що пакети відповідають селекторам, не гарантує, що маршрути направляють пакети в тунель, і не гарантує наявності маршрутів повернення.
2) Чи слід віддавати перевагу route‑based VPN (VTI) чи policy‑based VPN?
Віддавайте перевагу route‑based (VTI), коли можете. Це відповідає реальній роботі маршрутизації, гарно підтримує динамічну маршрутизацію і простіше для спостережуваності і розуміння.
3) Як швидко довести, що це маршрутизація, а не «VPN»?
Запустіть ip route get для віддаленого хоста на обох шлюзах, потім захопіть пакети на LAN і тунельних інтерфейсах tcpdump. Якщо пакети не заходять у тунель — це маршрутизація/вибір політики. Якщо заходять, але не повертаються — це маршрут повернення або віддалений фаєрвол/NAT.
4) Чому ping працює, а TCP не працює?
Часто це MTU/PMTU і заблоковані ICMP frag‑needed повідомлення. Також деякі середовища по‑іншому обробляють ICMP, ніж TCP. Виміряйте PMTU через tracepath і кламеруйте MSS у разі потреби.
5) Чи потрібно дозволяти ICMP через фаєрволи для VPN?
Ви повинні дозволити ті типи ICMP, які потрібні для PMTU‑виявлення на шляху, особливо «fragmentation needed». Блокування ICMP на всі 100% — шлях до мовчазних чорних дір і довгих інцидентів.
6) Який найшвидший спосіб виявити асиметричну маршрутизацію?
Порівняйте traceroute і результати lookup маршрутів з обох сторін. Також перевірте conntrack‑стани: купа записів SYN_SENT [UNREPLIED] — сильна підказка, що відповіді не повертаються тим же шляхом.
7) Як перекриття підмереж викликає односторонній трафік?
Якщо обидві сторони використовують однаковий RFC1918 діапазон, кожна може вважати призначення «локальним» і робити ARP замість маршрутизації в тунель. Або неправильний маршрут перемагає. Якщо перенумерація неможлива — використайте явний NAT через тунель і документуйте це ретельно.
8) Чи завжди NAT‑T означає, що NAT є на шляху?
Не завжди. Деякі стекі використовують UDP‑інкапсуляцію за політикою для сумісності. Але якщо NAT є і ви не використовуєте NAT‑T — очікуйте проблем: ESP погано співпрацює з трансляцією адрес.
9) Чи може rp_filter зламати VPN‑трафік?
Так. Якщо пакети приходять на інтерфейс, який ядро не вважає найкращим зворотним шляхом для джерела, rp_filter може їх відкинути. У дизайнах з мульти‑WAN або policy‑routing строгий rp_filter часто підводить.
10) Що моніторити, щоб раніше ловити односторонні проблеми?
Моніторьте лічильники байтів/пакетів SA по child SA, дропи інтерфейсів і двобічні синтетичні проби (ICMP + TCP). Сам по собі «тунель підключений» — приємна метрика, але не метрика доступності.
Висновок: наступні кроки, що реально запобігають повторенню
Якщо хочете припинити повернення одностороннього трафіку як сезонну алергію, зробіть ці кроки:
- Запишіть домен шифрування (точні CIDR обох сторін). Ставтесь до цього як до контракту API. Контракти не «майже співпадають».
- Доведіть симетричність маршрутизації за допомогою
ip route getна обох шлюзах для кількох репрезентативних хостів. Зберігайте виводи в записі зміни. - Зробіть NAT явним: додайте винятки VPN вище правил маскараду і переглядайте їх щоразу при змінах інтернет‑егіда.
- Зробіть MTU «нудним»: виміряйте PMTU, кламеруйте MSS якщо потрібно, і перестаньте блокувати ICMP, від якого залежите.
- Автоматизуйте двобічні проби, щоб виявляти «тунель підключений, трафік мертвий» за хвилини, а не через заявку через два дні.
- Тестуйте фейловер як частину системи, бо він нею і є. Більшість односторонніх інцидентів — це історії «працювало, поки щось не змінилося».
Робіть чекліст маршрутизації першим. Це не гламурно, але саме так ви отримаєте VPN, що поводиться як мережа, а не як будинок з привидами.