Debian 13: розділений DNS для VPN і LAN — надійне налаштування, яке не ламається після перезавантаження

Було корисно?

Розділений DNS — це одна з тих задач, яка мала би бути нудною, але перетворюється на витратний уікенд, бо хтось перезавантажив ноутбук,
VPN перепідключився, і раптом git.company.internal починає резолвитися в публічний інтернет (або, що ще гірше, взагалі не резолвиться).
Якщо ви коли-небудь бачили, як розгортання в production зависає через те, що билд-агент втратив внутрішній DNS посеред процесу — ви знаєте це відчуття:
це не драматично, але дорого.

Debian 13 може чисто реалізувати розділений DNS. Трюк у тому, щоб обрати одну контрольну площину для DNS і зробити так, щоб усе інше їй підпорядковувалось.
Ця стаття пропонує налаштування, яке виживає після перезавантаження, зміни Wi‑Fi, перепідключення VPN і «корисних» DHCP-серверів.

Що ви будуєте (і що ні)

Розділений DNS означає: певні домени резолвяться через конкретні DNS-сервери, тоді як усе інше використовує ваш «звичайний» DNS.
Типовий приклад:

  • *.corp.internal та *.svc.cluster.local резолвяться через DNS-сервери VPN
  • все інше резолвиться через локальний LAN DNS (або публічні резолвери)

Ви не будуєте фермy DNS-серверів. Ви створюєте детермінований клієнтський конфіг для резолвера, який:
(1) маршрутизує правильні імена до правильних резолверів, (2) не «виливає» внутрішні запити у публічний DNS, і (3) залишається стабільним після перезавантажень.

Ваш ворог — не сама складність DNS. Це конфліктуючі менеджери DNS. Debian-системи часто мають кілька акторів, що тягнуть /etc/resolv.conf у різні боки:
NetworkManager, systemd-resolved, VPN-клієнти, DHCP-клієнти і іноді чиїсь dotfiles з 2014 року.

Цікавинки і коротка історія (бо контекст рятує від болю)

  1. Розділений DNS передує хайпу навколо VPN: у підприємствах його застосовували раніше для split-horizon зон, де внутрішні імена ніколи не мають резолвитися зовні.
  2. Формат /etc/resolv.conf навмисно простий — настільки простий, що він не може виразити маршрутизацію за доменом. Для split DNS потрібен розумніший інструмент.
  3. «Маршрутні домени» systemd-resolved (концепція ~domain) призначені саме для того, щоб сказати «цю суфіксну зону спрямовувати на DNS цього інтерфейсу».
  4. Класичне «обмеження до 3 nameserver» у resolv.conf не лише фольклор: багато резолверів все ще поводяться так, і порядок може підвести.
  5. Негативне кешування (пам’ять NXDOMAIN) може робити DNS привидним: ви полагодите сервер, а клієнти все одно будуть падати, поки кеш не завершиться.
  6. DNS search-домени старші за більшість сучасних VPN-інструментів, і їх часто зловживають. Довгий список пошуку підвищує навантаження та викликає сюрпризи.
  7. «DNS-leaks» часто не про приватність — вони про надійність. Внутрішні зони, запитані через публічний DNS, повертають NXDOMAIN і ламають застосунки.
  8. Багато корпоративних VPN історично нав’язували повний контроль над DNS, бо старі клієнти не вміли маршрутизувати по доменам; ця звичка ще живе.

Парафраз ідеї від Werner Vogels (CTO Amazon): все ламається постійно; проєктуйте системи, припускаючи, що відмови — норма.
Розділений DNS — це маленька ілюстрація цієї філософії: проєктуйте під флапи інтерфейсів і перепідключення.

Вибір архітектури, який реально працює

Обрати одного власника DNS-рішень

На Debian 13 найчистіший підхід: нехай systemd-resolved буде движком політики резолвера.
Нехай NetworkManager (або ваш VPN-клієнт) подає йому DNS-сервери та домени, прив’язані до інтерфейсів.
Потім вкажіть /etc/resolv.conf на stub resolved.

Чого слід уникати: стек, де кожен робить по-своєму — NetworkManager перезаписує /etc/resolv.conf,
VPN його перезаписує, і post-up скрипт намагається відновити. Це працює допоки не перестане — а зазвичай ламається після перезавантаження.

