Triệu chứng chính: Temporary failure in name resolution, Could not resolve host, dig ra SERVFAIL/NXDOMAIN, tên nội bộ (split DNS) không phân giải được trong khi tên public thì được, hoặc đã đổi record mà máy vẫn trả IP cũ.
Trên Ubuntu, app gọi glibc → /etc/nsswitch.conf (hosts: files ... dns) → /etc/hosts rồi /etc/resolv.conf → stub 127.0.0.53 (systemd-resolved) → DNS server thật theo từng link. Khoanh vùng = hỏi từng tầng.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách xử lý |
|---|---|---|
dig @198.51.100.53 được, dig example.com không |
resolved không có DNS server cho link nào | resolvectl status; cấu hình nameservers trong netplan |
/etc/resolv.conf bị ghi đè, nội dung lạ |
Có công cụ khác (DHCP client, VPN, cloud-init) ghi file | Giữ symlink tới /run/systemd/resolve/stub-resolv.conf; cấu hình DNS ở netplan/resolved |
Tên nội bộ *.corp.example.com không phân giải khi bật VPN |
Query đi sai link, thiếu routing domain | resolvectl domain tun0 '~corp.example.com' (bền: cấu hình ở VPN/netplan) |
SERVFAIL chỉ với một số domain |
DNSSEC validate lỗi, hoặc upstream lỗi | dig +cd (bỏ validate) để so; resolvectl query --validate=no; xem DNSSEC= |
| Đã sửa record, máy vẫn trả IP cũ | Cache của resolved (theo TTL) hoặc cache ở app/JVM | resolvectl flush-caches; kiểm tra TTL bằng dig |
getent hosts khác dig |
/etc/hosts hoặc nsswitch đè |
grep name /etc/hosts; dig bỏ qua /etc/hosts, getent thì không |
| Container Docker không phân giải | Docker không dùng được 127.0.0.53, lấy DNS từ /run/systemd/resolve/resolv.conf |
Kiểm tra file đó có server thật; hoặc "dns": [...] trong daemon.json |
| Port 53 bị chiếm khi chạy dnsmasq/bind/Pi-hole | Stub listener của resolved giữ 127.0.0.53:53 |
DNSStubListener=no (xem bên dưới) |
| Query chậm đúng 5 giây rồi mới có kết quả | Server đầu tiên chết, timeout rồi mới chuyển server sau | Bỏ server chết khỏi cấu hình; resolvectl status xem Current DNS Server |
Tên ngắn host1 không phân giải |
Thiếu search domain | resolvectl domain eth0 example.com hoặc search: trong netplan |
Các bước khoanh vùng
flowchart TD A["App lỗi resolve"] --> B{"getent hosts name OK?"} B -->|Có| C["Lỗi ở app: cache, proxy, container"] B -->|Không| D{"resolvectl query name OK?"} D -->|Có| E["Kiểm tra nsswitch, /etc/resolv.conf"] D -->|Không| F{"dig @server-thật name OK?"} F -->|Có| G["resolved: link, routing domain, DNSSEC"] F -->|Không| H["Lỗi ở DNS server / zone / firewall"]
1. Cấu hình hiện tại
ls -l /etc/resolv.conf # nên là -> ../run/systemd/resolve/stub-resolv.conf
cat /run/systemd/resolve/resolv.conf # DNS server thật mà resolved đang dùng
resolvectl status # server + domain theo từng link, Current DNS Server
grep ^hosts /etc/nsswitch.conf2. Hỏi từng tầng
getent hosts app.example.com # đúng đường app đi (gồm /etc/hosts)
resolvectl query app.example.com # qua resolved, cho biết link nào trả lời
resolvectl query --cache=no app.example.com # bỏ qua cache
dig app.example.com # qua 127.0.0.53
dig @198.51.100.53 app.example.com # hỏi thẳng server, bỏ qua resolved
dig +tcp @198.51.100.53 app.example.com # nghi UDP 53 bị chặn / response lớn3. Phía server / zone
| Mục đích | Lệnh |
|---|---|
| Chỉ lấy kết quả | dig +short example.com A |
| Đi từ root xuống, thấy delegation hỏng ở đâu | dig +trace example.com |
| Serial SOA trên mọi NS (NS lệch dữ liệu) | dig +nssearch example.com |
| Hỏi authoritative, không đệ quy | dig +norecurse @ns1.example.com example.com |
| Reverse lookup | dig -x 203.0.113.5 |
| Xem TTL còn lại trong cache | dig example.com (cột thứ 2), chạy lại thấy giảm |
| Bỏ kiểm tra DNSSEC để so SERVFAIL | dig +cd example.com |
4. Log của resolved
sudo resolvectl log-level debug
journalctl -u systemd-resolved -f
sudo resolvectl log-level info # nhớ trả lại
resolvectl statistics # cache hit/miss, DNSSEC verdictCấu hình đúng
Đặt DNS bền qua netplan (nameservers:). Cấu hình chung cho resolved đặt ở drop-in:
[Resolve]
# Split DNS: chỉ gửi *.corp.example.com tới server nội bộ
DNS=198.51.100.53
Domains=~corp.example.com
# Tắt stub 127.0.0.53 khi chạy DNS server riêng trên port 53
#DNSStubListener=nosudo systemctl restart systemd-resolved
# Nếu tắt stub: trỏ resolv.conf sang file chứa server thật
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.confresolvectl dns / resolvectl domain chỉ là runtime, mất khi link up/down hoặc reboot. Dùng để thử, sau đó đưa vào netplan hoặc resolved.conf.d.
Kiểm tra nhanh
resolvectl status | grep -E 'Link|Current DNS|DNS Servers|DNS Domain'
getent hosts example.com; resolvectl query example.com; dig +short example.com
dig +short @198.51.100.53 example.com
resolvectl flush-caches && resolvectl statistics | grep -i 'current cache size'Lệnh DNS cơ bản khác: Linux network cheatsheet.