Ви підключаєтеся до VPN і все здається «включеним». Тунель зеленіє. Іконка усміхається.
А потім: нічого не резольвиться. Внутрішні імена не працюють, можливо не працює й публічний DNS, і ваш браузер виконує
корпоративний еквівалент «дивиться на зачинені двері».
Це та помилка, яка змушує розумних людей робити дурниці — наприклад випадково редагувати /etc/resolv.conf
о 2-й ранку. Не робіть цього. В Ubuntu 24.04 поведінка резолвера — шарувата система (systemd-resolved + NetworkManager + DNS на рівні інтерфейсу),
а VPN агресивно змінюють маршрути. Виправляти DNS без виправлення маршрутів — як міняти батарейки в детекторі диму, поки кухня ще у вогні.
Ментальна модель: що змінилося в Ubuntu 24.04 і чому VPN зламуть її
Ubuntu 24.04 все ще «використовує» /etc/resolv.conf, але так само, як фокусник «використовує» колоду карт:
це не місце, де приймаються справжні рішення. Більшість десктопних і багато серверних інсталяцій працюють
з systemd-resolved зі stub‑резолвером та DNS конфігурацією на рівні інтерфейсу.
NetworkManager зазвичай є політичним механізмом, який передає systemd-resolved DNS і домени.
VPN‑клієнти (OpenVPN, WireGuard через NetworkManager, пропрієтарні агенти) часто змінюють:
- Маршрути (маршрут за замовчуванням, політичні маршрути, маршрути split tunnel)
- DNS‑сервери (поштовхають внутрішні резолвери, замінюють на «тільки VPN DNS»)
- Пошукові домени / split DNS домени (маршрутизувати лише
corp.exampleчерез VPN DNS) - Правила фаєрвола (деякі клієнти реалізують власний kill‑switch)
Підступ: DNS — це мережевий трафік. Якщо таблиця маршрутів вказує DNS‑пакети не туди,
«виправлення DNS» на рівні резолвера не допоможе. Так само, правильний маршрут з неправильним резолвером
створює враження, що VPN впав, хоча це не так. Отже, порядок важливий:
спочатку маршрути, потім вибір резолвера, потім поведінка split DNS, і нарешті кеші.
Ось базовий потік на типовій системі Ubuntu 24.04:
- glibc викликає бібліотеку резолвера (зазвичай використовуючи правила
nsswitch.conf) - Запити йдуть до nameserver, вказаного в
/etc/resolv.conf(часто127.0.0.53) - systemd-resolved обирає DNS‑сервери на рівні лінку, по доменах, з урахуванням маршрутів
- Пакети відправляються через таблицю маршрутів ядра (або політичне маршрутизацію) через обраний інтерфейс
Якщо VPN «допоміжно» встановлює маршрут за замовчуванням через тунель, але забуває дозволити доступ до корпоративного DNS
через цей тунель — або гірше, встановлює DNS‑сервери, які доступні лише в локальній мережі — ви отримаєте класичний симптом: IP‑адреси працюють, імена — ні.
Або «публічні імена працюють, внутрішні — ні».
Одне висловлювання варте стикера:
«Надія — не стратегія.»
— Gordon R. Dickson. Це не цитата SRE, але чудово підходить до налагодження DNS.
(Якщо ви не можете це перевірити командами — це надія.)
Жарт №1: DNS — єдина система, де «працює на моїй машині» може буквально означати «працює на моєму резолвері».
Цікаві факти та контекст (коротко, конкретно, корисно)
- systemd-resolved давно є стандартним резолвером в Ubuntu, але екосистема досі вважає
/etc/resolv.confавторитетним, що створює примарні баги, коли це лише stub. - Split DNS старше, ніж думають інженери: підприємства робили «внутрішні зони на внутрішніх резолверах» задовго до того, як сучасні VPN‑додатки почали називати це фічею.
- NetworkManager може встановлювати DNS на рівні підключення і для кожного VPN, і може вирішувати, чи перезаписує VPN DNS існуючі налаштування чи доповнює їх.
- Опції push в OpenVPN можуть доставляти DNS‑сервери та маршрути клієнтам; якщо конфіг сервера неакуратний, всі клієнти успадковують цю неакуратність.
- WireGuard не має рідної контрольної площини для DNS; DNS зазвичай налаштовує клієнт (wg-quick, NetworkManager або скрипти), тож «DNS зламався» часто означає «клієнт не застосував DNS».
- 127.0.0.53 — це не «DNS‑сервер»; це локальний stub‑прослуховувач для systemd-resolved. Якщо ви вказуєте додаткам інший сервер, ви випадково можете обійти логіку split DNS.
- DNS по TCP існує не просто так: великі відповіді, DNSSEC і деякі комбінації VPN/фаєрвола, що неправильно обробляють UDP‑фрагментацію.
- Пошукові домени можна випадково використати як зброю: додавання суфікса на кшталт
corp.exampleможе змінити резольвинг коротких імен і заплутати журнали та інструменти.
Швидкий план діагностики (що перевіряти спочатку/далі)
Спочатку: доведіть, чи проблема в маршрутах чи в резолюванні
-
Чи досяжний відомий IP через VPN?
Якщо ви можете пінгувати або curl‑ити внутрішню IP, а внутрішні імена не працюють — це резолвер. Якщо ж внутрішні IP недосяжні — починайте з маршрутів/фаєрвола. -
Чи можна дістатися до конфігурованого DNS‑серверу(ів)?
Якщо VPN надав10.0.0.53, але ви не можете прокласти до нього маршрут, то DNS приречений незалежно від правильності конфігів.
По‑друге: дивіться на погляд systemd-resolved, а не на припущення
-
Використайте
resolvectl status, щоб побачити DNS‑сервери та домени по лінках.
Якщо у вашого VPN‑лінку є DNS, але маршрут за замовчуванням все ще вказує на Wi‑Fi, у вас може бути split tunnel без split DNS (або навпаки). -
Перевірте, чи
/etc/resolv.confє stub, що вказує на127.0.0.53, або щось інше.
Якщо VPN‑клієнт його перезаписав, ви можете обходити пер‑лінкову логіку systemd‑resolved.
По‑третє: перевірте резолювання з кількох кутів
-
Тестуйте через
resolvectl query(проходить через systemd-resolved). -
Тестуйте з
dig @SERVER(обминає локальну політику; добре для перевірки досяжності та коректності сервера). - Якщо результати відрізняються — у вас політика/конфіг не збігається, а не чистий збій DNS.
По‑четверте: тільки тоді торкайтеся конфігурації
Не починайте «виправляти», підв’язуючи 8.8.8.8 або вириваючи resolved. Саме так ви отримаєте публічний DNS, що працює,
а внутрішні зони мовчать тижнями. Виправте маршрути й політику резолверів так, щоб машина поводилася правильно як з VPN, так і без нього.
Практичні завдання: команди, очікуваний вивід і рішення
Це перевірки, які я реально виконую на Ubuntu 24.04, коли VPN «підключається», але DNS поводиться так, ніби в іншому часовому поясі.
Кожне завдання містить: команду, що означає типовий вивід, і рішення, яке з нього витікає.
Виконуйте їх у порядку, якщо вам не подобається хаотична налагодка.
Завдання 1: Підтвердити, що інтерфейс VPN існує і UP
cr0x@server:~$ ip -brief link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp0s31f6 UP 3c:52:82:ab:cd:ef <BROADCAST,MULTICAST,UP,LOWER_UP>
wg0 UNKNOWN 9a:bc:de:f0:12:34 <POINTOPOINT,NOARP,UP,LOWER_UP>
Значення: wg0 (або tun0) існує і UP. Якщо його немає — це вже не проблема DNS, це проблема VPN.
Рішення: Якщо інтерфейс відсутній/не UP, спершу виправте підключення/аутентифікацію VPN. Зупиніться тут.
Завдання 2: Перевірити адреси на VPN‑інтерфейсі
cr0x@server:~$ ip addr show dev wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
inet 10.44.0.12/32 scope global wg0
valid_lft forever preferred_lft forever
Значення: Ви отримали адресу. /32 на WireGuard — звичайне явище. Для OpenVPN ви можете бачити /24 або /20.
Рішення: Відсутність адреси означає, що тунель не налаштований правильно. DNS не може працювати, якщо VPN не призначив мережеву ідентичність.
Завдання 3: Перевірити маршрут за замовчуванням і маршрути VPN
cr0x@server:~$ ip route
default via 192.168.1.1 dev enp0s31f6 proto dhcp metric 100
10.44.0.0/16 dev wg0 proto kernel scope link src 10.44.0.12
192.168.1.0/24 dev enp0s31f6 proto kernel scope link src 192.168.1.50 metric 100
Значення: Маршрут за замовчуванням все ще локальний; VPN дає маршрут лише до 10.44/16 (split tunnel).
Рішення: Якщо корпоративний DNS знаходиться в 10.44/16 — добре. Якщо VPN передав DNS як 10.99.0.53, але немає маршруту до 10.99/16 — ви знайшли баг: відсутні маршрути.
Завдання 4: Запитайте «як ми маршрутуємо до IP DNS‑сервера?»
cr0x@server:~$ ip route get 10.44.0.53
10.44.0.53 dev wg0 src 10.44.0.12 uid 1000
cache
Значення: Пакети до 10.44.0.53 підуть через wg0. Чудово.
Рішення: Якщо воно маршрутує через неправильний інтерфейс (наприклад Wi‑Fi), виправляйте маршрути/політику перед тим, як чіпати DNS‑налаштування.
Завдання 5: Перевірити, чи можна дістатися до DNS‑сервера (ICMP опціонально; UDP/53 — суттєво)
cr0x@server:~$ nc -uvz -w2 10.44.0.53 53
Connection to 10.44.0.53 53 port [udp/domain] succeeded!
Значення: UDP 53 виглядає досяжним. Це не абсолютна гарантія, але сильно вказує, що маршрути/фаєрвол не блокують базовий DNS.
Рішення: Якщо це не вдається — зосередьтесь на маршрутах VPN, правилах фаєрвола або на тому, що DNS‑сервер недоступний.
Завдання 6: Подивіться, чим насправді є /etc/resolv.conf
cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Apr 25 10:12 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
Значення: Використовується stub‑резолвер; додатки звертаються до 127.0.0.53, а systemd-resolved обирає upstream.
Рішення: Якщо /etc/resolv.conf є звичайним файлом, що вказує на якийсь VPN‑провайдований DNS, ви могли обійти resolved і порушити split DNS. Вирішіть, чи вам це потрібно (зазвичай ні).
Завдання 7: Перевірте стан systemd-resolved і DNS по лінках
cr0x@server:~$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp0s31f6)
Current Scopes: DNS
Protocols: +DefaultRoute
Current DNS Server: 192.168.1.1
DNS Servers: 192.168.1.1
Link 4 (wg0)
Current Scopes: DNS
Protocols: -DefaultRoute
DNS Servers: 10.44.0.53
DNS Domain: ~corp.example
Значення: Ідеальна настройка split DNS: лише corp.example спрямовується до VPN DNS (маршрутний домен позначено ~).
Рішення: Якщо у VPN‑лінку немає DNS‑серверів — NetworkManager не застосував їх (або клієнт щось поламав). Виправляйте в профілі NM/VPN.
Завдання 8: Підтвердити резолювання через шлях systemd-resolved
cr0x@server:~$ resolvectl query app01.corp.example
app01.corp.example: 10.44.20.17 -- link: wg0
-- Information acquired via protocol DNS in 42.1ms.
-- Data is authenticated: no
Значення: Resolved обирає wg0 і повертає правильний запис.
Рішення: Якщо це працює, а додатки все одно падають — перевірте nsswitch.conf або специфічну поведінку додатків (деякі обходять glibc).
Завдання 9: Порівняйте з прямим dig до VPN DNS‑сервера
cr0x@server:~$ dig @10.44.0.53 app01.corp.example +time=2 +tries=1
; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @10.44.0.53 app01.corp.example +time=2 +tries=1
; (1 server found)
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48291
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; ANSWER SECTION:
app01.corp.example. 60 IN A 10.44.20.17
;; Query time: 25 msec
;; SERVER: 10.44.0.53#53(10.44.0.53) (UDP)
;; WHEN: Thu Apr 25 10:26:51 UTC 2025
;; MSG SIZE rcvd: 62
Значення: Сам DNS‑сервер в порядку.
Рішення: Якщо dig працює, але resolvectl — ні, то причина в локальній політиці/конфігу (домени, пер‑лінковий DNS, стан resolved).
Завдання 10: Перевірити, чи VPN змінив пріоритет DNS або обробку маршруту за замовчуванням
cr0x@server:~$ nmcli dev show wg0 | sed -n '1,120p'
GENERAL.DEVICE: wg0
GENERAL.TYPE: wireguard
GENERAL.STATE: 100 (connected)
IP4.ADDRESS[1]: 10.44.0.12/32
IP4.GATEWAY: --
IP4.DNS[1]: 10.44.0.53
IP4.DOMAIN[1]: corp.example
IP4.ROUTE[1]: dst = 10.44.0.0/16, nh = 0.0.0.0, mt = 0
Значення: NM вважає, що wg0 має DNS і маршрут. Добре.
Рішення: Якщо IP4.DNS відсутній — виправляйте профіль VPN; не ламаючи resolved вручну як перший крок.
Завдання 11: Перевірити правила політичної маршрутизації (поширено з kill‑switch або «full tunnel»)
cr0x@server:~$ ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
Значення: Немає спеціальних політичних правил. Діє проста таблиця маршрутів.
Рішення: Якщо ви бачите додаткові правила, що перенаправляють DNS‑трафік (або весь трафік) в іншу таблицю — необхідно перевірити й ті таблиці також. Не думайте, що лише ip route каже всю історію.
Завдання 12: Перевірити правила фаєрвола на блокування DNS (особливо з kill‑switch)
cr0x@server:~$ sudo nft list ruleset | sed -n '1,160p'
table inet filter {
chain output {
type filter hook output priority filter; policy accept;
ip daddr 10.44.0.0/16 udp dport 53 accept
ip daddr 10.44.0.0/16 tcp dport 53 accept
}
}
Значення: DNS у VPN‑просторі дозволено. Чудово.
Рішення: Якщо ви бачите ланцюг output з політикою drop або правила, які дозволяють трафік лише через тунельний інтерфейс — підтвердіть, що DNS включено. Багато «приватних» VPN‑клієнтів блокують UDP/53, якщо це явно не дозволено.
Завдання 13: Перевірити логи systemd-resolved, коли виглядає «сконфігуровано, але мертве»
cr0x@server:~$ journalctl -u systemd-resolved -n 80 --no-pager
Apr 25 10:24:10 server systemd-resolved[812]: Using degraded feature set UDP instead of UDP+EDNS0 for DNS server 10.44.0.53.
Apr 25 10:24:12 server systemd-resolved[812]: Failed to send hostname reply: Transport endpoint is not connected
Apr 25 10:24:20 server systemd-resolved[812]: Switching to DNS server 10.44.0.53 for link 4.
Значення: Ви бачите повтори, відкотів і повідомлення «degraded feature set», що підказують про проблеми MTU/фрагментації через VPN.
Рішення: Якщо бачите повторювані таймаути або переключення — переходьте до перевірки MTU і спроб TCP‑DNS.
Завдання 14: Протестувати DNS по TCP (бо VPN і MTU люблять драму)
cr0x@server:~$ dig @10.44.0.53 app01.corp.example +tcp +time=2 +tries=1
; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @10.44.0.53 app01.corp.example +tcp +time=2 +tries=1
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1136
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; ANSWER SECTION:
app01.corp.example. 60 IN A 10.44.20.17
;; Query time: 31 msec
;; SERVER: 10.44.0.53#53(10.44.0.53) (TCP)
;; WHEN: Thu Apr 25 10:28:51 UTC 2025
;; MSG SIZE rcvd: 62
Значення: TCP працює. Якщо UDP падає, а TCP працює — підозрюйте MTU/фрагментацію або фаєрвол, що цілеспрямовано блокує UDP.
Рішення: Змініть MTU на тунелі, виправте проблеми Path MTU Discovery або дозволіть фрагменти UDP. Не «виправляйте» це підмінною зміною резолвера на публічний — це приховає проблему.
Завдання 15: Підтвердити, що додатки використовують NSS
cr0x@server:~$ grep -E '^(hosts|resolve)' /etc/nsswitch.conf
hosts: files mdns4_minimal [NOTFOUND=return] dns
Значення: Стандартний порядок: files, потім mDNS, потім DNS. Добре.
Рішення: Якщо dns відсутній або замінений чимось дивним — ви можете отримати «resolvectl працює, а getent падає». Виправте порядок NSS перед тим, як звинувачувати VPN.
Завдання 16: Тестувати резолювання як простий інструмент ОС (бо браузери брешуть)
cr0x@server:~$ getent ahosts app01.corp.example
10.44.20.17 STREAM app01.corp.example
10.44.20.17 DGRAM app01.corp.example
10.44.20.17 RAW app01.corp.example
Значення: Шлях резолвера glibc працює.
Рішення: Якщо getent падає, але resolvectl query працює — проблема між glibc і resolved (режим resolv.conf, nsswitch або DNS специфічний для додатку).
Виправляємо в правильному порядку: маршрути → резолвери → split DNS → кеші
Тема: не «виправляйте» DNS шляхом примусового встановлення єдиного резолвера глобально, якщо ви навмисно не хочете зламати split DNS.
Ваша мета — політична коректність: внутрішні домени резольвляться через внутрішній DNS коли VPN увімкнено; публічні домени резольвляться як звичайно; VPN вимкнений — повернення до нормального стану.
Це надійність, а не героїзм.
Крок 1: Виправте маршрути до DNS‑серверів (і внутрішніх зон)
Більшість помилок DNS через VPN — не в DNS. Вони в маршрутах. VPN передає адресу DNS‑сервера, яка доступна лише через тунель,
але тунель налаштований неправильно для split‑маршрутизації. Або навпаки: встановлено full‑tunnel, але клієнтський фаєрвол блокує DNS поза тунелем.
Якщо ви виявили відсутні маршрути, вирішіть, куди має йти виправлення:
- Правильне місце: профіль VPN / конфіг сервера, який штовхає маршрути. Виправте це один раз; всі клієнти отримають користь.
- Допустимий обхід: додайте статичні маршрути на клієнті, якщо ви не можете контролювати VPN‑сервер.
- Погана ідея: переключитися на публічний резолвер, щоб «повернути інтернет». Це приховає поламані внутрішні маршрути й уб’є внутрішнє резолювання.
Приклад: тимчасово додати маршрут (поки профіль VPN не виправлено):
cr0x@server:~$ sudo ip route add 10.99.0.0/16 dev wg0
Значення: Ви зробили мережу DNS‑сервера досяжною через тунель.
Рішення: Якщо це «виправляє DNS», поверніться і імплементуйте маршрут у налаштуваннях NetworkManager або на VPN‑сервері. Не лишайте унікальні ручні маршрути на ноутбуках як постійну стратегію.
Крок 2: Переконайтеся, що systemd-resolved — авторитет (якщо немає причин інакше)
В Ubuntu 24.04 ви хочете одного приймача рішень. Якщо VPN‑клієнт замінює /etc/resolv.conf на статичний файл,
він може обійти systemd-resolved і порушити split DNS. Відновіть stub‑symlink за потреби.
cr0x@server:~$ sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Значення: Додатки використовують локальний stub; resolved може застосовувати пер‑лінковий DNS і маршрутні домени.
Рішення: Якщо ви керуєте headless‑сервером і свідомо не хочете systemd-resolved — це інша архітектура. Але не змішуйте режими випадково.
Крок 3: Виправте DNS та налаштування split DNS у підключенні NetworkManager
Для корпоративних VPN зазвичай потрібен split DNS: внутрішні зони через VPN DNS, все інше через звичайний резолвер.
На Ubuntu з NetworkManager це означає, що VPN‑підключення має встановити:
- VPN DNS‑сервер(и): внутрішні резолвери
- DNS‑домени: маршрутні домени на кшталт
~corp.example(або налаштовані в NM, щоб resolved їх отримав) - Відповідні маршрути: до внутрішніх мереж і DNS‑серверів
Перевірте й відкоригуйте налаштування підключення (приклад показує читання значень; запис залежить від типу VPN):
cr0x@server:~$ nmcli -f NAME,TYPE,DEVICE connection show --active
Wired connection 1 ethernet enp0s31f6
Corp WG wireguard wg0
cr0x@server:~$ nmcli connection show "Corp WG" | sed -n '1,140p'
connection.id: Corp WG
connection.type: wireguard
ipv4.method: auto
ipv4.dns: 10.44.0.53
ipv4.dns-search: corp.example
ipv4.never-default: yes
Значення: ipv4.never-default: yes вказує на split tunnel (без маршруту за замовчуванням через VPN).
Рішення: Якщо потрібен full tunnel — встановіть never-default в no (і переконайтесь, що маршрути/фаєрвол дозволяють DNS‑серверу виходити!). Якщо потрібен split tunnel — залишайте yes, але переконайтесь, що існують маршрути до внутрішніх DNS і мереж.
Крок 4: Відновіть маршрути доменів (тонка частина, яку люди пропускають)
Ви можете мати «DNS‑сервери встановлені», але все одно надсилати запити не туди.
У systemd-resolved важливі маршрутні домени. Маршрутний домен (позначений ~ у виводі resolvectl)
каже resolved, які домени мають обслуговуватися яким лінком.
Якщо ваш VPN має обробляти лише corp.example, встановіть саме його, а не глобальний список пошуків, що робить усе наче внутрішнім.
Глобальний search‑лист — це те, як коротке ім’я printer стає printer.corp.example вдома,
і раптом ваша сімейна мережа — «частина інциденту».
Крок 5: Очистіть кеші після змін (але тільки після змін)
systemd-resolved кешує. Браузери кешують. Деякі додатки агресивно кешують. Очистіть потрібний кеш у потрібний час, щоб не ганятися за привидами.
cr0x@server:~$ sudo resolvectl flush-caches
cr0x@server:~$ resolvectl statistics
DNSSEC supported by current servers: no
Transactions: 58
Cache hits: 11
Cache misses: 47
Значення: Якщо ви продовжуєте бачити кеш‑хіти для неправильних відповідей, очищення допомагає, але не виправляє політику.
Рішення: Очистіть один раз після зміни конфігурації, потім повторно протестуйте. Якщо ви часто чистите кеш під час налагодження, ви втрачаєте діагностичний сигнал.
Крок 6: Якщо UDP ненадійний, ставте MTU в пріоритет
VPN змінюють MTU. DNS по UDP може постраждати від фрагментації, EDNS0 і проблем Path MTU Discovery.
Якщо ви бачите у resolved повідомлення про деградацію або таймаути UDP, тестуйте TCP (Завдання 14).
Потім подумайте про зменшення MTU на тунелі або виправлення правил фаєрвола, що відкидають фрагменти.
Жарт №2: Найшвидший спосіб вивчити MTU — ігнорувати його тиждень і «відкрити» о 3‑й ранку.
Три корпоративні історії з полів DNS/VPN
Міні‑історія 1: Інцидент через хибне припущення
Середня компанія розгорнула Ubuntu 24.04 для групи інженерів, які жили в VPN‑світі. Міграція «пройшла добре»,
поки в перший тиждень внутрішні сервіси не почали «флапати». Симптом був дивний: внутрішні веб‑додатки працювали за IP, але не за іменем,
і тільки для деяких користувачів, в залежності від місця підключення.
Припущення було класичним: «resolv.conf — це конфігурація DNS». Доброзичливий член команди написав скрипт, що перезаписував
/etc/resolv.conf при підключенні VPN, вказуючи напряму на корпоративний DNS, і знову перезаписував при відключенні.
Вони протестували в терміналі, оголосили перемогу і повернулися до фіч.
На Ubuntu 24.04 цей скрипт обходив пер‑лінкову логіку systemd-resolved і маршрутні домени.
Користувачі в режимі split tunnel почали відправляти всі DNS‑запити до корпоративних резолверів — включно з публічними доменами — через шляхи, які не були промаршрутовані.
Корпоративні DNS‑сервери були доступні лише через тунель, і скрипт іноді виконувався раніше, ніж встановлювалися маршрути.
DNS‑запити йшли в нікуди, потім кешувалися як NXDOMAIN, і браузерний досвід став як ігровий автомат.
Виправлення було нудним: видалити скрипт, відновити stub‑резолвер і виправити VPN‑профіль, щоб NetworkManager передавав resolved правильні сервери й маршрутні домени.
Інцидент закінчився не героїчним хаком, а смиренною визнаною причиною: система має політичний двигун не просто так.
Міні‑історія 2: Оптимізація, що обернулася проти
Інша організація мала команду з оптимізації мережі. Вони втомилися від скарг на «повільний DNS» і вирішили оптимізувати:
штовхнути єдиний «швидкий» DNS‑сервер всім VPN‑клієнтам. Сервер був добре ресурсоємним і близько до концентратору VPN.
Вони також скоротили TTL для внутрішніх записів, бо «так зміни швидше проростають».
Це обернулося проти в двох сенсах. По‑перше, клієнти в split tunnel режимі тепер мали резолвер, доступний лише через VPN, але пуш не гарантовано забезпечував
маршрути до цього резолвера в кожному режимі тунелю. По‑друге, низькі TTL збільшили обсяг запитів і зробили видимими переривчасті втрати пакетів у вигляді таймаутів.
Резолвер був «швидким» в ізоляції, але крихким у реальній мережі.
Інженери почали жорстко прописувати публічні резолвери, щоб «полагодити інтернет», що створило новий клас проблем:
внутрішні домени витікали в публічний DNS (переважно безпечно, але незручно), і внутрішні імена перестали взагалі резольвитися.
Плейбук служби підтримки перетворився на купу суперечливих порад.
Остаточне виправлення: відновити split DNS (внутрішні зони — тільки до внутрішніх резолверів, коли існують маршрути),
тримати TTL помірними і додати підтримку TCP‑fallback для DNS на шляху VPN.
Продуктивність покращилася, бо система стала правильною, а не тому, що хтось оголосив резолвер «швидким».
Міні‑історія 3: Нудна, але правильна практика, що врятувала ситуацію
Підприємство з високими вимогами до безпеки мало звичку, що виглядала нудно на папері: кожна зміна VPN вимагала виконання тест‑чеклисту на чистому образі Ubuntu.
Не на ноутбуку розробника. Не на «вже налаштованій» машині. Тимчасова VM, яка представляла базову реальність.
Вони тестували маршрути, DNS і невеликий набір внутрішніх запитів.
Одного тижня вони планували додати нову внутрішню DNS‑зону і оновити VPN, щоб штовхати відповідний маршрутний домен.
Під час запуску чек‑листу resolvectl status показав, що домен додається як search‑домен замість маршрутного.
Це означало б, що resolved трактуватиме його інакше, і короткі імена почали б резольвитися дивно.
Це ще не був інцидент, але пахло недобре.
Команда виявила це до релізу. Вони налаштували генерацію профілю NetworkManager так, щоб VPN створював правильні пер‑доменні маршрути.
Вони також підтвердили, що IP DNS‑сервера досяжний у split tunnel режимі, перевіривши ip route get під час підключення.
Це запобігло хвилі заявок «VPN підключено, але DNS мертвий».
Ніяких геройств. Нічних правок. Лише чеклист, що трактує DNS і маршрути як пов’язану систему.
Найкращі інциденти — ті, за які вас ніколи не розбудять.
Поширені помилки (симптом → причина → виправлення)
1) Симптом: «VPN підключається, але внутрішні імена не резольвляться»
Причина: DNS‑сервер VPN налаштований, але немає маршруту до нього (split tunnel пропускає підмережу резолвера).
br Виправлення: Додайте/відновіть маршрути до IP(ів) DNS‑серверів у профілі VPN або в конфігу сервера. Перевірте через ip route get DNS_IP.
2) Симптом: «Публічний DNS працює, внутрішній — ні»
Причина: Split DNS не налаштований; внутрішні домени не спрямовуються до VPN‑резолвера (або відсутні маршрутні домени).
Виправлення: Налаштуйте маршрутні домени (наприклад, ~corp.example) для VPN‑лінка в resolved/NM і переконайтеся, що VPN‑сервери встановлені на цьому лінку.
3) Симптом: «Внутрішнє працює, але інтернет вмирає при увімкненому VPN»
Причина: Встановлено full tunnel маршрут (або правила kill‑switch), але VPN DNS вказує на внутрішні резолвери, які не резольвлять публічні домени, або еґрес обмежений.
Виправлення: Визначте політику: full tunnel з корпоративними рекурсивними резолверами, що резольвять публіку, або split tunnel з зовнішнім резолвером для інтернету. Не робіть півзаходів.
4) Симптом: «resolvectl query працює, але браузери/додатки все ще падають»
Причина: Додаток обходить системний резолвер (DoH, власний резолвер, контейнерний DNS або жорстко прописаний nameserver).
Виправлення: Підтвердіть через getent ahosts і налаштування додатку. Тимчасово відключіть DoH або узгодьте його з корпоративною DNS‑політикою.
5) Симптом: «dig @DNS працює, але resolvectl query таймаутиться»
Причина: systemd-resolved використовує інші DNS‑сервери або неправильно обирає лінк через відсутність маршрутних доменів.
Виправлення: Перевірте resolvectl status і переконайтеся, що VPN‑лінк має DNS‑сервери і ~domain маршрутні домени.
6) Симптом: «DNS працював деякий час, потім зламався після сну/пробудження»
Причина: VPN перепідключився, але DNS‑налаштування не були повторно застосовані (гонитва між VPN up і оновленням NM/resolved), або залишилися застарілі маршрути.
Виправлення: Підтвердіть стан після відновлення за завданнями 3, 7, 10. Якщо чогось бракує — виправте dispatcher‑скрипти або інтеграцію VPN‑клієнта; очищення кешу — не лікування, а пластир.
7) Симптом: «Лише великі DNS‑відповіді падають (деякі домени завантажуються, інші — ні)»
Причина: Проблеми MTU/фрагментації, EDNS0 або відкидання UDP‑фрагментів через тунель.
Виправлення: Тестуйте TCP для DNS. Відрегулюйте MTU тунелю, дозволіть фрагменти або налаштуйте безпечні розміри UDP.
8) Симптом: «Випадкові NXDOMAIN для внутрішніх імен»
Причина: Неправильний резолвер відповідає на внутрішні запити (публічний резолвер або домашній роутер), іноді через відсутність маршрутного домену або неправильного пріоритету DNS.
Виправлення: Застосуйте split DNS: внутрішні зони мають оброблятися виключно внутрішніми резолверами через VPN‑лінк.
Чеклисти / покроковий план
Чеклист A: Послідовність «Потрібно, щоб працювало зараз» (10–15 хвилин)
- Підтвердьте, що інтерфейс VPN UP:
ip -brief link. - Підтвердьте, що VPN має IP:
ip addr show dev wg0абоip addr show dev tun0. - Перевірте маршрути:
ip route. - Підтвердьте маршрут до DNS:
ip route get DNS_IP. - Перевірте досяжність порту DNS:
nc -uvz DNS_IP 53. - Огляньте стан резолвера:
resolvectl status. - Запитайте внутрішнє ім’я:
resolvectl query host.corp.example. - Порівняйте з прямим dig:
dig @DNS_IP host.corp.example. - Після змін один раз очистіть кеш:
sudo resolvectl flush-caches. - Якщо UDP ненадійний — тестуйте TCP:
dig @DNS_IP host.corp.example +tcp.
Чеклист B: Зробити виправлення довготривалим (щоб цей тикет не повертався)
- Припиніть ручне редагування
/etc/resolv.conf; відновіть stub‑symlink, якщо потрібно. - Виправте маршрути VPN/сервер push, щоб включити підмережу DNS‑серверів та внутрішні мережі.
- Налаштуйте маршрутні домени split DNS (не просто search‑домени) для внутрішніх зон.
- Підтвердіть у
resolvectl status, що VPN‑лінк володіє~corp.example. - Підтвердіть, що
nmcli dev showпоказує DNS і домени на VPN‑інтерфейсі. - Аудитуйте правила фаєрвола/kill‑switch для DNS по UDP і TCP.
- Документуйте очікуваний стан: який інтерфейс за яким доменом і якими DNS‑серверами відповідає.
- Додайте регресійний тест: підключіть VPN на чистому образі і виконайте
resolvectl queryдля одного внутрішнього і одного публічного імені.
Чеклист C: Коли підозрюєте, що VPN‑клієнт «занадто допомагає»
- Перевірте, чи
/etc/resolv.confне був замінений на звичайний файл. - Перевірте додаткові записи
ip rule. - Перевірте вивід
nftна правила фільтрації UDP/53. - Шукайте кілька DNS‑менеджерів, що працюють одночасно (пропрієтарний клієнт + NetworkManager + resolved).
- Визначте одного менеджера як джерело правди; відключіть у інших можливість маніпулювати DNS, якщо це можливо.
FAQ
1) Чому VPN ламає DNS саме на Ubuntu 24.04?
Це не «саме» Ubuntu 24.04, але вона робить це більш помітним, бо systemd-resolved і пер‑лінковий DNS широко використовуються.
VPN‑клієнти, які вважають, що /etc/resolv.conf — єдиний регулятор, можуть конфліктувати зі справжнім стеком резолвера.
2) Чи варто відключати systemd-resolved?
Зазвичай ні. Resolved добре справляється зі split DNS, якщо отримує коректні пер‑лінкові налаштування. Вимикайте його лише якщо маєте чітку альтернативу
(наприклад локальний кеш‑резолвер, яким ви керуєте) і розумієте, як VPN‑клієнти це оновлюватимуть.
3) Мій /etc/resolv.conf вказує на 127.0.0.53. Це неправильно?
Ні. Це локальний stub. Реальні upstream‑сервери видно в resolvectl status.
Якщо ви вкажете /etc/resolv.conf напряму на upstream, ви можете обійти split DNS.
4) Що означає ~corp.example в resolvectl status?
Тильда позначає маршрутний домен: запити для цього домену йдуть до DNS‑серверів, прив’язаних до цього лінка.
Без тильди це більше нагадує search‑домен, що змінює спосіб розширення коротких імен.
5) Чому dig працює, а мої додатки все одно падають?
dig @server обходить вашу політику резолвера і ставить запит напряму до сервера. Воно доводить досяжність і коректність сервера,
але не те, що ОС використовує цей сервер для відповідного домену. Додатки також можуть використовувати DoH або власний стек резолвера.
6) Чому DNS працює для маленьких записів, але падає для деяких доменів?
Великі відповіді (кілька A/AAAA, DNSSEC, великі TXT) можуть натрапити на проблеми UDP‑фрагментації через VPN.
Тестуйте з dig +tcp. Якщо TCP працює, а UDP — ні, вирішіть питання MTU/фрагментації або поведінки фаєрвола.
7) Можу я просто додати публічний DNS на кшталт 1.1.1.1 як fallback?
Можете, але це політичне рішення з наслідками. Часто це призводить до витоку внутрішніх запитів на публічний DNS або непередбачуваних відмов,
і може маскувати відсутні маршрути VPN. Якщо компанія вимагає внутрішнього резолювання — не робіть цього.
8) Як зрозуміти, чи VPN примусово встановлює маршрут за замовчуванням?
Перевірте ip route наявність default‑маршруту та nmcli connection show на ipv4.never-default.
Також перевірте ip rule на політичну маршрутизацію, яка може перевизначати default.
9) Чому це ламається лише після перепідключення VPN?
Умови гонки та застарілий стан: маршрути й домени DNS можуть не повністю видалятись при відключенні
або не коректно застосовуватися при підключенні. Підтвердіть стан після reconnect з ip route і resolvectl status.
10) Який найбезпечніший спосіб перевірити виправлення?
Перевірте три речі: (1) ip route get DNS_IP використовує очікуваний інтерфейс, (2) resolvectl status показує коректні пер‑лінкові DNS і маршрутні домени,
(3) getent ahosts резольвить внутрішні і публічні імена як очікується з увімкненим і вимкненим VPN.
Висновок: практичні наступні кроки
Коли VPN ламає DNS на Ubuntu 24.04, виграшний хід — це порядок. Спочатку маршрути. Потім політика резолвера. Потім split DNS. Нарешті кеші.
Якщо виправляти в зворотному порядку, ви отримаєте те, що «працює», поки не перестане — зазвичай під час презентації, на виклику або обох.
Наступні кроки, які можна зробити вже сьогодні:
- Запустіть Швидкий план діагностики і збережіть виводи для
ip routeіresolvectl status. - Перевірте досяжність VPN DNS‑сервера через
ip route getіnc -uvz. - Відновіть stub
/etc/resolv.conf, якщо VPN‑клієнт його перезаписав. - Виправте профіль VPN/сервер, щоб маршрути й маршрутні домени відповідали DNS‑серверам, які він штовхає.
- Додайте регресійний чекліст на чистому образі Ubuntu 24.04, бо стан вчорашнього ноутбука — не тестове середовище.
Збої DNS рідко гламурні. Вони, однак, надзвичайно чесні: система виконає точно те, що вказують ваші маршрути і політика резолвера.
Зробіть ці дві речі коректними — і решта, як правило, стане на свої місця.