Розуміти два режими роботи resolved

  • Stub listener: система вказує на 127.0.0.53 (локальний stub), і resolved робить маршрутизацію та кешування upstream.
  • Foreign / direct resolv.conf: додатки звертаються напряму до upstream-серверів. Саме тут розділений DNS тихо помирає.

VPN має публікувати домени, а не лише сервери

VPN, який лише штовхає DNS-сервери без інформації «які домени за мною», прирікає вас на проблеми.
Ви хочете або:

  • інтерфейс VPN отримує routing domains на зразок ~corp.internal, ~company.local
  • або хоча б search-домени (менш точні, з більшим ризиком)

Пріоритет DNS — це не питання стилю

Вибір DNS-сервера підпорядковується правилам. Резолвери вибирають сервери за зв’язком, маршрутом і відповідністю домену. Якщо не встановити пріоритети,
«переможець» може змінюватися при зміні метрик інтерфейсів (роумінг Wi‑Fi дуже цьому сприяє).

Жарт №1: DNS — єдина система, де «це закешовано» приймається одночасно як пояснення і як виправдання.

Швидкий план діагностики

Коли розділений DNS ламається, не починайте з редагування файлів. Почніть з трьох швидких питань:
який резолвер активний, який інтерфейс «власник» домену, і яким шляхом додаток робить запит.

Спочатку: чи дійсно systemd-resolved керує ситуацією?

  • Перевірте, чи /etc/resolv.conf вказує на stub
  • Перевірте resolvectl status на наявність DNS, прив’язаних до інтерфейсів

Друге: чи домен маршрутизований на VPN-лінк?

  • Виконайте resolvectl query git.corp.internal і перевірте, чи це йде через DNS VPN
  • Підтвердіть, що VPN-лінк має ~corp.internal (routing domain), а не лише загальний search-домен

Третє: чи ваш додаток обходить системний резолвер?

  • Браузери, runtime контейнерів і деякі SDK можуть використовувати власний DNS або кеш
  • Порівняйте getent hosts та dig і зіставте результати

Швидкий тест вузького місця

  • Якщо resolvectl query швидкий, а додаток повільний: підозрюйте кешування на рівні додатку, проксі або DoH/DoT всередині додатку.
  • Якщо resolvectl query повільний: підозрюйте недоступний DNS-сервер, проблеми MTU на VPN або блокування UDP/TCP 53.
  • Якщо лише деякі домени падають: підозрюйте routing domains, конфлікти split-horizon або застарілий негативний кеш.

Вимоги та базові перевірки

Debian 13 зазвичай постачається з systemd і може запускати systemd-resolved. NetworkManager поширений на робочих станціях; на серверах ви можете
використовувати systemd-networkd або ifupdown. Цей гайд припускає, що ви користуєтесь NetworkManager або маєте VPN-інтерфейс, який можна налаштувати.

Визначте бажану поведінку перед тим, як щось міняти:

  • Хочете, щоб тільки внутрішні домени використовували DNS VPN (рекомендовано)?
  • Чи потрібно, щоб увесь DNS йшов через VPN під час підключення (іноді вимагається політикою)?
  • Чи потрібно підтримувати і IPv4, і IPv6 DNS-сервери?

Переважне налаштування: systemd-resolved як контроль DNS

1) Переконайтесь, що resolved запущений

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

2) Вкажіть /etc/resolv.conf на stub

Ви хочете, щоб /etc/resolv.conf був символьним посиланням на stub-resolv.conf systemd. Це якір, що виживає після перезавантаження.
Якщо дозволите іншим інструментам його писати, у вас буде різна DNS-поведінка кожного понеділка.

3) Дозвольте NetworkManager спілкуватися з resolved

NetworkManager може інтегруватися з systemd-resolved. Коли він це робить, DNS-сервери та домени стають властивостями, прив’язаними до лінка,
що саме і потрібно для розділеного DNS.

4) Прикріпіть routing domains до VPN-інтерфейсу

Магія — у синтаксисі routing domain: ~corp.internal. Тильда означає «маршрузувати запити для цього суфіксу на DNS цього лінка».
Без цього ви повертаєтесь до глобальної DNS-лотереї.

NetworkManager і розділений DNS для VPN: патерни WireGuard та OpenVPN

WireGuard через NetworkManager

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

OpenVPN через NetworkManager

OpenVPN зазвичай штовхає «dhcp-option DNS» і «dhcp-option DOMAIN». NetworkManager може перетворити це на налаштування resolved, прив’язані до лінка.
Головне — впевнитися, що домени стають routing domains (або принаймні search domains), а пріоритет DNS не дозволяє LAN перехоплювати внутрішні імена.

