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

Знайдіть, де народився пакет

Порядок хуків Netfilter розділяє три випадки, і лише один із них стосується FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

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

Два пакети, одна історія

Коли тунель піднято, внутрішній пакет застосунку і зашифрований зовнішній пакет є різними об’єктами. Внутрішній пакет несе адресу призначення й корисне навантаження, обрані застосунком. Зовнішній пакет несе шифротекст на адресу й порт партнера, і саме він насправді перетинає фізичний інтерфейс.

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

Простори імен зсувають межу

Контейнер ускладнює це, не змінюючи принципу. Запит застосунку — це локальний вивід усередині мережевого простору імен контейнера. Хост отримує цей трафік на віртуальному інтерфейсі Ethernet і може його переслати, тож правило FORWARD на хості може мати сенс, хоча процес, що створив запит, ніколи не торкався ланцюга OUTPUT хоста.

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

Запитайте, чи потрібна вам мітка взагалі

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

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

У iptables еквівалент живе в розкладці mangle OUTPUT, і діє та сама вимога: рішення про маршрутизацію треба переглянути після появи мітки. Далі правило політики має спожити мітку і вказати на таблицю, що містить придатний маршрут. Встановлення мітки conntrack — це третя, окрема операція; вона зберігає значення на потоці й сама по собі не ставить це значення на поточний пакет, щоб маршрутизація могла його прочитати.

Перевірте пошук і лічильник разом

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

Адреса й мітка наведені для прикладу, і два запити маршруту відповідають на різні питання. Другий питає, що зробило б ядро, якби пакет ніс цю мітку; він не показує, що ваш набір правил призначає якусь. Ставтеся до нього як до перевірки гіпотези, а не як до доказу, що політика працює.

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

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

Схожі статті