Увімкнення клієнта OpenVPN у режимі повного тунелю на машині, до якої ви підключаєтеся через SSH, може обірвати сесію за секунду, і машина при цьому не робить нічого неправильного. Тунель не змінює те, як пакети доходять до сервера; він змінює те, як виходять відповіді. Щойно маршрут за замовчуванням вказує на tun0, відповідь вашому SSH-клієнту потрапляє в мережу постачальника, яка не має маршруту назад до вашої адреси. З’єднання зависає, наступна спроба завершується за таймаутом, а демон увесь час слухає порт 22.

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

Чому відповідь виходить не тими дверима

Вхідні пакети, як і раніше, надходять на фізичний інтерфейс, бо клієнт VPN не може змінити те, як інтернет досягає публічної адреси вашого сервера. Відповіді — окреме рішення: для кожного пакета ядро шукає призначення, і після --redirect-gateway запис за замовчуванням каже тунель. Вихід постачальника бачить адресу, яку не обслуговує, і відкидає пакет.

Власний захист OpenVPN покриває рівно одну адресу. Посібник 2.6 описує --redirect-gateway як послідовність: він додає маршрут до хоста для peer VPN через шлюз, який використовувався до тунелю, щоб зашифрований трафік не міг повернутися в себе, а потім замінює маршрут за замовчуванням. Цей маршрут до хоста призначений лише для peer. Ваш SSH-клієнт — просто ще одна інтернет-адреса і не отримує винятку.

Одну помилку з префіксом варто виключити заздалегідь. ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 без довжини збігається з єдиною адресою 0.0.0.0, а не з інтернетом; має бути 0.0.0.0/0. І якщо взяття маршруту за замовчуванням ламає власний транспорт тунелю, додайте кінцеву точку як маршрут до хоста через фізичний інтерфейс, використовуючи реальну адресу постачальника.

Закріпіть адресу клієнта для негайного виправлення

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

curl -s https://ifconfig.co
ip route

На сервері додайте виняток до запуску клієнта. Адреси тут — заповнювачі; важлива форма:

sudo ip route add 80.128.240.55 via 192.168.178.1

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

Не дайте клієнту взяти маршрут за замовчуванням

Чистіша опція — не дозволяти тунелю замінювати маршрут за замовчуванням узагалі. route-nopull у поєднанні з --client або --pull приймає просунуті параметри, крім маршрутів, block-outside-dns і параметрів у стилі DHCP, як-от DNS-сервери, тож ви додаєте лише потрібні префікси. Вужчий інструмент — фільтр витягування, який відкидає одну проблемну директиву і зберігає решту:

route-nopull
pull-filter ignore "redirect-gateway"

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

Розділіть зворотний шлях за джерелом або з’єднанням

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

ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1

Це працює тому, що відповіді на вхідне SSH-з’єднання походять з адреси, до якої підключився клієнт. В описаному випадку, де кожна вхідна служба мала продовжувати працювати, використовувалася саме така форма. Коли вхідна адреса плаває або шлях динамічний, натомість позначайте з’єднання: поставте позначку conntrack на перший пакет з фізичного інтерфейсу, скопіюйте її на пакети відповіді в OUTPUT і маршрутизуйте позначені пакети через таблицю, що вказує на фізичний шлюз.

iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412

Тримайте позначку з’єднання, позначку міжмережевого екрана і номер таблиці окремо під час тестування. Повторне використання одного номера для двох ролей дає правило, яке виглядає правильним і потрапляє в неправильні пакети. Запису таблиці за замовчуванням також потрібен via зі шлюзом LAN на звичайному каналі Ethernet; голий dev eth0 працює лише коли інтерфейс типу точка-точка або наступний перехід вирішується інакше. Описаний хост Jessie випадково опинився на каналі, де гола форма працювала, і це не правило дистрибутива для копіювання.

Перевірте, не замкнувши себе ззовні

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

ip route get 80.128.240.55

Відповідь має називати фізичний інтерфейс і старий шлюз, а не тунель. Потім відкрийте друге SSH-з’єднання; це справжня перевірка, бо стара сесія може вижити на стані, який нове з’єднання не відтворить. Якщо друге висить, а перше ще відповідає, правило так і не збіглося з важливим трафіком, і шукати треба в позначках або в адресі джерела.

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

Схожі статті