Жарт №2: VPN DNS як корпоративна органіграмма — технічно задокументовано, емоційно непередбачувано.

Опціонально: локальний dnsmasq для впертого оточення

Я віддаю перевагу одному only systemd-resolved для Debian-клієнтів. Але є крайові випадки:

  • Потрібні правила умовної переадресації, яких очікує конкретний застарілий застосунок.
  • Потрібно відтворити давно усталений корпоративний патерн: «надсилаємо corp.internal на 10.x, усе інше на ISP».
  • Працюєте в оточенні, де VPN-інструменти не можуть стабільно повідомити домени resolved.

У таких випадках dnsmasq може діяти як локальний політик-форвардер, а resolved може форвардити до нього — або можна пропустити resolved і дозволити NetworkManager годувати dnsmasq.
Ризик — збільшення складності. Складність прийнятна, коли вона задокументована і стабільна. Неприйнятна, коли вона випадкова.

Практичні завдання: команди, виводи та рішення

Ці завдання написані так, ніби ви на виклику: ви виконуєте команду, інтерпретуєте вивід, потім вирішуєте, що робити далі.
Не «пробуйте щось» без плану. Міняйте одну змінну за раз.

Завдання 1: Підтвердити, що Debian використовує systemd-resolved

cr0x@server:~$ systemctl status systemd-resolved --no-pager
● systemd-resolved.service - Network Name Resolution
     Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-12-29 08:41:12 UTC; 2h 13min ago
       Docs: man:systemd-resolved.service(8)

Значення: «active (running)» — обов’язкова умова для цього підходу.
Рішення: Якщо він неактивний/відключений, увімкніть його перед тим, як торкатися DNS VPN.

Завдання 2: Перевірити, хто володіє /etc/resolv.conf

cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Dec 29 08:41 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf

Значення: Це символьне посилання — «частина, що стійка до перезавантаження».
Рішення: Якщо воно вказує кудись інакше (або це звичайний файл), виправте це; інакше ви налагоджуєте рухому ціль.

Завдання 3: Оглянути глобальний і per-link вигляд DNS у resolved

cr0x@server:~$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 192.168.1.1
       DNS Servers: 192.168.1.1
        DNS Domain: lan

Link 2 (enp3s0)
    Current Scopes: DNS
         Protocols: +DefaultRoute
Current DNS Server: 192.168.1.1
       DNS Servers: 192.168.1.1
        DNS Domain: lan

Link 5 (wg0)
    Current Scopes: DNS
         Protocols: -DefaultRoute
       DNS Servers: 10.20.30.53 10.20.30.54
        DNS Domain: ~corp.internal ~svc.cluster.local

Значення: VPN-лінк має routing domains (~corp.internal) і не є дефолтним маршрутом для DNS.
Рішення: Якщо VPN-лінк не має routing domains, розділений DNS не спрацює. Додайте їх на рівні підключення.

Завдання 4: Підтвердити, що конкретне внутрішнє ім’я йде через DNS VPN

cr0x@server:~$ resolvectl query git.corp.internal
git.corp.internal: 10.20.40.12                        -- link: wg0
                  (git.corp.internal)

Значення: Запит пройшов через лінк wg0.
Рішення: Якщо там link: enp3s0 або «No appropriate name servers», виправляйте routing domains або доступність DNS.

Завдання 5: Порівняти шлях резолюції libc (те, чим користуються більшість додатків)

cr0x@server:~$ getent hosts git.corp.internal
10.20.40.12     git.corp.internal

Значення: NSS + libc резолвять коректно.
Рішення: Якщо resolvectl query працює, але getent падає — підозрюйте неправильну конфігурацію NSS або те, що додаток обходить системний резолвер.

Завдання 6: Перевірити, що NetworkManager використовує resolved (а не пише resolv.conf напряму)

cr0x@server:~$ nmcli general status
STATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN
connected  full          enabled  enabled  enabled  enabled
cr0x@server:~$ nmcli -t -f RUNNING,VERSION,STATE general
running:yes
version:1.48.0
state:connected

Значення: NM живий; наступний крок — перевірити, що він налаштований на використання systemd-resolved.
Рішення: Якщо NM не запущений, ваші зміни DNS доведеться вносити через systemd-networkd або безпосередньо через VPN-інструменти.

