Bối cảnh & Lý do: Vượt qua giới hạn của resolv.conf tĩnh
Trong nhiều thập kỷ, Linux phụ thuộc vào tệp văn bản thuần tại /etc/resolv.conf, được điền bởi các DHCP lease hoặc nameserver cố định. Mô hình đơn giản đó dần bộc lộ nhiều điểm yếu trong hạ tầng hiện đại. Các cấu hình tĩnh không thể cache kết quả truy vấn ngay tại máy cục bộ. Chúng không nhận diện được định tuyến split-horizon qua các VPN tunnel, đồng thời gửi mọi truy vấn qua mạng không tin cậy dưới dạng UDP văn bản rõ (cleartext).
systemd-resolved giải quyết triệt để những nút thắt này. Dịch vụ này chạy như một stub resolver cục bộ lắng nghe tại 127.0.0.53:53. Nhờ lưu cache các bản ghi trong RAM, nó giảm độ trễ của các truy vấn lặp lại xuống gần như bằng 0. Nó còn xử lý xác thực DNSSEC, điều hướng truy vấn đến các tunnel riêng theo từng network interface (như WireGuard hay OpenVPN), và mã hóa toàn bộ lưu lượng gửi lên upstream qua TLS trên cổng 853.
Các thay đổi về DNS có thể dễ dàng làm cô lập một máy chủ. Trong một lần triển khai thử nghiệm trên 12 node production, một thay đổi DoT chưa được kiểm thử kỹ đã bóp nghẹt các truy vấn API ra ngoài và làm tê liệt các agent thu thập metrics chỉ trong vài phút. Hãy luôn kiểm tra kỹ các thay đổi resolver trên một máy canary trước khi áp dụng trên quy mô toàn hệ thống.
Cài đặt: Đảm bảo systemd-resolved hoạt động trơn tru
Các bản phân phối như Ubuntu (18.04+) và Debian 12 đã tích hợp sẵn systemd-resolved. Tuy nhiên, các bản cloud image tối giản, LXC container hoặc base image bị lược bỏ có thể chưa có sẵn. Hãy cài đặt gói nếu hệ thống của bạn thiếu binary:
# Hệ thống Debian/Ubuntu
sudo apt-get update
sudo apt-get install systemd-resolved -y
# RHEL/Fedora/Rocky Linux
sudo dnf install systemd-resolved -y
Khởi động daemon và cấu hình để dịch vụ tự động chạy cùng hệ thống:
sudo systemctl enable --now systemd-resolved.service
Các hàm tra cứu tiêu chuẩn trong thư viện C (glibc getaddrinfo) vẫn đọc /etc/resolv.conf. Hãy trỏ đường dẫn này trực tiếp tới tệp stub động của systemd thông qua một symlink:
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Kiểm tra lại xem liên kết đã trỏ đúng tới stub resolver hay chưa:
cat /etc/resolv.conf
Nội dung tệp sẽ hiển thị nameserver 127.0.0.53 và options edns0 trust-ad.
Cấu hình: DNS Caching, DoT và cơ chế dự phòng (Fallbacks)
Các thông số mặc định của daemon nằm ở /etc/systemd/resolved.conf. Đừng bao giờ chỉnh sửa trực tiếp tệp này vì các bản cập nhật gói sẽ ghi đè lên các thay đổi của bạn. Thay vào đó, hãy đặt các tệp ghi đè theo dạng module bên trong /etc/systemd/resolved.conf.d/.
1. Thiết lập bộ nhớ đệm DNS trong RAM (In-Memory DNS Caching)
Lưu cache cục bộ giúp tiết kiệm các lượt truyền dữ liệu khứ hồi (round-trip) qua mạng công cộng. Cắt giảm 40ms cho mỗi lệnh gọi microservice API sẽ giảm đáng kể tổng thời gian xử lý yêu cầu tích lũy. Hãy tạo một drop-in file riêng:
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo tee /etc/systemd/resolved.conf.d/01-cache.conf << 'EOF'
[Resolve]
DNSCache=yes
CacheFromLocalhost=no
EOF
DNSCache=yes hướng dẫn resolver lưu cả kết quả truy vấn thành công lẫn thất bại (positive và negative lookups) vào RAM dựa trên giới hạn TTL từ máy chủ có thẩm quyền. Thiết lập CacheFromLocalhost=no nhằm tránh việc lưu cache hai lần nếu bạn đang chạy các proxy trung gian như dnsmasq hay unbound trên cùng một máy.
2. Bắt buộc sử dụng DNS-over-TLS (DoT)
DNS tiêu chuẩn truyền tải tên miền qua mạng công cộng dưới dạng văn bản rõ, khiến bất kỳ router trung gian hay ISP nào cũng có thể đọc được. DNS-over-TLS bảo vệ các truy vấn bằng TLS qua cổng TCP 853. Hãy khai báo các upstream resolver cùng với hostname SNI (Server Name Indication) tương ứng:
sudo tee /etc/systemd/resolved.conf.d/02-dot.conf << 'EOF'
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com
FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net
DNSOverTLS=yes
DNSSEC=allow-downgrade
EOF
Có ba chỉ thị quan trọng giúp cấu hình này vận hành ổn định:
#cloudflare-dns.com: Cung cấp hostname SNI. Resolver sẽ dùng giá trị này để đối chiếu và xác thực chứng chỉ TLS của máy chủ upstream.DNSOverTLS=yes: Bắt buộc dùng TLS. Nếu firewall chặn cổng 853, truy vấn sẽ báo lỗi ngay lập tức thay vì tự động quay về dạng văn bản rõ không mã hóa. Hãy đổi thànhopportunisticnếu bạn muốn tạm thời quay về kết nối không mã hóa khi mạng gặp sự cố chập chờn.DNSSEC=allow-downgrade: Xác thực chữ ký DNSSEC khi tên miền hỗ trợ, nhưng không từ chối các yêu cầu tra cứu đối với những tên miền chưa ký DNSSEC.
Áp dụng các thiết lập mới:
sudo systemctl restart systemd-resolved
Kiểm tra & Giám sát: Kiểm tra Cache & Xử lý sự cố
Đừng bao giờ mặc định cấu hình DNS mới đã hoạt động chỉ vì service khởi động lại không báo lỗi. Hãy luôn xác minh trạng thái hoạt động thực tế và luồng gói tin đang chạy.
Kiểm tra trạng thái và các Upstream đang hoạt động
Chạy resolvectl status để xem thông tin cấu hình link và các nameserver đang hoạt động:
resolvectl status
Quan sát khối Global. Đảm bảo DNSOverTLS: yes đang bật và các upstream bạn vừa cấu hình đã xuất hiện trong danh sách.
Kiểm tra độ trễ và Cache Hit
Đo lường hiệu quả của cache bằng công cụ dig:
# Truy vấn lần đầu: cache miss (phải gửi qua WAN)
dig @127.0.0.53 kernel.org | grep "Query time"
# Truy vấn lần hai: cache hit (lấy trực tiếp từ RAM cục bộ)
dig @127.0.0.53 kernel.org | grep "Query time"
Yêu cầu đầu tiên thường mất khoảng 35ms đến 75ms để truy vấn nhà cung cấp upstream qua TLS. Yêu cầu thứ hai sẽ phân giải chỉ trong 0 msec hoặc 1 msec.
Xem thống kê hoạt động của Cache
Kiểm tra tình trạng cache bằng lệnh resolvectl statistics:
resolvectl statistics
Lệnh này sẽ báo cáo số bản ghi cache đang có, số transaction, số lượt trúng cache (hit count) và trượt cache (miss count). Một node khỏe mạnh thường duy trì tỷ lệ cache hit trên 70% trong các tác vụ web và background job thông thường.
Xóa các bản ghi cũ (Flush Cache)
Xóa sạch các bản ghi cục bộ sau khi cập nhật DNS hoặc di chuyển hạ tầng mà không cần khởi động lại dịch vụ:
resolvectl flush-caches
Các kịch bản gỡ lỗi chuyên sâu
Khi các truy vấn DNS thất bại, hãy lần theo dấu vết sự cố bằng các bước kiểm tra có mục tiêu sau:
1. Kiểm tra cổng 853 chiều Outbound
Chế độ DoT nghiêm ngặt yêu cầu quyền truy cập outbound TCP qua cổng 853. Các nhóm Cloud Security Group, firewall doanh nghiệp và nhà mạng ISP thường xuyên chặn cổng này. Hãy kiểm tra kết nối thô trực tiếp:
nc -zv -w3 1.1.1.1 853
Nếu quá trình bắt tay (handshake) bị timeout sau 3 giây, hãy nới lỏng các quy tắc egress của firewall. Nếu không thể mở cổng 853 ở upstream, hãy chuyển DNSOverTLS=yes về DNSOverTLS=opportunistic trong drop-in file của bạn.
2. Khắc phục tình trạng tệp resolv.conf bị ghi đè
Các DHCP client, netplan và NetworkManager thường xuyên xung đột để giành quyền kiểm soát /etc/resolv.conf. Hãy kiểm tra trạng thái inode của tệp:
ls -la /etc/resolv.conf
Nếu /etc/resolv.conf là một tệp thông thường thay vì symlink trỏ đến /run/systemd/resolve/stub-resolv.conf, các công cụ bên ngoài đã ghi đè lên nó. Hãy tạo lại symlink. Sau đó, hướng dẫn NetworkManager nhường quyền quản lý DNS cho systemd bằng cách thêm dòng dns=systemd-resolved dưới khối [main] trong /etc/NetworkManager/NetworkManager.conf.
3. Bắt gói tin truy vấn trực tiếp (Packet Sniffing)
Theo dõi log phân giải theo thời gian thực với journalctl:
journalctl -u systemd-resolved -f --no-tail
Để kiểm tra lưu lượng mạng thực tế, hãy dùng tcpdump. Hãy xác minh rằng các truy vấn rời khỏi interface đối ngoại qua cổng TCP 853 thay vì cổng UDP 53 văn bản rõ:
sudo tcpdump -ni any port 853 or port 53
Các ứng dụng nội bộ sẽ truy vấn tới 127.0.0.53:53 tại máy cục bộ. Trong khi đó, toàn bộ lưu lượng ra ngoài chỉ được phép trỏ tới IP của upstream trên cổng 853 và được bao bọc an toàn trong các phiên TLS.

