NAT через VPN для перекритих мереж: як з’єднати їх без жалю

Було корисно?

У вас є дві мережі, які обидві вважають, що вони володіють 10.0.0.0/8. Або ще гірше — обидві 192.168.1.0/24, бо десь хтось наклеїв стікер із «192.168.1.1» і назвав це архітектурою.
Тепер потрібно зробити site-to-site VPN між ними. Самої маршрутизації недостатньо — бо маршрутизація припускає, що IP-адреси мають значення й унікальні. У ваших — ні.

NAT через VPN — це лом, яким ви розсуваєте ці мережі і дозволяєте їм говорити. Він працює. Також легко зробити «майже правильно», при цьому тихо зламавши DNS, логування, ідентичність і будь-який додаток, що вважає IP сталим. Це керівництво, яке я б хотів, щоб більше людей читали перед тим, як кинути тунель у продакшн у п’ятницю.

Коли NAT через VPN — правильний інструмент (а коли — ні)

NAT через VPN існує з однієї основної причини: перекриття адресного простору. Якщо Сайт A і Сайт B мають обидва 10.0.0.0/16, ви не можете їх маршрутизувати, бо «10.0.5.10» не означає одного хоста — воно означає два. Маршрутизація потребує унікальності. NAT її створює, переписуючи адреси при перетині межі.

Використовуйте NAT через VPN коли

  • ви не можете перенумерувати одну сторону вчасно (злиття компаній, мережі вендорів, «тимчасові» лабораторії, що стали продакшном).
  • вам потрібна вузька інтеграція: кілька сервісів через тунель, а не повна сітка з’єднань.
  • вам потрібна жорстка ізоляція: хочете явні межі трансляції й контрольовану досяжність.
  • ви інтегруєте хмарні VPC, створені з однаковими CIDR за замовчуванням різними командами.

Не використовуйте NAT через VPN коли

  • ви можете перенумерувати з розумним радіусом впливу. Перенумерація болить один раз. NAT болить довічно.
  • вам потрібна end-to-end ідентичність на основі IP (деякі старі ACL, крихке ліцензування, гео-правила). NAT перетворить «хто» на «якийсь шлюз».
  • вам потрібні вхідні з’єднання з обох сторін до довільних хостів. NAT може це зробити, але оперативне навантаження швидко зросте.
  • вам потрібна ідеальна прозорість (наприклад, маршрутизуючі протоколи, певні засоби безпеки, деякі протоколи, що вбудовують IP). NAT за визначенням зламує «прозорість».

NAT не є злом. Це компроміс. Беріть його, коли потрібно, а потім проєктуйте так, ніби його перевірить роздратована версія вас у майбутньому.

Ментальна модель, яка не збреше о 2:00 ночі

Ви будуєте межу трансляції через тунель. Тунель — це лише транспорт — WireGuard, IPsec, OpenVPN, GRE over IPsec — не має значення. Важливе таке:
адреси, що використовуються всередині кожної LAN, не повинні бути глобально унікальними, але адреси, що використовуються через межу, мають бути унікальними на цій межі.

Думайте про три простори адрес:

  • Local-real: реальні адреси на Сайті A (наприклад, 10.0.0.0/16).
  • Remote-real: реальні адреси на Сайті B (також 10.0.0.0/16, бо життя — це біль).
  • Translated (virtual): адреси, які ви прикидаєтеся, що має інша сторона, коли дивитесь через VPN (наприклад, «Сайт B стає 172.20.0.0/16, коли його бачить Сайт A»).

Потім вирішуєте напрямок:

  • SNAT (source NAT): «Коли мої хости говорять через тунель, переписувати їхній source-адрес.»
  • DNAT (destination NAT): «Коли трафік приходить через тунель на трансляційну адресу, переписувати його на реальний пункт призначення.»
  • Обидва, часто: SNAT в одному напрямку, DNAT в іншому, щоб кожна сторона бачила іншу як унікальний віртуальний CIDR.

«NAT-пристрій» зазвичай — шлюз VPN. Це добре: централізований контроль, менше рухомих частин, простіше відлагодження. Але це також означає, що цей шлюз стає вашою єдиною точкою істини трансляції — і, отже, єдиною точкою відмови, якщо ви неправильно налаштували conntrack, маршрути або стан фаєрвола.

Жарт №1: NAT — як клейка стрічка. Якщо її використовувати обережно — дійдете додому; якщо використовувати всюди — самі станете цією стрічкою.

Шаблони проєктування: що NATити, де NATити і чому

Шаблон A: «Одна сторона транслює іншу» (унідижнальний переклад)

Сайт A може дістатися до Сайту B, транслюючи Сайт B у неперекритий діапазон, як його бачить A. Сайту B може не потрібно ініціювати з’єднання назад, або він може ініціювати його за окремими правилами.

Підходить для: «A спілкується з вендором», «A забирає метрики з B», «одно-сторонні API виклики».

Ризик: асиметрія. Ви забудете, що це асиметрично, поки інцидент не зажадає зворотної досяжності (віддалена адміністрація, callbacks, mutual TLS з IP-allowlist тощо).

Шаблон B: «Обидві сторони транслюють одна одну» (двосторонні віртуальні CIDR)

Кожна сторона отримує віртуальний вигляд іншої. Приклад:

  • Сайт A реальний: 10.0.0.0/16; Сайт A віртуальний (як його бачить B): 172.21.0.0/16
  • Сайт B реальний: 10.0.0.0/16; Сайт B віртуальний (як його бачить A): 172.22.0.0/16

Це означає:

  • З A ви дістаєтеся до хостів B через 172.22.x.y.
  • З B ви дістаєтеся до A через 172.21.x.y.

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

Ризик: більше правил NAT, більше складності, більше «почекай, яку адресу ти тестував?» моментів.

Шаблон C: NAT лише для «зон колізії»

Іноді перекривається лише частина CIDR. Приклад: обидві сторони використовують 10.10.0.0/16, але Сайт A також має 10.20.0.0/16, що не перекривається.
Ви можете маршрутизувати унікальну частину напряму і NATити тільки перекритий фрагмент.

Підходить для: зменшення обсягу трансляції й збереження справжніх source IP, коли це можливо.

Ризик: операційна нюансність. Усунення несправностей стає «цей сервіс маршрутизований, а той — NATований», що фактично є пасткою для нового on-call.

Де ставити NAT: шлюз vs хост vs виділений middlebox

  • NAT на шлюзі VPN: найкращий дефолт. Одне місце для керування станом, фаєрволом і логуванням.
  • NAT на окремих хостах: уникайте, якщо не любите «сніжинок». Це ламає уніфіковану політику і перетворює міграції на мистецький проєкт.
  • Виділений NAT middlebox: корисно, коли VPN завершується на керованому обладнанні, яке не можна налаштувати, або коли потрібні пари HA і чітке розділення.

Вибирайте транслювані CIDR як паролі: неочевидні

Не переводьте одну сторону в 192.168.0.0/16, якщо вам подобається колізія з домашніми мережами, кав’ярнями VPN і тим незручним керівником, що підключається через tether під час аварій.
Обирайте щось на кшталт 172.20.0.0/14 або вирізок з 100.64.0.0/10 (CGNAT-простір), якщо середовище це дозволяє. Будьте послідовні й документуйте.

Стан, conntrack і чому «воно пінгується» — це не рев’ю дизайну

Більшість реалізацій NAT залежать від відстеження сесій. Це означає:

  • Повернення трафіку має проходити через той самий шлюз (симетрія).
  • Перехід на резерв без синхронізації стану може зламати активні потоки.
  • Висока інтенсивність з’єднань може виснажити таблиці conntrack.

Якщо ваш додаток використовує довготривалі з’єднання (БД, брокери повідомлень), плануйте це. Якщо він використовує короткі сплески (HTTP без keepalive, певні RPC-патерни), плануйте ще ретельніше.

Що ламається, якщо зробити неправильно

NAT через VPN ламається передбачуваними, нудними способами. Проблема в тому, що ви зазвичай виявляєте їх у найменш вдалий момент.

1) Маршрутизуючі цикли та чорні діри

Якщо ви транслюєте трафік у CIDR, який вже маршрутизується кимось іншим, ви створюєте цикл або западину. Ваш моніторинг може показувати «VPN up», поки пакети виконують інтерпретативний танок між маршрутизаторами.

2) Асиметричні шляхи повернення (тихий вбивця)

NAT є станним. Якщо вихідний трафік іде через Шлюз A, а повернення повертається через Шлюз B, у Шлюза B немає запису conntrack, тож він скидає або неправильно NATить. Симптоми виглядають як «працює в один бік» або «SYN-SYN/ACK-і більше нічого».

3) DNS і плутанина імен‑в-адреси

Якщо Сайт A резолвить db.siteb.internal у реальну адресу (10.0.5.10), але повинен достукатися через трансляційну адресу (172.22.5.10), ваші додатки падають, хоча мережевий шлях нормальний.
Виправлення мережі недостатньо; потрібно виправити найменування.

4) Allowlist на основі IP і колапс ідентичності

Коли ви робите SNAT, віддалий бік може бачити весь трафік як такий, що йде з трансляційної IP шлюзу. Ваша політика «allowlist цього підмережі» стає «дозволь шлюз».
Це не обов’язково неправильно — але це змінює модель загроз і історію аудиту.

5) Протоколи, що вбудовують IP-адреси

Деякі протоколи несуть IP-літерали в payload. Класичні приклади: певні режими FTP, SIP/VoIP, деякі VPN-in-VPN архітектури, старі механізми ліцензування та додатки, що саморекламують кінцеві точки.
NAT переписує заголовки, не payload — якщо тільки ви не додаєте application-layer gateway (а ви, ймовірно, цього робити не будете).

6) Логування та форензіка стають менш правдивими

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

7) MTU і фрагментація ведуть себе дивно

Інкапсуляція VPN зменшує ефективний MTU. NAT цього не спричиняє, але розгортання NAT-over-VPN часто супроводжується «ми додали тунель і тепер деякі HTTPS виклики зависають».
Ви побачите проблеми PMTUD, заблоковані ICMP і «малі пакети працюють».

Жарт №2: VPN був «увімкнений» весь час. Як і Титанік.

Цікаві факти та історичний контекст

  • NAT не був частиною початкового плану Інтернету. Він став масовим у середині 1990-х, коли виснаження IPv4 став реальністю, і організації захотіли приватні мережі.
  • RFC 1918 (приватні IPv4 діапазони) — з 1996 року. Він формалізував 10/8, 172.16/12 та 192.168/16, що дозволило еру «всі використовують 10.0.0.0/8».
  • IPsec спочатку не любив NAT. Ранній IPsec ESP захищав заголовки так, що вони погано працювали з NAT-пристроями; з’явився NAT Traversal (NAT-T) для вирішення цього.
  • Carrier-grade NAT (CGNAT) нормалізував масштабну трансляцію. Ось чому існує простір 100.64.0.0/10 — бо NAT на краю вже не вистачав.
  • NAT порушує принцип end-to-end. Цей принцип передує сучасній «zero trust», але напруженість усе ще видна: трансляція додає проміжний стан.
  • Linux conntrack таблиці десятиліттями були обмеженням продакшну. Високі швидкості з’єднань можуть виснажити стан набагато раніше, ніж CPU впаде.
  • Багато підприємств випадково стандартизувалися на тих самих підмережах. Шаблони VPC/VNet за замовчуванням і «скопіюй VLAN-план з останнього сайту» створили перекриття як звичний бізнес-результат.
  • Policy-based routing існує довше за багато хмарних VPN сервісів. Старі інженери мереж використовували його, щоб спрямовувати трафік через NAT і тунелі задовго до появи категорії продуктів «Transit Gateway».

Одна цитата, яку варто тримати на стікері:
Все ламається, весь час. — Werner Vogels

Три корпоративні міні-історії з копальні NAT

Міні-історія 1: Інцидент через неправильне припущення

Середня компанія придбала меншу. Обидві сторони використовували 10.0.0.0/16 внутрішньо, бо так буває. План інтеграції: «швидкий IPsec тунель, NAT для придбаної сторони в 172.20.0.0/16, готово».
Це працювало в лабораторії. Навіть працювало тиждень у продакшні.

Потім зламалася обробка зарплат. Не цілком — достатньо, щоб стати інцидентом із увагою керівництва. SRE на чергуванні бачив успішні ping-и і робочі TCP-з’єднання від ап-серверів до payroll API. Але API повертав 403.
Це те, за що люди звичайно звинувачують VPN, фаєрвол або місяць.

Корінь проблеми: payroll API мав allowlist на основі IP. Під час тестування source IP були окремими хостами. У продакшні нове «cleanup» правило SNAT-ило весь вихідний трафік в одну трансляційну IP-адресу шлюзу, щоб спростити політики.
Allowlist не містив IP шлюзу. Ніхто не подумав, що NAT змінить ідентичність, бо «ми просто робимо маршрутизацію».

Виправлення: оновити allowlist-и, додати SNAT-пули за підмережами, щоб різні рівні апів зберегли грубу ідентичність, і — найголовніше — записати, що NAT змінює атрибуцію і повинен перевірятися з контролем безпеки.
Тунель був нормальний. Припущення — ні.

Міні-історія 2: Оптимізація, що відмовила

Інша організація мала стабільне NAT-over-VPN, але CPU шлюзу був вищим ніж очікували в пікові години. Інженер вирішив «оптимізувати», вимкнувши відстеження з’єднань там, де можна, і використовуючи статeless правила плюс маршрутизуючі хитрощі.
Для кількох протоколів це виглядало як безкоштовний приріст продуктивності.

Через два тижні випадкові дзвінки клієнтів почали падати — періодично. Деякі запити проходили; інші зависали. Хронологія інциденту була безладною, бо VPN залишався підключеним і пакетні втрати були неочевидні.
Це проявлялося переважно як таймаути на шарі додатків, що викликало повтори, що збільшувало навантаження і спричиняло ще більше таймаутів. Класика.

Справжня причина була тонкою: деякі потоки мали трохи інший шлях повернення після зміни маршруту на віддалому боці. З вимкненим conntrack для того класу трафіку NAT-мапінги були нестабільні для довготривалих сесій, і стан фаєрвола більше не відповідав очікуванням додатка.
Система зійшла в напівполаманий стан, який важко було відтворити на вимогу.

Виправлення: повернути conntrack, зробити маршрутизацію симетричною за допомогою політик, масштабувати шлюз (більший інстанс, кращі NIC offloads, адекватне розмірювання conntrack).
«Оптимізація» зекономила CPU і витратила надійність. Це не вигідна угода.

Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію

Глобальна компанія запустила NAT-over-VPN між фабричною мережею і центральним ERP. Нічого особливого: пара транслюваних CIDR, жорсткі правила фаєрволу і процес зміни, що вимагав три речі: діаграму, план тестування і план відкату.

Одного вечора подія у провайдера спричинила флапінг і failover на резервний VPN-headend. Резерв був налаштований коректно, але не синхронізував conntrack-стан (бо більшість налаштувань цього не робить).
Кілька довготривалих сесій впали, спрацювали тривоги, і черговий почав хвилюватися.

Ось нудна частина: у їхньому ранбуці був відомий «процедура сливу сесій». Вони тимчасово зменшили інтервали keepalive у шарі додатку, форсували перепідключення у контрольованому вікні і валідували відновлення за чеклістом синтетичних транзакцій.
Це не було елегантно. Це було передбачувано.

Результат — інцидент локалізували, мінімальна неконсистентність даних і постмортем без фрази «ми не були впевнені, що роблять правила NAT».
Нудна практика перемагає. Нудна масштабується.

Практичні завдання: команди, очікуваний вивід, рішення

Мета налагодження NAT-over-VPN — припинити гадати. Нижче завдання, які можна виконати на Linux-шлюзах і тестових хостах. Кожне містить:
команду, що означає вивід, і яке рішення прийняти далі.

Завдання 1: Підтвердити перекриття і знайти колізію

cr0x@server:~$ ip -brief addr
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             10.0.1.1/24
wg0              UP             10.200.0.1/24

Значення: Цей шлюз в локальній мережі на 10.0.1.0/24 і має тунельний інтерфейс wg0.
Якщо віддалий бік також 10.0.1.0/24 (або щось що перекривається), чиста маршрутизація зіткнеться.
Рішення: Оберіть трансляційний CIDR, якого немає на жодній стороні (і не з’явиться пізніше).

Завдання 2: Перевірити таблицю маршрутизації на неоднозначні маршрути

cr0x@server:~$ ip route show
default via 10.0.1.254 dev eth0
10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.1
10.200.0.0/24 dev wg0 proto kernel scope link src 10.200.0.1

Значення: Поки що немає явного маршруту для віддаленого трансляційного CIDR.
Рішення: Додайте маршрут для віддаленого трансляційного CIDR через тунельний інтерфейс (або через таблицю політичної маршрутизації, якщо потрібно).

Завдання 3: Перевірити, що VPN-хеншейк дійсно встановлений (приклад WireGuard)

cr0x@server:~$ sudo wg show
interface: wg0
  public key: 3xQk...redacted
  listening port: 51820

peer: c0z9...redacted
  endpoint: 198.51.100.20:51820
  allowed ips: 10.200.0.2/32
  latest handshake: 31 seconds ago
  transfer: 48.22 MiB received, 51.10 MiB sent

Значення: Тунель увімкнений і передає трафік.
Рішення: Якщо handshake застарів, зупиніться і виправте підключення/ключі/UDP доступність перед тим, як лізти в NAT.

Завдання 4: Підтвердити, що IP-форвардинг увімкнений на шлюзі

cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Значення: Ядро форвардить пакети між інтерфейсами.
Рішення: Якщо 0, увімкніть і збережіть через /etc/sysctl.d/. Без цього ви звинуватите NAT у проблемі маршрутизації.

Завдання 5: Перевірити, чи rp_filter не відкине асиметрично маршрутизовані пакети

cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1

Значення: Строге зворотне шляхове фільтрування увімкнено глобально. При політичній маршрутизації або кількох uplink-ах rp_filter може скидати коректний трафік.
Рішення: Для VPN NAT-шлюзів розгляньте встановлення 2 (loose) на відповідних інтерфейсах, якщо ви навмисно використовуєте асиметричну маршрутизацію.

Завдання 6: Побачити пакети до та після NAT за допомогою tcpdump

cr0x@server:~$ sudo tcpdump -ni eth0 host 10.0.1.50 and port 443 -c 3
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:00:01.100000 IP 10.0.1.50.51544 > 172.22.5.10.443: Flags [S], seq 1000, win 64240, options [mss 1460], length 0
cr0x@server:~$ sudo tcpdump -ni wg0 host 172.22.5.10 and port 443 -c 3
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
12:00:01.100500 IP 172.21.1.50.51544 > 172.22.5.10.443: Flags [S], seq 1000, win 64240, options [mss 1360], length 0

Значення: В LAN джерело — 10.0.1.50; у тунелі джерело стало 172.21.1.50 (SNAT застосовано). MSS теж змінилось (ефект інкапсуляції).
Рішення: Якщо не бачите транслюваний source у тунелі, ваше правило NAT не збігається або стоїть у неправильному ланцюгу/гачку.

Завдання 7: Перевірити правила NAT (приклад iptables legacy)

cr0x@server:~$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.0.1.0/24 -d 172.22.0.0/16 -o wg0 -j SNAT --to-source 172.21.0.1
-A PREROUTING -i wg0 -d 172.21.0.0/16 -j DNAT --to-destination 10.0.1.0/24

Значення: Є SNAT для трафіку, що йде в віддалений трансляційний CIDR. Є також DNAT-правило, яке виглядає неправильно: DNAT на цілу CIDR в такому вигляді не є валідним і вказує на плутанину.
Рішення: Використовуйте детерміновані 1:1 mapping-правила (NETMAP) або явний DNAT на хост/сервіс, а не «DNAT на мережу», якщо ви не знаєте, що підтримує ваше ПЗ.

Завдання 8: Перевірити правила NAT (приклад nftables)

cr0x@server:~$ sudo nft list ruleset
table ip nat {
  chain prerouting {
    type nat hook prerouting priority dstnat; policy accept;
    iifname "wg0" ip daddr 172.21.0.0/16 dnat to 10.0.1.0/24
  }
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    oifname "wg0" ip saddr 10.0.1.0/24 ip daddr 172.22.0.0/16 snat to 172.21.0.1
  }
}

Значення: Подібна проблема: DNAT-спроба концептуально некоректна. DNAT потребує конкретного призначення (або construct mapping), а не «усі ці йдуть у ту мережу».
Рішення: Переробіть з використанням 1:1 netmapping (NETMAP) або використайте пару невзаємоперекритих віртуальних CIDR з детермінованою трансляцією.

Завдання 9: Підтвердити, що conntrack бачить NAT-ований потік

cr0x@server:~$ sudo conntrack -L -p tcp --dport 443 | head -n 3
tcp      6 431999 ESTABLISHED src=10.0.1.50 dst=172.22.5.10 sport=51544 dport=443 src=172.22.5.10 dst=172.21.0.1 sport=443 dport=51544 [ASSURED] mark=0 use=1

Значення: Conntrack показує оригінальний кортеж і трансляційний кортеж. Це добре.
Рішення: Якщо таблиця пуста, поки трафік йде, conntrack може бути оминутим або зламаний — очікуйте періодичних збоїв під навантаженням.

Завдання 10: Перевірити ємність conntrack перед тим, як це стане «випадковими» відкидами

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 24891
net.netfilter.nf_conntrack_max = 262144

Значення: Ви на ~9.5% використання. Нормально.
Рішення: Якщо count підходить до max в пікові, збільшіть max (з урахуванням пам’яті) і налаштуйте таймаути під ваш профіль трафіку.

Завдання 11: Виявити проблеми MTU за допомогою DF ping (класична VPN-біль)

cr0x@server:~$ ping -M do -s 1472 172.22.5.10 -c 2
PING 172.22.5.10 (172.22.5.10) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1420
ping: local error: message too long, mtu=1420

--- 172.22.5.10 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1030ms

Значення: Ефективний MTU — 1420; спроба відправити 1500-байтові фрейми з DF завершується помилкою.
Рішення: Обмежте MSS на тунелі/фаєрволі або встановіть MTU інтерфейсу відповідно. Також переконайтесь, що ICMP «frag needed» не блокується.

Завдання 12: Підтвердити, що віддалений бачить правильний source (перевірка впливу на додаток)

cr0x@server:~$ curl -sS --connect-timeout 3 https://172.22.5.10/whoami
{"remote_addr":"172.21.0.1","x_forwarded_for":null}

Значення: Віддалий додаток бачить SNAT-адресу шлюзу, а не початковий хост.
Рішення: Якщо віддалому додатку потрібна ідентифікація клієнта, не SNATьте все в одну IP. Використовуйте 1:1 mapping або SNAT-пул і оновіть allowlist-и.

Завдання 13: Перевірити політичну маршрутизацію, коли потрібно зберегти симетрію NAT

cr0x@server:~$ ip rule show
0:      from all lookup local
100:    from 10.0.1.0/24 to 172.22.0.0/16 lookup 100
32766:  from all lookup main
32767:  from all lookup default
cr0x@server:~$ ip route show table 100
172.22.0.0/16 dev wg0 scope link

Значення: Трафік з локального підмережі до віддаленого трансляційного CIDR змушується у таблицю 100, яка маршрутизує його через тунель.
Рішення: Якщо у вас кілька WAN або тунелів, це спосіб зберегти шляхи повернення консистентними і уникнути втрати NAT-стану.

Завдання 14: Перевірити лічильники фаєрвола, щоб довести, що саме відкидається

cr0x@server:~$ sudo iptables -vnL FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in  out source        destination
 812K  92M ACCEPT     all  --  eth0 wg0 10.0.1.0/24  172.22.0.0/16
 221K  21M ACCEPT     all  --  wg0 eth0 172.22.0.0/16 10.0.1.0/24
  512  42K DROP       all  --  *   *   0.0.0.0/0     0.0.0.0/0

Значення: Форвард дозволений в обох напрямках для тих CIDR, і лічильники зростають. Також є дефолтний drop.
Рішення: Якщо лічильники на ACCEPT правилах залишаються нульовими під час тесту, ваш трафік не досягає цієї машини або не відповідає CIDR, які ви вважаєте (несумісність трансляції, неправильний інтерфейс, неправильний маршрут).

Завдання 15: Підтвердити, що віддалений має маршрут назад до вашого трансляційного простору

cr0x@server:~$ ip route get 172.21.1.50
172.21.1.50 dev wg0 src 10.200.0.2 uid 0
    cache

Значення: Віддалий знає, що повертати 172.21.0.0/16 треба через тунельний інтерфейс.
Рішення: Якщо віддалий намагається відправити 172.21.0.0/16 до свого дефолтного шлюзу, ви отримаєте односторонній трафік і будете звинувачувати NAT. Додайте маршрут.

Швидкий план діагностики

Це порядок дій, що дозволить швидше дійти до вузького місця, не виконуючи інтерпретативні NAT-маніпуляції на живому інцидентному мосту.

По-перше: доведіть, що тунель і маршрути справжні

  1. Стан VPN: handshake/SA встановлені, байти інкрементуються. Якщо ні — зупиніться.
  2. Маршрути: кожна сторона має маршрут до трансляційного CIDR через тунель. Немає маршруту — нема шляху повернення — нема радості.
  3. Форвард і фаєрвол: ip_forward=1; ланцюг FORWARD дозволяє трафік; лічильники рухаються.

По-друге: доведіть, що трансляція справді відбувається

  1. tcpdump на обох інтерфейсах: побачити оригінальний кортеж в LAN і трансляційний в тунелі.
  2. запис conntrack існує: підтвердити NAT-стан для потоку.
  3. віддалий бачить очікуваний source: перевірити простим endpoint-ом або логами сервера.

По-третє: знайдіть «пінг працює, а додатки — ні» проблеми

  1. MTU/MSS: робіть DF пінги; стежте за зависаннями TLS/HTTP POST.
  2. DNS: підтвердіть, що імена резолвляться у трансляційні адреси (або забезпечте split-horizon).
  3. Allowlist/автентифікація: перевірте, чи віддалий очікує реальні IP клієнтів; NAT може їх зруйнувати.

По-четверте: перевірте масштаб і старіння стану

  1. ємність conntrack і таймаути під навантаженням.
  2. CPU softirq / NIC drops на шлюзах (сатурація переривань виглядає як втрата пакетів).
  3. поведінка HA при відмові: втрата стану і асиметричні шляхи після failover.

Типові помилки: симптом → корінь → виправлення

1) «Я можу пінгувати, але TCP таймаутиться»

Симптоми: ICMP працює, малі запити працюють, завантаження або TLS-рукопотискання зависають.

Корінь: MTU/PMTUD проблеми через інкапсуляцію; ICMP «frag needed» заблокований; відсутнє MSS-clamping.

Виправлення: обмежити MSS на трафіку через тунель, встановити правильний MTU на тунельному інтерфейсі, дозволити потрібний ICMP.

2) «Працює зі шлюзу, не працює з хостів за ним»

Симптоми: Шлюз може дістатися віддаленого сервісу, а внутрішні хости — ні.

Корінь: відсутні FORWARD-правила, відсутній SNAT для форварденого трафіку або відсутній маршрут повернення для трансляційного клієнтського підмережі.

Виправлення: увімкнути форвардинг, додати правила FORWARD, реалізувати SNAT і додати віддалений маршрут назад до трансляційного діапазону клієнтів.

3) «Один напрямок працює; зворотний — ні»

Симптоми: A→B працює, B→A падає (або навпаки). Або SYN виходить, SYN/ACK не доходить.

Корінь: асиметрична маршрутизація через HA-шлюзи або кілька WAN; стан conntrack є лише на одній ноді.

Виправлення: забезпечити симетричну маршрутизацію за допомогою політичної маршрутизації; використовувати active/standby; розглянути синхронізацію conntrack, якщо дійсно потрібен active/active.

4) «Віддалений додаток повертає 403/unauthorized після зміни NAT»

Симптоми: Мережеве з’єднання нормальне; додаток відмовляє в доступі.

Корінь: Allowlist на основі IP бачить IP шлюзу NAT, а не оригінальних клієнтів.

Виправлення: оновити allowlist-и; використовувати 1:1 трансляцію або SNAT-пули; переносити авторизацію вище по стеку, де можливо.

5) «Деякі хости досяжні, інші — ні»

Симптоми: Працює підмножина віддалених хостів; інші — чорні діри.

Корінь: часткове перекриття; неправильний або неповний netmapping; маршрути існують для деяких трансляційних діапазонів, але не для інших.

Виправлення: мапити детерміновано і покривати весь потрібний діапазон; аудіювати маршрути на обох сторонах; уникати змішування маршрутизованих і NAT-ованих сегментів без чіткої документації.

6) «Після failover все ламається, поки ми не перезапустимо щось»

Симптоми: HA-подія спричиняє масові таймаути; поступове відновлення після витікання сесій або рестартів сервісів.

Корінь: втрата conntrack/NAT стану під час failover; довготривалі сесії не перепідключуються коректно.

Виправлення: віддавати перевагу active/standby з стабільною маршрутизацією; скоротити keepalive; погодитися, що деякі сесії впадуть і проектувати ретраї; додати контрольовані процедури дренажу.

7) «DNS резолвить, але з’єднання йдуть не туди»

Симптоми: Клієнт резолвить віддалене ім’я, але потрапляє на локальний хост з тією ж IP або на неправильний сервіс.

Корінь: DNS повертає реальну (перекриту) адресу; локальна маршрутизація віддає перевагу локальній підмережі.

Виправлення: split-horizon DNS або умовний форвардинг, що повертає трансляційні адреси; не витрачайте реальні перекриті IP через межу.

8) «Раніше було нормально; тепер падає під навантаженням»

Симптоми: Періодичні збої під час піку; логи показують помилки вставки в conntrack або відкидання.

Корінь: виснаження таблиці conntrack; недостатня ємність NAT-стану; сатурація CPU softirq.

Виправлення: збільшити nf_conntrack_max, налаштувати таймаути, масштабувати ресурси шлюзу і виміряти втрати пакетів на NIC та в ядрі.

Чеклісти / покроковий план

Покроково: розумне розгортання NAT через VPN

  1. Перелічіть адресний простір з обох сторін: реальні CIDR, DHCP-діапазони, статичні блоки та «таємні» лабораторні мережі.
  2. Оберіть трансляційні CIDR, що не конфліктують з жодною стороною, з запасом для росту. Запишіть їх у спільному місці.
  3. Визначте напрям трансляції: унідижнально чи двосторонньо. За замовчуванням обирайте двосторонньо лише якщо це дійсно потрібно.
  4. Визначте детальність трансляції:
    • 1:1 netmapping для збереження ідентичності хостів
    • many-to-one SNAT для простоти (прийміть втрату ідентичності)
  5. Реалізуйте маршрути до трансляційних CIDR на обох сторонах (статично або через систему маршрутизації, якщо доречно).
  6. Реалізуйте правила NAT з явним матчингом: source CIDR, destination CIDR, ingress/egress інтерфейси.
  7. Реалізуйте правила фаєрволу так, ніби NAT не існує: дозволяйте лише потрібні порти/сервіси через трансляційні CIDR.
  8. Виправте DNS: split-horizon, умовний форвардинг або явні хости для трансляційних імен. Якщо DNS помилковий — все здається неправильним.
  9. Опрацюйте MTU: встановіть MTU тунелю і обмежте MSS, якщо потрібно. Тестуйте DF пінгами і реальними потоками додатків.
  10. Логуйте трансляції: зберігайте логи NAT/фаєрволу (з лімітом швидкості) і майте видимість pre- і post-NAT кортежів.
  11. Тестуйте навантаження conntrack: переконайтесь у запасі під очікуваний пік з коефіцієнтом сплеска.
  12. Напишіть і відрепетируйте план відкату: видалення NAT рідко миттєве; плануйте шлях «вимкнути NAT, зберегти тунель» і «вимкнути тунель».

Чекліст перед зміною (що перевірити перед вмиканням)

  • Трансляційні CIDR не з’являються в ip route на жодній стороні, крім запланованих VPN-маршрутів.
  • Умовні DNS відповіді повертають трансляційні адреси для протилежного сайту.
  • Дефолтна політика фаєрволу явна і протестована.
  • MTU/MSS протестовані з реальними розмірами payload (не лише ping).
  • Розмір conntrack перевірено; є моніторинг для nf_conntrack_count і лічильників відкидів.

Чекліст після зміни (що перевірити одразу після)

  • tcpdump підтверджує pre/post NAT адреси на правильних інтерфейсах.
  • Віддалені логи показують очікувані source-адреси (і контролі безпеки все ще працюють).
  • DNS резолв з обох сторін повертає правильний вигляд.
  • Довготривалі сесії (БД, брокери) тримаються щонайменше годину без падінь.
  • On-call має односторінковий ранбук з трансляційними CIDR і тестовими командами.

Питання й відповіді

1) Чи можу я уникнути NAT, просто додаючи більш специфічні маршрути?

Ні, коли перекриття точне або неоднозначне. Якщо обидві сторони мають 10.0.1.0/24, маршрут не скаже, який саме 10.0.1.50 ви мали на увазі. Потрібна унікальність — або перенумерувати, або транслювати.

2) Чи те саме NAT через VPN і NAT-T?

Ні. NAT-T (NAT Traversal) — це техніка для дозволу роботи IPsec через NAT-пристрої шляхом інкапсуляції в UDP. NAT-over-VPN — це навмисна трансляція адрес через тунель для вирішення перекриттів.

3) Використовувати SNAT, DNAT чи 1:1 mapping?

Якщо віддаленій стороні потрібно розрізняти хости (allowlist-и, логування, політики по хостах), використовуйте детермінований 1:1 mapping. Якщо потрібно просто «клієнти можуть дістатися сервісу», SNAT в одну IP простіше, але приховує ідентичність.

4) Де має жити NAT?

На шлюзі VPN, якщо немає сильної причини інакше. Централізація NAT зменшує конфігураційний дріфт і робить packet capture та фаєрвол-політику послідовними.

5) Як обробляти DNS з трансляційними адресами?

Використовуйте split-horizon DNS: кожен сайт отримує відповіді, що мають сенс для його вигляду. Якщо Сайт A має дістатися Сайту B через 172.22.0.0/16, DNS Сайту A має повертати 172.22.x.y для імен B.

6) Чи NAT зламає mutual TLS або перевірку сертифіката?

Прямо — ні; TLS не дивиться на source IP. Але якщо ваші політики авторизації (поза TLS) використовують IP-allowlist-и, NAT змінює те, ким віддалений думає, що ви є.

7) Чи можу я запустити active/active NAT-шлюзи для HA?

Можна, але обережно. Без синхронізації стану і симетричної маршрутизації ви зламаєте потоки. Active/standby простіше для stateful NAT, і «простота» — це перевага.

8) Чому це працює для одних додатків, а для інших — ні?

Зазвичай через одну з трьох причин: MTU проблеми, DNS повертає реальні (перекриті) IP, або додаток вбудовує IP-адреси / очікує client IP для авторизації.

9) Чи IPv6 — це справжнє рішення?

IPv6 зменшує тиск через нестачу адрес і проблему перекриттів, але не магічно не вирішує існуючі IPv4-пристрої, вендорські апарати або ваш поточний графік M&A. Це стратегія, а не сьогоднішній міра.

10) Який найкращий спосіб документувати NAT через VPN, щоб люди перестали його ламати?

Діаграма, що показує реальні й трансляційні CIDR, таблиця правил NAT простою мовою і невеликий набір тестів з очікуваними результатами. Додатково: внесіть трансляційні діапазони в IPAM, якщо він у вас є.

Висновки: наступні кроки, що дійсно зменшують ризик

NAT через VPN — цілком поважне рішення для перекритих мереж, якщо ви ставитесь до нього як до першокласного дизайну, а не як до тимчасового хаку, що дивним чином залишається тимчасовим.
Робота — це не лише правила NAT. Це симетрична маршрутизація, правильний DNS, обробка MTU, логування та планування ємності для стану.

Практичні наступні кроки:

  1. Запишіть трансляційні CIDR і зарезервуйте їх як реальний адресний простір.
  2. Оберіть модель трансляції (1:1 проти many:1) на основі потреб в ідентичності, а не зручності.
  3. Побудуйте мінімальний тестовий набір: ping з DF, TCP connect, реальний HTTP запит і один тест довготривалої сесії.
  4. Додайте моніторинг для використання conntrack, відкидів пакетів і лічильників байтів VPN.
  5. Проведіть drill з відмови, якщо у вас є HA. Якщо ні — признайте це і запрограмуйте очікування щодо простою відповідно.

Якщо ви можете перенумерувати пізніше — зробіть це. Але якщо ні — зробіть NAT через VPN нудним, передбачуваним і добре освітленим. Інциденти все одно відбуватимуться — просто з менше містики й меншою кількістю людей, що кричать на packet captures.

← Попередня
Еволюція VRAM: від простого GDDR до повної божевільності
Наступна →
ZFS txg_timeout: чому записи йдуть пакетами (і як згладити затримки)

Залишити коментар