Завдання 7: Оглянути DNS і домени VPN-підключення у NetworkManager

cr0x@server:~$ nmcli -f NAME,TYPE,DEVICE connection show --active
NAME            TYPE       DEVICE
Office-WG       wireguard  wg0
Home-LAN        ethernet   enp3s0
cr0x@server:~$ nmcli connection show "Office-WG" | sed -n '1,120p'
connection.id:                          Office-WG
connection.type:                        wireguard
connection.interface-name:              wg0
ipv4.method:                            auto
ipv4.dns:                               10.20.30.53,10.20.30.54
ipv4.dns-search:                        corp.internal,svc.cluster.local
ipv4.ignore-auto-dns:                   yes
ipv6.method:                            disabled

Значення: NM має DNS і search-домени. З інтеграцією resolved це може стати routing domains.
Рішення: Якщо ipv4.ignore-auto-dns встановлено в no на LAN, DHCP може перевизначити ваші наміри; налаштуйте пріоритети і ignore-auto-dns де потрібно.

Завдання 8: Встановити DNS-сервери VPN і search-домени (та зафіксувати їх)

cr0x@server:~$ sudo nmcli connection modify "Office-WG" ipv4.dns "10.20.30.53 10.20.30.54"
cr0x@server:~$ sudo nmcli connection modify "Office-WG" ipv4.dns-search "corp.internal svc.cluster.local"
cr0x@server:~$ sudo nmcli connection modify "Office-WG" ipv4.ignore-auto-dns yes
cr0x@server:~$ sudo nmcli connection down "Office-WG" && sudo nmcli connection up "Office-WG"
Connection 'Office-WG' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/17)
Connection 'Office-WG' successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/19)

Значення: Ви явно та постійно задали DNS VPN у NM.
Рішення: Якщо після перепідключення resolvectl status досі не показує routing domains, перевірте інтеграцію NM з resolved або використайте drop-in для resolved.

Завдання 9: Підтвердити, що resolved бачить DNS-сервери VPN після перепідключення

cr0x@server:~$ resolvectl status wg0
Link 5 (wg0)
    Current Scopes: DNS
         Protocols: -DefaultRoute
       DNS Servers: 10.20.30.53 10.20.30.54
        DNS Domain: ~corp.internal ~svc.cluster.local

Значення: Ідеально: DNS-сервери, прив’язані до лінка, і routing domains.
Рішення: Якщо домени позначені без тильди, ви ще можете працювати через search domains, але чекайте витоків і дивностей. Виправляйте правильно.

Завдання 10: Форсувати routing domains на VPN-лінку через resolved (коли VPN-клієнт не може)

cr0x@server:~$ sudo mkdir -p /etc/systemd/resolved.conf.d
cr0x@server:~$ sudo tee /etc/systemd/resolved.conf.d/wg0-domains.conf >/dev/null <<'EOF'
[Resolve]
EOF
cr0x@server:~$ sudo resolvectl domain wg0 '~corp.internal' '~svc.cluster.local'
cr0x@server:~$ sudo resolvectl dns wg0 10.20.30.53 10.20.30.54

Значення: Ви застосували налаштування вживу. Зауважте: зміни через resolvectl domain зазвичай не зберігаються після перезавантаження, якщо ваш мережевий менеджер їх не переведе в конфіг.
Рішення: Використовуйте це для тимчасової діагностики; потім перенесіть конфіг у NetworkManager або systemd-networkd, щоб все зберігалося після перезавантаження.

Завдання 11: Перевірити, чи ви не «виливаєте» внутрішні запити у публічний DNS

cr0x@server:~$ resolvectl query doesnotexist.corp.internal
doesnotexist.corp.internal: resolve call failed: 'does not exist' (NXDOMAIN) -- link: wg0

Значення: NXDOMAIN прийшов від VPN-лінка. Добре — запит пішов туди, куди ви планували.
Рішення: Якщо NXDOMAIN приходить від LAN DNS, ваша розділена маршрутизація не працює і внутрішні запити витікають.

Завдання 12: Перевірити «корисний» локальний stub або конфліктуючий прослуховувач на порту 53

cr0x@server:~$ sudo ss -ltnup | grep ':53 '
udp   UNCONN 0      0         127.0.0.53%lo:53         0.0.0.0:*    users:(("systemd-resolve",pid=620,fd=13))
tcp   LISTEN 0      4096      127.0.0.53%lo:53         0.0.0.0:*    users:(("systemd-resolve",pid=620,fd=14))

