Cấu hình DNS-over-TLS với systemd-resolved trên Linux: Tăng bảo mật khi phân giải tên miền

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Sau 6 tháng chạy production với systemd-resolved trên Ubuntu 22.04, mình mới thật sự hiểu tại sao cái service này được tích hợp sẵn vào systemd. Ban đầu mình cũng hay bỏ qua — cứ để mặc định, DNS resolve được là thôi. Nhưng từ khi bật DNS-over-TLS, mọi thứ khác hẳn: không còn lo ISP can thiệp DNS query, tốc độ resolve nhanh hơn nhờ connection reuse và cache local, và có thêm DNSSEC validate domain thật.

Quick Start: Cấu hình trong 5 phút

Mở terminal lên, làm theo từng bước này — không cần cài thêm package nào cả:

1. Kiểm tra systemd-resolved đang chạy chưa

systemctl status systemd-resolved
# Nếu chưa chạy:
sudo systemctl enable --now systemd-resolved

2. Backup config cũ và chỉnh resolved.conf

sudo cp /etc/systemd/resolved.conf /etc/systemd/resolved.conf.bak
sudo nano /etc/systemd/resolved.conf

Thêm nội dung sau vào section [Resolve]:

[Resolve]
# DNS servers hỗ trợ DoT — format: IP#hostname để verify TLS cert
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
FallbackDNS=8.8.8.8#dns.google 8.8.4.4#dns.google

# Bật DNS-over-TLS
DNSOverTLS=yes

# Bật DNSSEC validation
DNSSEC=yes

# Cache DNS (mặc định đã bật — để rõ ràng)
Cache=yes

3. Restart và kiểm tra

sudo systemctl restart systemd-resolved

# Kiểm tra trạng thái — tìm dòng DNS-over-TLS và DNSSEC
resolvectl status

Nếu thấy DNS-over-TLS setting: yes và DNSSEC setting: yes là đã xong phần cơ bản.

4. Đảm bảo /etc/resolv.conf trỏ đúng vào stub resolver

# Kiểm tra resolv.conf hiện tại
cat /etc/resolv.conf

# Phải có dòng: nameserver 127.0.0.53
# Nếu không có, tạo symlink:
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Test nhanh:

resolvectl query itfromzero.com
# Hoặc:
dig @127.0.0.53 itfromzero.com

Hiểu rõ hơn: Tại sao DNS thường lại là vấn đề bảo mật?

DNS truyền thống gửi query qua UDP port 53, plaintext hoàn toàn. Nghĩa là bất kỳ ai nằm giữa máy bạn và DNS server đều đọc được bạn đang lookup domain gì — ISP, router công cộng ở café, hay bất kỳ thiết bị nào trong path mạng.

DNS-over-TLS (DoT) wrap toàn bộ DNS query trong TLS connection, tương tự HTTPS wrap HTTP vậy. Query gửi qua TCP port 853, mã hóa end-to-end. ISP chỉ thấy bạn đang kết nối tới 1.1.1.1:853, không thấy nội dung query.

Tại sao chọn systemd-resolved thay vì cài stubby hay dnscrypt-proxy? Vì nó có sẵn trên mọi distro dùng systemd (Ubuntu, Fedora, Debian, Arch…), không cần cài thêm package, tích hợp tốt với NetworkManager, và handle caching sẵn luôn.

Ý nghĩa của format DNS#hostname

Cú pháp IP#hostname dùng để xác thực TLS certificate của DNS server:

# Cloudflare DoT
DNS=1.1.1.1#cloudflare-dns.com

# Google DoT
DNS=8.8.8.8#dns.google

# Quad9 (có chặn thêm malware domain)
DNS=9.9.9.9#dns.quad9.net

Phần #hostname là SNI (Server Name Indication) — resolved dùng hostname này để verify TLS cert của server. Không có phần này thì DoT vẫn mã hóa nhưng không verify certificate, kém an toàn hơn một bậc.

Nâng cao: DNSSEC, Fallback thông minh và Per-link DNS

DNSSEC — Xác thực DNS response không bị giả mạo

