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

Почніть із двох потоків, які треба розділити

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

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

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

Позначте сокет, який несе конверт

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

mark 42
route-noexec
disable-dco

Десяткове 42 — це шістнадцяткове 0x2a, і саме шістнадцяткову форму зіставлятимуть правила маршрутизації. Довідка з link-options описує mark як те, що застосовується до зашифрованих вихідних пакетів у Linux, тобто рівно до того сокета, чиїм шляхом треба керувати. Вимкнення розвантаження каналу даних утримує цей приклад на шляху простору користувача, де поведінка мітки — та сама описана.

route-noexec придушує автоматичне додавання й видалення маршрутів з боку OpenVPN. Натомість він нічого не встановлює, тож від цього моменту власник маршрутів має підтримувати кожен маршрут, потрібний тунелю. Якщо приватний адресат зникає після зміни, це відсутня політика заміни, а не дефект мітки.

Не тримайте маршрут хоста в головній таблиці для 198.51.100.25, поки робите це. Такий маршрут знову вводить рівно той виняток, який проєкт намагається звузити, і переможе для потоку HTTPS перш ніж буде опитано будь-яку з політик нижче.

Надішліть усе інше до таблиці тунелю

Щойно інтерфейс тунелю існує й тримає свою адресу, політика виглядає так:

ip -4 route add default dev tun1 src 10.90.0.10 table 47100
ip -4 rule add priority 20000 lookup main suppress_prefixlength 0
ip -4 rule add priority 20001 not fwmark 0x2a lookup 47100
ip -4 rule add priority 20002 not fwmark 0x2a unreachable

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

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

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

Нехай зворотний шлях бачить ту саму мітку

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

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

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

Доведіть це двома пошуками маршруту

Порівняйте, що вирішує ядро для двох контекстів, і читайте поля dev і src, а не код виходу:

ip -4 route get 198.51.100.25
ip -4 route get 198.51.100.25 mark 0x2a

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

Запишіть, що проєкт не покриває, перш ніж оголосити його готовим. DNS, IPv6 і життєвий цикл правил потребують кожен свого рішення, і це приклад маршрутизації IPv4, а не повна конфігурація приватності. Його цінність — селектор: конверт отримує виняток аплінку, а звичайна служба за тією самою адресою не зобов'язана його успадковувати.

Схожі статті