Значення: resolved володіє stub-listener. Ніякого локального bind-сервера немає.
Рішення: Якщо ви бачите dnsmasq/unbound, що також биндує 127.0.0.1:53, вирішіть, хто має право працювати і вимкніть інший. «Обидва» — не план.

Завдання 13: Переконатися, що nsswitch налаштований адекватно для резолюції хостів

cr0x@server:~$ grep -E '^(hosts|networks):' /etc/nsswitch.conf
hosts:          files mdns4_minimal [NOTFOUND=return] dns
networks:       files

Значення: DNS присутній у ланцюжку; локальні файли мають пріоритет.
Рішення: Якщо dns відсутній, або у вас екзотичні модулі — виправте NSS перед тим, як звинувачувати resolved.

Завдання 14: Спостерігати за поведінкою DNS під час перепідключення VPN

cr0x@server:~$ journalctl -u systemd-resolved -n 80 --no-pager
Dec 29 10:42:11 server systemd-resolved[620]: Switching to fallback DNS server 192.168.1.1#53.
Dec 29 10:42:25 server systemd-resolved[620]: Using degraded feature set UDP instead of UDP+EDNS0 for DNS server 10.20.30.53.
Dec 29 10:42:29 server systemd-resolved[620]: DNS server 10.20.30.53#53 connected via wg0.

Значення: resolved адаптується до досяжності серверів і можливостей EDNS0. Часто це прихована причина «вчора працювало швидко».
Рішення: Якщо ви бачите постійні перемикання, досліджуйте MTU, втрачені пакети або правила фаєрволу на шляху VPN.

Три корпоративні короткі історії (бо шрами вчать)

Коротка історія 1: Інцидент через хибне припущення

Середня компанія розгорнула новий VPN-концентратор. Мережна команда протестувала його з Windows-клієнтом, підтвердила, що внутрішні сайти працюють,
і оголосила перемогу. Користувачам Linux сказали «просто використовуйте OpenVPN» і дали конфіг, що штовхав DNS-сервери, але без доменів.

Хибне припущення: «якщо ми штовхаємо внутрішні DNS-сервери, внутрішні імена резолвитимуться». На Linux це часто означає, що ці сервери стають
глобально пріоритетними. Коли користувачі відключалися, застаріла конфіг залишалася — або, ще гірше, резолвер все одно намагався питати недосяжні 10.x сервери.
Користувачі відчували це як «DNS випадково помирає після VPN».

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

Виправлення не було героїчним. Вони перестали дозволяти VPN перезаписувати глобальний DNS і замість цього опублікували routing domains для corp.internal і
svc.cluster.local. Linux-клієнти тоді надсилали лише ці суфікси на DNS VPN. Все інше лишалося на LAN DNS.

Урок: розділений DNS — це не «необов’язкове полірування». Це коректність. VPN DNS без доменів — це як давати телефонні номери без кодів зон.

Коротка історія 2: Оптимізація, що відплатила

Інша організація хотіла пришвидшити збірки. Хтось помітив, що затримка DNS до корпоративних резолверів через VPN була ~60–120мс у пікові години.
Пропозиція: «давайте кешувати все агресивно на ноутбуках і підняти TTL на внутрішньому DNS». Звучало розумно — поки не перестало.

Вони розгорнули локальний кешуючий шар, і це покращило медіану резолюції. Але межі split DNS стали розмиті.
Деякі внутрішні записи були короткочасні за дизайном, бо сервіси переміщувалися за load balancer’ами. Кеш шар зберігав старі відповіді.
Коли сервіс відключився, клієнти продовжували звертатись до мертвого кінця хвилинами.

Момент відплати був тонким: моніторинг показував, що сервіс здоровий і failover відпрацював. Тільки частина клієнтів була недоступна.
Винними виявилися кеші резолверів. «Швидший DNS» перетворився на інцидент «чому лише віддалені інженери ламаються».

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

Коротка історія 3: Нудна, але правильна практика, що врятувала день

Глобальна компанія мала суворе правило для кінцевих точок: один власник DNS (системний резолвер), один шлях конфігурації (профілі NetworkManager),
і ніяких post-connect скриптів, що редагують /etc/resolv.conf. Інженери бурчали, бо це здавалося бюрократією.