DNSSEC giải quyết vấn đề khác với DoT: đảm bảo response DNS không bị inject giả (DNS spoofing/cache poisoning). Với DNSSEC bật, resolved verify chữ ký điện tử của DNS record — nếu ai cố inject record giả, query sẽ fail thay vì trả về địa chỉ sai.

# Kiểm tra DNSSEC đang hoạt động
resolvectl query --type=DNSKEY google.com

# Test một domain cụ thể có DNSSEC không
resolvectl query --type=DS cloudflare.com

Lưu ý: Nếu bạn dùng VPN có DNS riêng, DNSSEC=yes đôi khi gây xung đột. Khi đó đặt DNSSEC=allow-downgrade — validate nếu server hỗ trợ, tự động bỏ qua nếu không.

Cấu hình Fallback DNS đúng cách

Trên server production Ubuntu 22.04 với 4GB RAM mình đang quản lý, mình nhận thấy việc này giúp giảm đáng kể thời gian xử lý — đặc biệt khi DNS chính có spike latency. Mình dùng Quad9 làm fallback vì nó tự chặn malware domain, thêm một layer bảo vệ miễn phí:

[Resolve]
# Primary: Cloudflare DoT
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com

# Fallback: Quad9 DoT — chặn thêm malware domain
FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net

DNSOverTLS=yes
DNSSEC=yes
Cache=yes
DNSStubListener=yes
ReadEtcHosts=yes

Per-link DNS — Mỗi interface dùng DNS riêng

Nếu máy có nhiều interface (VPN, LAN, WiFi) và muốn mỗi interface route DNS khác nhau:

# Xem DNS đang được gán cho từng interface
resolvectl

# Gán DNS riêng cho interface eth0 (tạm thời, mất sau reboot)
sudo resolvectl dns eth0 1.1.1.1

# Gán search domain — prefix ~ nghĩa là routing domain
# Query *.company.internal sẽ đi qua interface này
sudo resolvectl domain eth0 ~company.internal

Ký hiệu ~ trước domain là routing domain: query domain company.internal route qua interface này, các domain khác vẫn dùng DNS global. Rất hữu ích khi connect VPN corporate mà vẫn muốn internet traffic qua DNS nhanh.

Tips thực tế: Debug và Monitor

Khi DNS không resolve được — checklist

# Xem log realtime
journalctl -u systemd-resolved -f

# Flush cache khi nghi ngờ cache stale
sudo resolvectl flush-caches

# Xem thống kê cache — cache hit rate tốt là trên 40%
resolvectl statistics

# Query với verbose output để debug
resolvectl query --legend=yes itfromzero.com

Verify DoT thực sự đang encrypt traffic

# Xem connection TCP:853 đang active
ss -tnp | grep :853

# Capture để confirm traffic đi qua port 853
# (không thấy nội dung vì đã mã hóa — đó là dấu hiệu tốt)
sudo tcpdump -i any port 853 -n -c 20

Xử lý xung đột với /etc/resolv.conf

Đây là vấn đề hay gặp nhất. NetworkManager hoặc DHCP client đôi khi ghi đè /etc/resolv.conf, làm DNS bypass resolved luôn.

# Kiểm tra resolv.conf là symlink hay file thật
ls -la /etc/resolv.conf

# Nếu là file thật — backup rồi tạo symlink đúng:
sudo mv /etc/resolv.conf /etc/resolv.conf.bak
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

# Nếu dùng NetworkManager — bảo nó không ghi đè:
sudo mkdir -p /etc/NetworkManager/conf.d
sudo tee /etc/NetworkManager/conf.d/dns.conf <<EOF
[main]
dns=systemd-resolved
EOF
sudo systemctl restart NetworkManager

Sau khi apply config đầy đủ, mình dùng resolvectl statistics để monitor định kỳ. Cache hit rate thường trên 60% với máy dev — hơn nửa số DNS query không cần ra internet, resolve ngay từ local. Với server production ít domain đa dạng hơn thì con số này còn cao hơn nữa.

Share: