Розмістіть службу на ноутбуці за NAT рівня оператора, спрямуйте цей ноутбук на VPS через VPN, і ніхто ззовні не зможе до нього дістатися. Ви додаєте правило NAT призначення на VPS і отримуєте дещо гірше за тишу: з'єднання відкриваються, а потім зависають. Відповідь не зникає, вона виходить власним маршрутом типового клієнта, тобто сервер її ніколи не бачить. Пройдіть ці п'ять перевірок по порядку й зупиніться на першій, яка не виконується.

Переконайтеся, що сервер узагалі пересилатиме

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

sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1

Задати це в працюючому ядрі не те саме, що задати його через перезавантаження. Запишіть net.ipv4.ip_forward=1 у файл у /etc/sysctl.d/, виконайте sysctl --system, а потім прочитайте значення назад замість того, щоб вірити, що файл підхоплено. Контейнеру, який керує власним простором імен мережі, потрібне те саме значення всередині цього простору, а не лише на хості.

Якщо зворотне читання досі нуль, зупиніться тут. Ніщо далі не працюватиме.

Закріпіть адресу тунелю, перш ніж на неї посилатиметься будь-яке правило

Пул видає адреси в порядку підключень, тож правило, написане для сьогоднішньої оренди, наступного тижня може тихо вказувати на іншого клієнта. Прив'яжіть адресу до ідентичності сертифіката, а не до порядку приходу.

client-config-dir /etc/openvpn/ccd
ifconfig-push 10.77.0.14 10.77.0.13

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

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

Перекладайте в обидва боки

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

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 29443 -j DNAT --to-destination 10.77.0.14:29443
iptables -t nat -A POSTROUTING -d 10.77.0.14 -p tcp --dport 29443 -j SNAT --to-source 10.77.0.13

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

Прочитайте обидва правила назад за допомогою iptables -t nat -S і переконайтеся, що ім'я інтерфейсу — те, яке несе публічну адресу. На хості, що вже фільтрує через nftables, запишіть переклад у ланцюг NAT nftables відповідного сімейства адрес, а не змішуйте інструменти.

Пропустіть таблицю фільтрів

Таблиці NAT переписують заголовки; вони не дають дозволу. За типової політики DROP пересланому потоку потрібен власний дозвіл, плюс зворотний напрямок, який більшість політик уже покривають правилом established,related.

iptables -A FORWARD -i eth0 -o tun0 -p tcp --dport 29443 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Перевірте політику ланцюга FORWARD, перш ніж щось додавати, бо порядок раннього DROP вирішує, чи ваше правило взагалі врахують. На хості, чия фільтрація живе в nftables, додайте еквівалентне правило до гака forward таблиці inet і підтвердьте, що базовий ланцюг справді бачить пересланий трафік, а не лише локальний вхід. Якщо лічильник пакетів на новому правилі лишається нульовим, поки лічильники NAT зростають, пакет відкидається до вашого правила. Це сигнал прочитати порядок ланцюгів, а не додати другу копію того самого правила.

Доведіть це із зовнішньої мережі

Перевірте з незв'язаної мережі. Проба з іншої машини в тому самому LAN може пройти через підтримку hairpin NAT і ніколи не задіяти шлях, який використовує віддалений клієнт, тож зелений результат там доводить неправильне.

tcpdump -ni any port 29443
conntrack -L | grep 29443

Запустіть захоплення на сервері й на клієнті одночасно. Захоплення на сервері показує, чи перекладений пакет виходить у бік тунелю; захоплення на клієнті показує, чи запит надходить і куди адресовано відповідь. Запис перекладу в conntrack -L доводить, що правило збіглося, а його відсутність доводить, що пакет так і не дістався ланцюга NAT.

Сканери портів — слабкий доказ. Вони повідомляють порт як закритий, доки застосунок не прив'язано й не слухає, тож використовуйте справжнє з'єднання зі справжньою службою. Коли це нарешті запрацює, тримайте експозицію на тому одному порті: пересилання SSH або панелі адміністратора, бо перше правило здалося незручним, — це значно більше рішення, ніж публікація служби.

Схожі статті