Потім патч до VPN-шлюзу вніс баг, через який список штовханих DNS-серверів іноді включав недосяжний резолвер першим.
Деякі клієнти таймаутилися на першому сервері і переходили на резервний; інші зависали через логіку повторних спроб. Могло бути погано.

Завдяки єдиному дизайну, діагностика була швидкою. На уражених машинах resolvectl status ясно показував поганий DNS-сервер на VPN-лінку.
Вони могли задеплоїти однорядкове оновлення профілю NetworkManager, щоб переставити порядок DNS-серверів і зменшити болючість повторних спроб.

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

Поширені помилки: симптом → причина → виправлення

  • Симптом: DNS працює до перезавантаження, потім внутрішні імена падають.
    Причина: /etc/resolv.conf — звичайний файл або керується неправильним інструментом; resolved не активний як stub.
    Виправлення: Увімкніть resolved і зробіть символьне посилання /etc/resolv.conf/run/systemd/resolve/stub-resolv.conf.
  • Симптом: Під VPN публічний DNS перестає працювати або повільнішає.
    Причина: DNS-сервери VPN використовуються як глобальні резолвери; вони або блокують рекурсію, або мають поганий egress.
    Виправлення: Використайте routing domains (~corp.internal), щоб тільки внутрішні домени потрапляли на DNS VPN; залиште LAN/публічні резолвери для решти.
  • Симптом: Внутрішні домени резолвяться в публічні IP (неправильний сервіс, помилки сертифікатів).
    Причина: Split-horizon mismatch: запити для внутрішніх зон йдуть до публічних резолверів першими.
    Виправлення: Переконайтесь, що внутрішній суфікс маршрутизовано на VPN-лінк; перевірте resolvectl query, щоб воно показувало link: wg0.
  • Симптом: resolvectl query працює, але браузер чи Java-додаток падає.
    Причина: Додаток обходить системний резолвер (DoH), має закріплений DNS або застарілий кеш.
    Виправлення: Порівняйте з getent hosts; відключіть DoH у додатку або узгодьте його з політикою; перезапустіть додаток після змін DNS.
  • Симптом: Лише деякі внутрішні імена падають, особливо короткі імена хостів.
    Причина: Відсутній search-домен на VPN-лінку, або конфлікт порядку search між LAN і VPN.
    Виправлення: Додайте явні домени; надавайте перевагу FQDN; зменшіть і впорядкуйте search-домени обережно.
  • Симптом: Випадкові таймаути при резолюції внутрішніх імен через VPN.
    Причина: Проблеми MTU/фрагментації на шляху VPN, або DNS-сервер вимагає TCP-fallback і він заблокований.
    Виправлення: Перевірте логи resolved на degraded mode; протестуйте доступність TCP/53; виправте MTU або правила фаєрволу.
  • Симптом: DNS-запити йдуть до неправильного локального сервісу на порті 53.
    Причина: Інший резолвер (dnsmasq/unbound) слухає порт, або мережа контейнера перехоплює DNS.
    Виправлення: Визначте одного локального слухача; зупиніть інший; переконайтесь через ss -ltnup.

Контрольні списки / покроковий план

Контрольний список A: Чистий базовий стан, що витримує перезавантаження

  1. Увімкніть і запустіть systemd-resolved.
  2. Створіть символьне посилання /etc/resolv.conf на stub-resolv.conf resolved.
  3. Підтвердіть, що resolvectl status показує resolv.conf mode: stub.
  4. Обирайте один мережевий менеджер: NetworkManager для десктопів, systemd-networkd для серверів. Не змішуйте без підстав.

Контрольний список B: Розділений DNS для VPN, який не «витікає»

  1. Явно вкажіть DNS-сервери VPN (уникайте «автоматично, якщо пощастить»).
  2. Прикріпіть routing domains до VPN-лінка: ~corp.internal, ~svc.cluster.local.
  3. Переконайтесь, що VPN-лінк не є дефолтним DNS-маршрутом, якщо політика це не вимагає.
  4. Підтвердіть через resolvectl query, що внутрішні домени показують link: wg0.
  5. Перевірте, що публічні домени все ще резолвяться через LAN DNS.

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

  1. Тримайте search-домени короткими; уникайте складання п’яти корпоративних суфіксів «на всякий випадок».
  2. У конфігураціях і автоматизації надавайте перевагу FQDN.
  3. Зробіть поведінку DNS видимою: навчіть людей resolvectl status і resolvectl query.
  4. Тестуйте цикли перепідключення: відключіть/підключіть VPN, змініть Wi‑Fi, переведіть у режим сну/пробудження.
  5. Документуйте єдине джерело правди: «DNS керує resolved; NM його наповнює».

