Ubuntu 24.04: Resolv.conf постійно змінюється — правильне виправлення systemd-resolved/NetworkManager

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

Ви редагуєте /etc/resolv.conf, воно працює п’ять хвилин, а потім «дбайливо» відкатується. Ваш застосунок втрачає резолюцію імен, split DNS вашого VPN перестає працювати, а канал чергових починає пахнути підгорілим тостом.

Ubuntu 24.04 не зламав DNS. Він просто зробив власників DNS більш явними: systemd-resolved, NetworkManager, DHCP і іноді VPN-плагіни всі намагаються бути «дорослими в кімнаті». Якщо ви не оберете один авторитет — і не підключите інших чисто — resolv.conf перетворюється на війну записів.

Ментальна модель: хто володіє DNS в Ubuntu 24.04

/etc/resolv.conf виглядає як простий файл. У сучасному Ubuntu це часто симлінк на згенерований файл. Це не змова; це сантехніка. Справжнє питання: який компонент є джерелом істини для DNS?

Головні учасники

  • systemd-resolved: локальна служба резолюції, яка може кешувати, підтримувати DNS-over-TLS (в деяких налаштуваннях) та per-link DNS (split DNS). Зазвичай вона відкриває локальний stub на 127.0.0.53 і пише «керований» resolv.conf.
  • NetworkManager: оркестратор мережі для десктопів і багатьох серверів, особливо коли netplan використовує renderer NetworkManager. Він збирає DNS від DHCP/VPN/статичної конфігурації і може передавати його systemd-resolved або писати /etc/resolv.conf напряму, залежно від налаштувань.
  • DHCP клієнти (часто через NetworkManager): надають DNS-сервери і search-домени, іноді агресивно. Якщо DHCP-сервер невірний, ваша машина стає невірною, стабільно і масово.
  • VPN-плагіни: додають маршрути і DNS. Деякі очікують split DNS. Деякі скидають повний override DNS. Деякі намагаються і все одно програють локальній конфігурації.
  • netplan: генерує нижчорівневу конфігурацію. Водночас він сам по собі не «робить DNS» під час роботи, але вирішує, який renderer (NetworkManager або systemd-networkd) буде це робити.

Що зазвичай означає «resolv.conf постійно змінюється»

Це майже ніколи не випадково. Це детермінований результат одного з наступних:

  • /etc/resolv.conf — симлінк на згенерований файл, і ви постійно редагуєте вивід цільового файлу замість входів.
  • NetworkManager налаштований використовувати systemd-resolved, але resolved відключений або неправильно посилений, тож NetworkManager починає писати власний файл.
  • Два менеджери DNS увімкнені і обидва вважають себе відповідальними.
  • VPN піднімається і штовхає DNS, потім DHCP оновлює і замінює його (або навпаки).
  • Якийсь інструмент конфігурації (cloud-init, provisioning, конфігураційний менеджер) «виправляє» DNS під час завантаження.

Сухий жартах: /etc/resolv.conf — це скотч Linux-мережі — хтось завжди вважає це «правильним місцем» для латання, і воно завжди відривається о 3:00 ранку.

Обирайте один авторитет. Підключайте інших так, щоб вони йому подавали інформацію. І припиніть редагувати /etc/resolv.conf вручну, якщо ваша мета — не створити загадку для себе в майбутньому.

Швидка діагностика (перевірте це спочатку)

Якщо DNS не працює або resolv.conf не затримується, не починайте з редагування. Почніть з відповідей на питання: «Хто останнім його писав?» і «Хто система вважає відповідальним за DNS?»

По-перше: визначте, чим насправді є /etc/resolv.conf

Це реальний файл чи симлінк? Якщо це симлінк — куди він вказує?

По-друге: з’ясуйте, чи активний systemd-resolved і що він думає

Якщо resolved працює, resolvectl status — ваше джерело істини щодо того, які DNS-сервери фактично використовуються по інтерфейсу, включно з VPN-лінками.

По-третє: перевірте режим DNS у NetworkManager

NetworkManager може бути налаштований використовувати resolved, dnsmasq або писати resolv.conf. Неправильний режим — найшвидший спосіб отримати файл, що змінюється щоразу, коли лінк «махне хвостом».

По-четверте: відтворіть і спостерігайте зміни в реальному часі

Коли ви не можете пояснити зміну, подивіться, як вона відбувається: tail файлу, дивіться часові мітки та корелюйте з журналами. Більшість «таємних перезаписів» — це оновлення DHCP або перепідключення VPN.

