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

Гості втрачають DNS тієї ж миті, коли піднімається тунель

Підтвердьте картину, перш ніж щось змінювати. Опустіть тунель, виконайте dig @192.168.122.1 example.com з гостьової системи й подивіться, що він відповідає. Підніміть тунель, повторіть і подивіться, що він вичерпує час. Ця пара результатів одним кроком виключає зламану мережу libvirt, неправильну адресу розв'язувача й мертвий dnsmasq.

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

Чому правило accept у пізнішому ланцюгу ніколи не спрацьовує

VPN-міжмережевий екран на мітках вирішує, дивлячись на мітку пакета або мітку з'єднання, а не на вашу адресу джерела. Усе, що надходить на фізичний інтерфейс без очікуваної мітки, відхиляється, і це відхилення відбувається в наборі правил, якому належить перевірка мітки. ip saddr 192.168.122.0/24 accept рядок, доданий до будь-якого пізнішого ланцюга, для цього пакета просто ніколи не розглядається, тому очевидне правило виглядає правильним і нічого не змінює.

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

Механізм, який робить можливим вузький виняток, — відстеження з'єднань. Коли ви задаєте ct mark на пакеті, значення зберігається в записі conntrack, а не лише на пакеті, тож кожен пакет цього з'єднання потім його несе, включно з відповіддю від хоста назад гостю. У цьому вся хитрість: позначте запит один раз, і зворотний шлях уже позначено.

Позначте запит раніше, ніж його побачить таблиця VPN

Помістіть виняток в окрему таблицю, щоб пізніший читач знайшов його, не розбираючи правила VPN:

table inet allowedLocal {
  chain guest_dns {
    type filter hook input priority mangle; policy accept;
    ip saddr 192.168.122.0/24 meta l4proto { tcp, udp } \
      th dport 53 ct mark set 0x00000f41
  }
}

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

Сам номер мітки не є переносним. Візьміть значення, яке встановлені правила VPN приймають для свого власного трафіку, прочитайте його з робочого набору правил і використайте саме його. Неправильна мітка дає правило, яке чисто завантажується, збігається з кожним запитом і нічого не пропускає.

Тримайте діру завширшки в порт 53

Як написано, це дозволяє DNS з підмережі libvirt до хоста через TCP або UDP на порт 53 і нічого більше. Воно не дає гостам вийти в інтернет поза тунелем і не дає хосту відкривати з'єднання в бік гостей. Якщо гостю згодом знадобиться інша служба хоста, додайте окреме правило з іменем цього порту призначення замість послаблення цього.

Будьте чесні щодо того, чим ви торгуєте. Гість, який може дістатися до розв'язувача, може й проштовхнути довільні дані через DNS-запити, і цей виняток — навмисна брехня в кордоні VPN, а не заява про те, що локальна мережа заслуговує довіри. Обмеження джерела до 192.168.122.0/24 тримає діру подалі від кожної іншої локальної підмережі, а підрахунок запитів від цього джерела дешевий, якщо загроза для вас важлива.

Зробіть так, щоб це пережило перезавантаження, і доведіть обидві половини

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

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

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

Схожі статті