Питання та відповіді

1) Чи обов’язково використовувати systemd-resolved для розділеного DNS на Debian 13?

Ні, але вам потрібен інструмент, що може виразити маршрутизацію за доменом. resolved — найпростіший варіант на Debian 13
і добре інтегрується з NetworkManager.

2) У чому різниця між search-доменами і routing domains?

Search-домени додають суфікси до коротких імен (наприклад, gitgit.corp.internal).
Routing domains (~corp.internal) вказують resolved, яким DNS-серверам надсилати запити для цього суфіксу.
Для розділеного DNS використовуйте routing domains. Search-домени застосовуйте помірно.

3) Чому не просто поставити DNS-сервери VPN першими в resolv.conf?

Бо це ламається, щойно VPN відключиться, і бо це відправляє неприкорпоративні запити до корпоративних резолверів.
Розділений DNS — про коректність, а не лише про «щоб внутрішнє резолвилося під час підключення».

4) Я використовую WireGuard з wg-quick, а не NetworkManager. Можу я це зробити?

Так, але вам потрібно переконатися, що DNS і маршрутизація доменів застосовуються стійко при піднятті інтерфейсу.
Поширений підхід — інтеграція з resolved через hooks на підняття інтерфейсу — і потім перевірка після перезавантаження, що скрипти виконуються.
Якщо можете, краще керувати WireGuard через NetworkManager на ноутбуках — це стабільніше.

5) Мої внутрішні DNS-сервери відповідають лише на внутрішні зони і відмовляють у рекурсії. Це нормально?

Так, це нормально і часто навмисне. Це ще одна причина використовувати розділений DNS: лише внутрішні суфікси повинні потрапляти на ці сервери,
а публічні імена повинні резолвитися інакше.

6) Чому «NXDOMAIN» іноді зберігається після того, як я полагодив DNS?

Негативне кешування. Резолвери й додатки можуть кешувати NXDOMAIN на TTL. Перезапуск resolved може очистити його кеш,
але додатки все ще можуть мати кеш. Для діагностики використовуйте нові імена або перезапустіть додаток.

7) Як зрозуміти, чи мій додаток обходить системний резолвер?

Порівняйте результати getent hosts name і додатку. Якщо libc резолвить, а додаток — ні,
перевірте у додатку налаштування DoH, вбудовані резолвери або проксі-конфігурацію.

8) Чи варто вимикати IPv6, щоб «вирішити проблеми DNS»?

Зазвичай ні. Dual-stack додає складності, але вимикання IPv6 часто ховає реальну проблему (наприклад, зламаний VPN DNS через IPv6 або погані маршрути RA).
Виправляйте конфігурацію, не відрізайте мережу.

9) Коли варто обирати dnsmasq замість systemd-resolved?

Коли потрібні правила умовної переадресації, які погано мапляться на link-scoped DNS, або коли застаріле програмне забезпечення не може повідомити розділені домени.
Розглядайте це як виняток, а не як стандарт.

Висновок: наступні кроки, що не зіпсують ваш понеділок

Стабільний шлях на Debian 13 простий: systemd-resolved керує політикою DNS; NetworkManager (або ваш мережевий стек) подає йому DNS-сервери і routing domains, прив’язані до лінків.
Нехай /etc/resolv.conf вказує на stub, і припиніть дозволяти випадковим скриптам відтирати його.

Практичні наступні кроки:

  1. Перевірте, що /etc/resolv.conf — це символьне посилання на stub resolved.
  2. Переконайтесь, що ваш VPN-лінк має routing domains (~corp.internal) і DNS-сервери VPN у resolvectl status.
  3. Запустіть три тести: resolvectl query для внутрішнього імені, getent hosts для того ж імені, та запит публічного імені.
  4. Спробуйте раз перезавантаження навмисно. Якщо після планового перезавантаження щось ламається — це ніколи не було стабільним, а лише тимчасово пощастило.
← Попередня
Ubuntu 24.04: IPv6 ламає випадкові сайти — виправте двостек правильно (не просто відключайте IPv6)
Наступна →
MySQL проти MariaDB на NVMe та SATA SSD: чому ваша БД досі повільна (і як це довести)

Залишити коментар