Цікаві факти й історія (бо у цього безладу є своя легенда)

  • Факт 1: /etc/resolv.conf з’явився раніше за більшість сучасних стеків мережі Linux; він походить із Unix-традицій, де конфігурація DNS була простим статичним файлом.
  • Факт 2: Підхід «stub resolver» (локальна адреса 127.x) існує, бо дозволяє кешування та політику per-interface без необхідності навчати кожен застосунок новим трюкам.
  • Факт 3: Ubuntu вже давно використовує симлінки для керування /etc/resolv.conf (через різні інструменти з часом), бо кілька компонентів хочуть динамічно постачати DNS.
  • Факт 4: split DNS став мейнстримом не через елегантність, а тому що корпоративні VPN і cloud VPC змусили його. Один резолвер для всього перестав працювати.
  • Факт 5: search-домени — це фіча для продуктивності, яка також є підступною: довгий список пошуку може уповільнити резолюцію, витікати запити або породжувати несподівані конфлікти імен.
  • Факт 6: історично багато libc резолверів читали лише /etc/resolv.conf і ігнорували хитрі служби часу виконання. Ось чому симлінк досі важливий: це сумісницький клей.
  • Факт 7: Кешування DNS на хості може давати приріст у продуктивності, але також посилювати відмови, коли негативне кешування зберігає помилки.
  • Факт 8: Поведінка DHCP з опцією «DNS» сильно варіюється в мережевому обладнанні; деякі середовища перезаписують DNS при оновленні, навіть коли в UI встановлено «manual DNS».

Одна перефразована ідея від експерта з надійності, яку варто тримати в голові: перефразована ідея: «Надія — не стратегія» — приписується Gene Kranz, часто цитують в операційних колах. Виправлення DNS на основі надії призводять до неприємних допитів перед комісією з змін.

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

Вам потрібна відтворювана діагностика. Ось конкретні завдання, що працюють на Ubuntu 24.04. Кожне містить те, що зазвичай означає вивід, і яке рішення обрати далі.

Завдання 1: Подивіться, чи /etc/resolv.conf є симлінком

cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Jun  2 10:14 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

Значення: Файл керований. Ручне редагування тимчасове найкраще.

Рішення: Припиніть редагувати файл. Вирішіть, чи хочете ви використовувати resolved (рекомендовано) чи ні, а потім налаштуйте входи відповідно.

Завдання 2: Ідентифікуйте вміст цілі симлінка

cr0x@server:~$ cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
nameserver 127.0.0.53
options edns0 trust-ad
search corp.example

Значення: Система очікує, що застосунки запитуватимуть локальний stub, а не напряму upstream DNS.

Рішення: Якщо DNS не працює, перевірте стан resolved і upstream-сервери, замість заміни цього файлу публічними резолверами.

Завдання 3: Перевірте, чи systemd-resolved запущений

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

Значення: resolved активний. Добре. Тепер запитайте його, які DNS він фактично використовує.

Рішення: Якщо він неактивний або замаскований, не намагайтеся зберегти stub-resolv.conf. Виберіть Рецепт B замість цього.

Завдання 4: Перегляньте погляд resolved на DNS (глобально та по лінках)

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

Link 2 (ens192)
    Current Scopes: DNS
         Protocols: +DefaultRoute
Current DNS Server: 10.10.0.53
       DNS Servers: 10.10.0.53 10.10.0.54
        DNS Domain: corp.example

Значення: resolved — авторитет, і в нього є upstream-сервери. Якщо луки не проходять, upstream може бути недоступним, заблокованим або неправильним.

Рішення: Якщо «Current DNS Server» порожній або вказує на щось несподіване (наприклад, VPN-лінк, коли ви не в VPN), зосередьтесь на конфігурації NetworkManager/VPN.

Завдання 5: Підтвердіть, що NetworkManager керує інтерфейсом

cr0x@server:~$ nmcli device status
DEVICE   TYPE      STATE      CONNECTION
ens192   ethernet  connected  Wired connection 1
lo       loopback  unmanaged  --

Значення: NetworkManager — за кермом для ens192.

Рішення: Налаштуйте DNS через профілі підключення NetworkManager (або netplan, що їх генерує), а не редагуйте resolv.conf вручну.

Завдання 6: Перевірте режим DNS у NetworkManager

cr0x@server:~$ nmcli general status
STATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN
connected  full          enabled  enabled  enabled  enabled
cr0x@server:~$ grep -R "^\[main\]$\|^dns=" -n /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d/*.conf 2>/dev/null
/etc/NetworkManager/conf.d/10-dns.conf:1:[main]
/etc/NetworkManager/conf.d/10-dns.conf:2:dns=systemd-resolved

Значення: NetworkManager налаштований передавати інформацію systemd-resolved. Це адекватний стандарт у багатьох Ubuntu-налаштуваннях.

Рішення: Якщо DNS нестабільний, підтвердьте, що resolved увімкнено і resolv.conf вказує на stub. Якщо ж ви хочете, щоб NM володів resolv.conf, чисто перейдіть на Рецепт B.

Завдання 7: Перевірте DNS-налаштування активного підключення

cr0x@server:~$ nmcli -g ipv4.method,ipv4.dns,ipv4.ignore-auto-dns,ipv4.dns-search connection show "Wired connection 1"
auto
10.10.0.53,10.10.0.54
no
corp.example

Значення: У вас є явні DNS-сервери й DHCP auto-DNS не ігнорується (no). Це може призвести до змішаних списків DNS залежно від поведінки DHCP.

Рішення: Якщо ви хочете детермінованого DNS, розгляньте встановлення ipv4.ignore-auto-dns yes і явне вказання DNS/search (з віддачею, що ви повинні будете це підтримувати).

Завдання 8: Подивіться останні логи, які пояснюють, хто переписав DNS

cr0x@server:~$ journalctl -u systemd-resolved -n 80 --no-pager
Dec 29 09:01:10 server systemd-resolved[812]: Using DNS server 10.10.0.53 for interface ens192.
Dec 29 09:05:34 server systemd-resolved[812]: Switching to DNS server 10.10.0.54 for interface ens192.
cr0x@server:~$ journalctl -u NetworkManager -n 120 --no-pager
Dec 29 09:05:31 server NetworkManager[701]: <info>  [..] dhcp4 (ens192): option domain_name_servers => '10.10.0.54 10.10.0.53'

Значення: Оновлення DHCP змінило порядок DNS у пропозиції; resolved пішов за ним.

Рішення: Вирішіть, чи довіряти DHCP. Якщо ні — перекрийте в NM профілі DNS і встановіть ipv4.ignore-auto-dns yes.

Завдання 9: Спостерігайте за /etc/resolv.conf у реальному часі

cr0x@server:~$ sudo inotifywait -m /etc/resolv.conf
Setting up watches.
Watches established.
/etc/resolv.conf MODIFY
/etc/resolv.conf ATTRIB

Значення: Хтось торкається файлу; тепер зіставте часові мітки з логами.

Рішення: Використайте мітку часу події, щоб прогнати grep по журналах навколо того часу; не гадати.

Завдання 10: Перевірте резолюцію через resolved явно

cr0x@server:~$ resolvectl query repo.corp.example
repo.corp.example: 10.20.30.40                      -- link: ens192

-- Information acquired via protocol DNS in 18.7ms.
-- Data is authenticated: no

Значення: resolved може резолвити це ім’я, використовуючи свій поточний DNS-шлях.

Рішення: Якщо застосунки все ще падають, можливо проблема в nsswitch, DNS контейнера або застосунок робить власні DNS-запити (так, деякі так роблять).

Завдання 11: Перевірте резолюцію «класичним» способом (і порівняйте)

cr0x@server:~$ getent hosts repo.corp.example
10.20.30.40     repo.corp.example

Значення: Glibc NSS резолюція працює для звичайних застосунків.

Рішення: Якщо resolvectl query працює, але getent не (або навпаки), перевірте /etc/nsswitch.conf і чи застосунки обходять NSS.

Завдання 12: Підтвердіть вибір renderer у netplan (хто має керувати лінками)

cr0x@server:~$ sudo netplan get
network:
  version: 2
  renderer: NetworkManager

Значення: NetworkManager має управляти мережею на цьому хості.

Рішення: Уникайте ввімкнення конфігурацій systemd-networkd, що конкурують, якщо ви не плануєте міграцію.

Завдання 13: Перевірте, чи cloud-init перезаписує мережу/DNS

cr0x@server:~$ cloud-init status
status: done
cr0x@server:~$ grep -R "manage_resolv_conf" -n /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg.d/*.cfg 2>/dev/null
/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg:2:manage_resolv_conf: false

Значення: Якщо manage_resolv_conf true, cloud-init може переписувати стан резолвера при завантаженні.

Рішення: В образах для хмар явно відключіть керування резолвером cloud-init, якщо ви не хочете, щоб він це робив.

Завдання 14: Перевірте, чи якийсь локальний dnsmasq або інший резолвер забирає порт 53

cr0x@server:~$ sudo ss -lntup | grep -E ":53\s"
udp   UNCONN 0      0          127.0.0.53%lo:53        0.0.0.0:*    users:(("systemd-resolve",pid=812,fd=14))
tcp   LISTEN 0      4096       127.0.0.53%lo:53        0.0.0.0:*    users:(("systemd-resolve",pid=812,fd=15))

Значення: resolved слухає на stub. Це очікувано в режимі stub.

Рішення: Якщо ви бачите dnsmasq або іншу службу, що прив’язана до 127.0.0.53 або 0.0.0.0:53, у вас конфлікт. Вирішіть, який резолвер повинен працювати, і відключіть інший.

Оберіть архітектуру (не змішуйте ці підходи)

Архітектура 1: systemd-resolved — резолвер, NetworkManager постачає йому дані

Це «нативний для Ubuntu» підхід для багатьох інсталяцій. Ви отримуєте per-interface DNS, адекватну поведінку VPN і чисту історію, звідки приходять зміни. Ваш /etc/resolv.conf зазвичай вказує на stub.

Коли робити: у вас є VPN, кілька лінків, вимоги split DNS або ви хочете сучасну поведінку, що не залежить від кожного застосунку.

Архітектура 2: відключити systemd-resolved, NetworkManager пише /etc/resolv.conf

Це «класичний» підхід: застосунки читають /etc/resolv.conf з upstream-серверами. Це простіше, і іноді це виправдано. Але ви втрачаєте частину можливостей split DNS, якщо VPN-інструменти не компенсують це.

Коли робити: ви керуєте мінімальними серверами, вам не потрібен split DNS або ваш стек застосунків погано працює з stub-резолверами.

Архітектура 3: статичний /etc/resolv.conf (immutable або ручне керування)

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

Коли робити: DNS-сервери ніколи не змінюються і ви розумієте операційні витрати. Інакше — не робіть цього.

Ще одна суха іронія: якщо ви «просто chattr +i» свій шлях з DNS-хаосу, ви не виправляєте систему — ви заводите хобі.

Рецепт A (рекомендовано): systemd-resolved + NetworkManager, правильно

Цільовий стан

  • systemd-resolved увімкнено та запущено
  • NetworkManager встановлено в dns=systemd-resolved
  • /etc/resolv.conf симлінкований на stub (або на «реальний» файл resolved, залежно від вашого уподобання)
  • DNS налаштовано в профілях підключення NetworkManager (або успадковується від DHCP/VPN як передбачено)

Крок 1: переконайтеся, що systemd-resolved увімкнено

cr0x@server:~$ sudo systemctl enable --now systemd-resolved
Created symlink /etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /usr/lib/systemd/system/systemd-resolved.service.

Значення: resolved запускатиметься при завантаженні і запущено зараз.

Рішення: Якщо увімкнення не вдається через маскування, розмаскуйте і знову увімкніть.

cr0x@server:~$ sudo systemctl unmask systemd-resolved
Removed "/etc/systemd/system/systemd-resolved.service".

Крок 2: налаштуйте NetworkManager використовувати resolved

Створіть (або перевірте) drop-in конфіг і не редагуйте головний файл вручну, щоб потім не забути.

cr0x@server:~$ sudo tee /etc/NetworkManager/conf.d/10-dns-systemd-resolved.conf >/dev/null <<'EOF'
[main]
dns=systemd-resolved
EOF
cr0x@server:~$ sudo systemctl restart NetworkManager

Значення: NetworkManager оновлюватиме resolved замість боротьби за resolv.conf.

Рішення: Якщо раніше використовували dns=dnsmasq, видаліть його, хіба що ви свідомо хочете dnsmasq попереду (більшість людей не хоче).

Крок 3: виправте симлінк /etc/resolv.conf

На системі, якою керує resolved, зазвичай бажано посилання на stub-файл:

cr0x@server:~$ sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 37 Dec 29 09:21 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf

Значення: застосунки бачать 127.0.0.53 і використовують resolved для політики.

Рішення: Якщо у вас є ПО, що ламається через stub-резолвер (деякі старі контейнери, вбудовані рантайми або дивні chroot), розгляньте посилання на «реальний» upstream-список замість цього:

cr0x@server:~$ sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Той файл містить upstream-сервери напряму. Ви втрачаєте деякі переваги, але зберігаєте сумісність.

Крок 4: налаштуйте DNS у правильному місці (профілі NM)

Якщо ви хочете статичний DNS незалежно від DHCP:

cr0x@server:~$ sudo nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
cr0x@server:~$ sudo nmcli connection modify "Wired connection 1" ipv4.dns "10.10.0.53 10.10.0.54"
cr0x@server:~$ sudo nmcli connection modify "Wired connection 1" ipv4.dns-search "corp.example"
cr0x@server:~$ sudo nmcli connection up "Wired connection 1"
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7)

Значення: NetworkManager перестане імпортувати DNS від DHCP для цього підключення і використовуватиме вказане вами.

Рішення: Використовуйте це лише якщо DHCP DNS недостовірний або вам потрібна послідовна поведінка між мережами.

Крок 5: перевірте end-to-end

cr0x@server:~$ resolvectl status | sed -n '1,35p'
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.10.0.53
       DNS Servers: 10.10.0.53 10.10.0.54
        DNS Domain: corp.example

Значення: resolved у режимі stub і має ваші бажані upstream-и.

Рішення: Якщо resolv.conf mode — «foreign», щось інше пише resolv.conf. Йдіть прямо до розділу «Поширені помилки».

Рецепт B: відключити systemd-resolved і дозволити NetworkManager писати resolv.conf

Це для середовищ, де ви хочете стару поведінку і приймаєте компроміси. Головне — зробити це чисто: відключити resolved, замінити симлінк на реальний файл (або NM-керований файл) і налаштувати DNS-плагін NetworkManager відповідно.

Крок 1: зупиніть і відключіть resolved

cr0x@server:~$ sudo systemctl disable --now systemd-resolved
Removed "/etc/systemd/system/multi-user.target.wants/systemd-resolved.service".

Значення: resolved не запускатиметься і не керуватиме поведінкою stub.

Рішення: Переконайтеся, що після цього ніхто інший не посилається на 127.0.0.53.

Крок 2: налаштуйте NetworkManager керувати DNS напряму

Залежно від середовища, встановлення dns=default зазвичай достатнє.

cr0x@server:~$ sudo tee /etc/NetworkManager/conf.d/10-dns-default.conf >/dev/null <<'EOF'
[main]
dns=default
EOF
cr0x@server:~$ sudo rm -f /etc/NetworkManager/conf.d/10-dns-systemd-resolved.conf
cr0x@server:~$ sudo systemctl restart NetworkManager

Значення: NetworkManager писатиме інформацію про резолвер своїм стандартним механізмом.

Рішення: Якщо у вас були інші DNS-плагіни, видаліть їх; змішані плагіни дають непередбачувані результати.

Крок 3: замініть /etc/resolv.conf на звичайний файл

cr0x@server:~$ sudo rm -f /etc/resolv.conf
cr0x@server:~$ sudo touch /etc/resolv.conf
cr0x@server:~$ sudo chmod 644 /etc/resolv.conf
cr0x@server:~$ ls -l /etc/resolv.conf
-rw-r--r-- 1 root root 0 Dec 29 09:40 /etc/resolv.conf

Значення: це більше не симлінк.

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

cr0x@server:~$ sudo nmcli networking off
cr0x@server:~$ sudo nmcli networking on
cr0x@server:~$ cat /etc/resolv.conf
nameserver 10.10.0.53
nameserver 10.10.0.54
search corp.example

Значення: застосунки виконуватимуть запити безпосередньо до upstream DNS.

Рішення: Підтвердіть, що жодна служба не очікує 127.0.0.53; якщо у вас були контейнери або локальні резолвери, налаштуйте їх відповідно.

Рецепт C: статичний resolv.conf (тільки якщо ви серйозно це маєте на увазі)

Статичний /etc/resolv.conf може підходити для певних приладів або ізольованих серверів. Це не загальне виправлення для «воно постійно змінюється», бо не вирішує, хто намагається його змінити.

Зробіть його статичним без ігор з файловою системою

Переважайте політику над незмінністю. Скажіть NetworkManager перестати чіпати DNS для цього підключення:

cr0x@server:~$ sudo nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
cr0x@server:~$ sudo nmcli connection modify "Wired connection 1" ipv6.ignore-auto-dns yes
cr0x@server:~$ sudo nmcli connection up "Wired connection 1"

Потім керуйте файлом явно:

cr0x@server:~$ sudo tee /etc/resolv.conf >/dev/null <<'EOF'
nameserver 10.10.0.53
nameserver 10.10.0.54
search corp.example
options timeout:2 attempts:2
EOF

Значення: ви берете на себе відповідальність за оновлення DNS. Тепер немає автоматичного безпечного механізму.

Рішення: Робіть це лише коли DNS-сервери стабільні і у вас є контроль за їхніми змінами.

VPN і split DNS: частина, яка зазвичай болить

Більшість скарг «resolv.conf постійно змінюється» насправді стосуються split DNS у масках. VPN піднімається, штовхає внутрішні домени і сервери, потім ваш основний інтерфейс оновлює DHCP і переупорядковує DNS. Або VPN-клієнт наполягає на default route і тягне DNS за собою.

Як має виглядати split DNS з systemd-resolved

З resolved ви хочете per-link домени і DNS-сервери. Внутрішні домени мають йти на VPN DNS; усе інше — на ваш звичайний DNS (або на публічні резолвери, якщо така ваша політика).

Діагностуйте, перевіривши per-link домени:

cr0x@server:~$ resolvectl status | sed -n '1,200p'
Global
resolv.conf mode: stub

Link 2 (ens192)
       DNS Servers: 10.10.0.53 10.10.0.54
        DNS Domain: ~.

Link 8 (tun0)
       DNS Servers: 172.16.1.10
        DNS Domain: corp.example

Значення:

  • ~. вказує на домен з маршрутизацією за замовчуванням (усі імена) для цього лінка. Якщо ваш VPN-лінк отримує ~., він може перехопити всі DNS-запити.
  • Домени типу corp.example без ~. маршрутизуються лише для цього суфіксу.

Рішення: Якщо VPN «краде» все, але не повинен, налаштуйте параметри VPN-плагіна або властивості NM-підключення, щоб уникнути встановлення VPN як default DNS route.

Крутилки NetworkManager, що впливають на поведінку VPN DNS

Вони відрізняються за типом VPN, але підхід до налагодження однаковий: перегляньте властивості профілю підключення (IP і маршрути), потім переконайтеся, що VPN не налаштований як «використовувати це підключення тільки для ресурсів у його мережі», якщо ви цього не хочете.

Перевірте деталі VPN-підключення:

cr0x@server:~$ nmcli connection show "Corp VPN" | grep -E "ipv4\.|ipv6\.|vpn\."
ipv4.never-default:                         no
ipv4.ignore-auto-dns:                       no
ipv4.dns:                                   --
ipv4.dns-search:                            --

Значення: Якщо never-defaultno, VPN може стати default route залежно від поведінки плагіна. Якщо ignore-auto-dnsno, він може імпортувати DNS і потенційно перекрити його.

Рішення: Для split-tunnel поведінки встановіть ipv4.never-default yes для VPN-підключення і переконайтеся, що домени налаштовано конкретно.

cr0x@server:~$ sudo nmcli connection modify "Corp VPN" ipv4.never-default yes
cr0x@server:~$ sudo nmcli connection up "Corp VPN"

Коли застосунки ігнорують системний резолвер

Деякі рантайми поставляють власний резолвер або кеш. Деякі контейнери монтують свій /etc/resolv.conf. Деякі Java-стеки кешують DNS, що робить відмови довшими, ніж мали би бути.

Якщо хост резолвить, але застосунок — ні, порівняйте це:

cr0x@server:~$ getent hosts internal.service.corp.example
10.50.0.15     internal.service.corp.example
cr0x@server:~$ sudo resolvectl query internal.service.corp.example
internal.service.corp.example: 10.50.0.15 -- link: tun0

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

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

1) Симптом: /etc/resolv.conf скидається на 127.0.0.53 після кожного перезавантаження

Корінь проблеми: Ви на Рецепті A (resolved), але постійно замінюєте симлінк звичайним файлом. Служби при завантаженні відновлюють симлінк.

Виправлення: Вирішіть використовувати resolved і налаштуйте DNS через NetworkManager; тримайте /etc/resolv.conf симлінкованим на /run/systemd/resolve/stub-resolv.conf (або на /run/systemd/resolve/resolv.conf для сумісності).

2) Симптом: resolv.conf містить upstream-сервери, але resolvectl показує інші сервери

Корінь проблеми: Режим «foreign»: щось інше, крім resolved, керує /etc/resolv.conf, але resolved все ще працює і приймає власні рішення для застосунків, що запитують stub.

Виправлення: Або відключіть resolved (Рецепт B), або відновіть симлінк resolv.conf (Рецепт A). Не запускайте обидва підходи одночасно.

3) Симптом: DNS працює до підключення VPN; потім публічні DNS-запити падають (або навпаки)

Корінь проблеми: VPN налаштований як default route і/або default DNS routing domain (~.), перехоплюючи всі запити.

Виправлення: Налаштуйте split DNS: VPN має володіти тільки корпоративними суфіксами; встановіть ipv4.never-default yes і переконайтеся, що домени scoped. Перевірте через resolvectl status.

4) Симптом: DNS змінюється кожні кілька годин

Корінь проблеми: DHCP оновлення переупорядковують або замінюють DNS-сервери; NetworkManager чесно їх імпортує.

Виправлення: Якщо DHCP DNS неправильний, перекрийте його в NM-профілі і встановіть ipv4.ignore-auto-dns yes. Інакше виправте конфігурацію DHCP-сервера (правильне рішення, але не завжди просте).

5) Симптом: «Temporary failure in name resolution» періодично, особливо під навантаженням

Корінь проблеми: Upstream DNS повільний/недоступний, або розгортання search-доменів призводить до множинних невдалих запитів на кожну резолюцію. Іноді MTU/фрагментація VPN викликають проблеми з UDP DNS.

Виправлення: Виміряйте за допомогою resolvectl query, перегляньте search-домени і протестуйте TCP-фолбек. Якщо VPN задіяний, перевірте MTU і розгляньте зменшення розміру DNS-пакетів на upstream-рівні (не калічте resolv.conf).

6) Симптом: Контейнери резолвлять інакше, ніж хост

Корінь проблеми: Рантайм контейнера інжектить власний /etc/resolv.conf. Також часто файл вказує на 127.0.0.53, який недоступний з мережевого простору контейнера.

Виправлення: Налаштуйте рантайм використовувати upstream-resolv.conf (для resolved-налаштувань використовуйте /run/systemd/resolve/resolv.conf як джерело) або надайте DNS-сервер, доступний з контейнера.

7) Симптом: Ви відключаєте resolved, але застосунки все ще запитують 127.0.0.53

Корінь проблеми: /etc/resolv.conf все ще вказує на stub-resolv.conf, або маєте застарілі конфігурації в chroot/контейнерах.

Виправлення: Замініть resolv.conf на реальний файл з upstream-серверами та перезапустіть служби, що кешують стан резолвера.

Чек-листи / поетапний план

Чек-лист 1: Зробити DNS стабільним на типовому робочому столі Ubuntu 24.04 (рекомендовано)

  1. Підтвердіть, що netplan використовує NetworkManager: sudo netplan get → шукайте renderer: NetworkManager.
  2. Увімкніть resolved: sudo systemctl enable --now systemd-resolved.
  3. Встановіть NM використовувати resolved через drop-in у /etc/NetworkManager/conf.d/.
  4. Симлінкуйте /etc/resolv.conf на /run/systemd/resolve/stub-resolv.conf.
  5. Налаштуйте DNS по NM-підключенню, якщо потрібно перекрити DHCP: nmcli connection modify ... ipv4.ignore-auto-dns yes.
  6. Перевірте за допомогою resolvectl status і getent hosts.
  7. Підключіть VPN і повторно перевірте per-link DNS-домени; виправте крадіжку default-route, якщо вона відбувається.

Чек-лист 2: Зробити DNS стабільним на сервері, де ви хочете класичний resolv.conf

  1. Відключіть resolved: sudo systemctl disable --now systemd-resolved.
  2. Налаштуйте NetworkManager dns=default (або обраний плагін, але оберіть лише один).
  3. Замініть симлінк /etc/resolv.conf на звичайний файл.
  4. Перезапустіть мережу: sudo nmcli networking off && sudo nmcli networking on.
  5. Переконайтеся, що /etc/resolv.conf містить upstream-сервери і getent hosts працює.
  6. Для VPN-клієнтів переконайтеся, що вони оновлюють resolv.conf контрольовано або використовуйте явні DNS-налаштування.

Чек-лист 3: Коли «щось постійно це змінює» і потрібні докази

  1. Спостерігайте зміни: sudo inotifywait -m /etc/resolv.conf.
  2. Збережіть часові мітки і зіставте з journalctl -u NetworkManager і journalctl -u systemd-resolved.
  3. Перевірте cloud-init: cloud-init status і grep на manage_resolv_conf.
  4. Пошукайте зміни від конфігураційної автоматики: ваші скрипти, systemd-юнити і cron (так, люди все ще кронають DNS-правки).
  5. Коли знайдете конкурента — видаліть його. Не торгуйтеся з ним.

Три корпоративні міні-історії з реального життя

Міні-історія 1: Інцидент через неправильне припущення

Команда мала фліт Ubuntu-серверів, в більшості стабільних і нудних. Новий внутрішній сервіс почав фейлити так, ніби це баг в застосунку: випадкові 502, повторні спроби, потім все «магічно» само відновлювалося. Перше припущення було найгіршим: «DNS не може бути проблемою, ми прописали його в resolv.conf».

Насправді вони «впирали» його. Місяці тому хтось редагував /etc/resolv.conf напряму, щоб змусити внутрішні DNS-сервери, бо DHCP в одному середовищі роздавав публічні резолвери. Це працювало до наступного перезавантаження, потім знову редагували. Згодом додали правило конфігураційного менеджера, щоб переписувати щодня. Це не управління DNS; це whack-a-mole з root-привілеями.

Після оновлення деяких хостів systemd-resolved став активним і /etc/resolv.conf знову став симлінком. Щоденна задача конфігменного менеджера замінювала його файлом з upstream DNS, але деякі застосунки все ще використовували resolved у певних контекстах, а деякі служби кешували резолюцію по-різному. На одному хості існувало два шляхи резолюції. Відмови залежали від синхронізації і від того, який шлях використовував процес.

Виправленням було не «поставити кращі DNS-сервери». Виправленням стало обрати власника: вони стандартизували resolved + NetworkManager, прибрали щоденну задачу і перемістили політику DNS у NM-профілі. Коли система отримала одиний джерело істини, «баг застосунку» зник. Постмортем був неприємним через одне: усі знали, що вони редагували resolv.conf як у 2003.

Міні-історія 2: Оптимізація, що зіграла злий жарт

Інша організація мала ініціативу продуктивності: зменшити латентність DNS для мікросервісів. Хтось помітив повторні запити до тих самих імен і вирішив, що локальне кешування допоможе. Вони увімкнули кешування на хості і штовхнули конфіг, щоб всі робочі навантаження зверталися до локального stub-резолвера.

Латентність зменшилась. Всім стало добре. Потім часткова відмова upstream DNS почала проявлятися: авторитетні сервери були нестабільні — таймаути, occasional SERVFAIL. Локальний кеш почав негативно кешувати невдачі. Один короткий miss перетворився на тривале «ні» на час життя кешу, і відсоток відмов по службах пішов з «піків і відновлення» в «плоску і брутальну» відмову.

Найгірше: відмова виглядала як регресія застосунку, бо рестарти не допомагали. Деякі хости швидко відновилися; інші — ні. Різниця була в стані кешу. Люди почали зливати ноди, відмотувати релізи і сперечатися, яка зміна це спричинила. Справжній винуватець — оптимізація, що прибрала природний джиттер і перетворила транзієнтні DNS-проблеми на липкі.

Вони врешті лишили кешування, бо воно не було помилкою само по собі. Але вони пом’якшили негативне кешування де можливо, покращили надійність upstream DNS і — що важливіше — додали діагностику: знімки resolvectl status у інцидентних рукописах. Оптимізації ок, але таємні оптимізації — це новий звук тривоги.

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

Одне підприємство мало нудний, майже дратівливий стандарт: кожний Linux-хост повинен мати перевірку «хто володіє DNS» як частину провізіонінгу. Вона перевіряла, чи хост використовує resolved чи ні, забезпечувала відповідний стан симлінка і підтверджувала режим DNS у NetworkManager. Інженери скаржилися, що це бюрократія.

Потім було злиття. Дві мережі, два VPN-рішення, два набори DHCP-політик і один об’єднаний фліт ноутбуків і билд-агентів. DNS-поведінка стала непередбачуваною за ніч. Природна людська відповідь — застосувати «швидкі виправлення» до resolv.conf на уражених хостах.

Команди, що дотримувались нудного стандарту, цього не робили. Вони проганяли перевірку власності, бачили, яка частина стеку має керувати DNS, і правили лише входи: NM-профілі DNS і scoping VPN split DNS. Це зробило їхні виправлення довговічними. Перезавантаження не ламали речі знову. Перепідключення VPN не випадково не міняли порядок резолверів.

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

Поширені запитання

1) Чому /etc/resolv.conf — симлінк в Ubuntu 24.04?

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

2) Чи 127.0.0.53 «невірна»?

Ні. Це локальна адреса stub-резолвера, яку використовує systemd-resolved. Застосунки надсилають DNS-запити туди; resolved пересилає їх на реальні upstream DNS-сервери згідно з per-link політикою.

3) Як припинити зміну resolv.conf?

Припиніть вважати /etc/resolv.conf джерелом конфігурації. Оберіть архітектуру: або використовуйте resolved і налаштуйте NetworkManager для нього (Рецепт A), або відключіть resolved і дайте NetworkManager писати upstream-сервери напряму (Рецепт B).

4) Що означає «resolv.conf mode: foreign» в resolvectl?

Зазвичай це означає, що resolved визначив, що /etc/resolv.conf не є його керованим файлом/симлінком, тож щось інше ним керує. Це знак, що у вас є конкуренція власників і слід вибрати один і очистити стан.

5) Я встановив DNS у графічному інтерфейсі, але воно постійно повертається. Чому?

Зазвичай тому, що DHCP досі дозволено підставляти DNS і перекривати/зливати налаштування. Перевірте nmcli -g ipv4.ignore-auto-dns .... Встановіть його в yes, якщо хочете детермінованого ручного DNS для цього підключення.

6) VPN ламає мій публічний DNS або корпоративний DNS. Який найкращий підхід?

Використовуйте split DNS з resolved: корпоративні зони спрямовуються на VPN DNS, все інше — на ваш звичайний DNS. Перевірте per-link домени за допомогою resolvectl status. Уникайте дозволяти VPN заявляти default routing domain, якщо ви не хочете, щоб весь DNS йшов через нього.

7) Чи варто робити /etc/resolv.conf незмінним за допомогою chattr?

Тільки якщо ви любите самостійно створені відмови. Це блокує легітимні оновлення DNS (оновлення DHCP, підключення VPN) і породжує заплутані режими відмови. Надайте перевагу правильному власництву і конфігурації.

8) Як налагоджувати «DNS працює на хості, але не в контейнерах»?

Перевірте, який /etc/resolv.conf бачить контейнер. Якщо він вказує на 127.0.0.53, але контейнер не може досягти цієї адреси (інший мережевий неймспейс), налаштуйте рантайм використовувати upstream-сервери (часто з /run/systemd/resolve/resolv.conf) або надайте досяжний DNS-сервер.

9) Чи погана ідея відключити systemd-resolved?

Не обов’язково. Це компроміс. Це спрощує речі для деяких серверних налаштувань, але ускладнює split DNS і поведінку VPN. Якщо відключаєте — робіть це чисто і переконайтеся, що ніхто більше не вказує на 127.0.0.53.

Висновок: стабільний DNS — стабільне життя

Довговічне виправлення для «resolv.conf постійно змінюється» — не боротися з файлом. Це обрати власника DNS і змусити всі інші компоненти підживлювати його замість змагання.

Наступні кроки, що реально витримають перезавантаження, перепідключення VPN і оновлення DHCP:

  • Зробіть швидку діагностику: перевірка симлінка → стан resolved → режим DNS NetworkManager → спостереження змін в реальному часі.
  • Якщо ви хочете сучасний split DNS і адекватну багатолінкову поведінку, реалізуйте Рецепт A і тримайте симлінк на stub.
  • Якщо ви хочете класичну поведінку для простого сервера, реалізуйте Рецепт B і видаліть stub повністю.
  • Задокументуйте обрану модель для вашого фліту. Найдорожчі інциденти з DNS починаються з «Я думав, що цей хост використовує…»
← Попередня
OpenVPN: Налаштуйте правильно (і чому він часто повільніший за WireGuard)
Наступна →
Втрачені паролі та шифрування: коли помилки стають незворотними

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