首页 / 帮助文档 / Ubuntu运维systemd-resolved防DNS劫持

Ubuntu运维systemd-resolved防DNS劫持

DNS劫持是Ubuntu服务器运维中一个隐蔽却危险的安全威胁,它通过篡改DNS解析结果,将你的访问重定向到恶意网站,可能导致数据泄露、中间人攻击或服务中断。在Ubuntu 18.04及更高版本中,守护进程systemd-resolved已成为默认的DNS解析器,正确配置它是防御此类攻击的第一道坚实防线。本文将直接深入,展示如何通过配置systemd-resolved来锁定DNS,使用加密的DNS-over-TLS(DoT)协议,并验证其工作状态,从而构建一个抗干扰的本地DNS解析环境。

理解systemd-resolved的核心角色与现状

systemd-resolved并非一个简单的DNS客户端,它是一个集缓存、链路本地多播名称解析(LLMNR)和DNS服务发现于一体的系统服务。其核心配置文件是/etc/systemd/resolved.conf。默认情况下,它从网络管理器(如NetworkManager或systemd-networkd)获取上游DNS服务器地址,通常是你的路由器或ISP提供的DNS。问题在于,这些明文传输的DNS查询极易在公共网络中被窥探和篡改。我们的目标是将systemd-resolved配置为直接使用可信的、支持DNS-over-TLS的公共DNS解析器,如Cloudflare(1.1.1.1)或Quad9(9.9.9.9),并对整个解析过程进行加密。

步骤一:配置systemd-resolved以启用DNS-over-TLS

首先,你需要编辑主配置文件。使用你熟悉的文本编辑器,如nano或vim,以sudo权限打开/etc/systemd/resolved.conf

sudo nano /etc/systemd/resolved.conf

找到[Resolve]部分,你需要设置以下几个关键参数。一个完整的、启用DoT的配置示例如下:

[Resolve]
# 指定使用加密DNS的服务器,这里以Cloudflare和Quad9为例
DNS=1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net
# 启用所有接口的DNS-over-TLS功能
DNSOverTLS=yes
# 设置DNS的默认搜索域(通常无需修改,保留为空即可)
Domains=~.
# 禁用LLMNR,它是一种本地网络名称解析协议,在某些环境中可能带来安全风险
LLMNR=no
# 禁用多播DNS(mDNS)
MulticastDNS=no
# 不依赖网络管理器推送的DNS设置,确保配置的稳定性
DNSSEC=allow-downgrade
# 设置DNS缓存模式
Cache=yes

解释一下关键行:DNS=1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net 这行指定了两个上游DNS服务器,并明确其用于TLS验证的域名。格式为IP地址#TLS域名DNSOverTLS=yes 强制对所有DNS查询尝试使用TLS加密。如果设置为opportunistic,则仅在服务器支持时加密,安全性稍弱。

步骤二:应用配置并重启服务

保存并关闭文件后,你需要重启systemd-resolved服务以使更改生效。同时,确保系统的解析配置指向本地systemd-resolved的存根解析器(监听在127.0.0.53)。

sudo systemctl restart systemd-resolved.service
sudo systemctl enable --now systemd-resolved.service

接着,检查系统的/etc/resolv.conf文件。它应该是一个指向systemd-resolved的符号链接。

ls -lh /etc/resolv.conf
# 应该显示类似:/etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

如果不是,你可以手动创建这个链接:

sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

步骤三:验证DNS-over-TLS是否生效

配置完成后,必须进行验证。使用systemd-resolve命令可以查看当前DNS服务的状态。

systemd-resolve --status

在输出中,找到你的主网络接口(如eth0或wlp2s0),应该能看到类似以下的配置,表明已使用指定的DNS服务器并启用了TLS:

Current DNS Server: 1.1.1.1
DNS Servers: 1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net
DNS Domain: ~.
DNSSEC setting: allow-downgrade
DNSSEC supported: yes
DNSOverTLS: yes

更直接的测试是使用digkdig(来自ldnsutils包)工具查询一个域名,并观察其使用的服务器和端口。安装kdig后执行:

sudo apt install ldnsutils
kdig example.com @127.0.0.53

虽然此命令显示查询发往本地存根解析器,但为了验证与上游服务器的连接是否加密,你可以使用tcpdumptshark抓包。在另一个终端执行抓包命令(监听你的出站网卡,如eth0),然后再次进行DNS查询:

sudo tcpdump -i eth0 port 853 -nv

如果看到发往1.1.1.1或9.9.9.9端口853(DoT标准端口)的TCP流量,而不是端口53的UDP流量,就证明DNS查询已被成功加密传输。这是防御DNS劫持最直接的证据。

高级加固与故障排查

除了基础配置,你还可以考虑以下高级加固措施:首先,启用严格的DNSSEC验证。将resolved.conf中的DNSSEC=allow-downgrade改为DNSSEC=yes,这将强制进行DNSSEC验证,如果签名无效则拒绝解析结果,进一步防止DNS欺骗。

其次,配置备用解析策略。对于关键服务,可以考虑设置一个备用、物理隔离的DNS解析路径作为冗余。这可以通过在/etc/systemd/network/目录下为特定网络接口创建独立的.network文件来实现。

当遇到解析问题时,一个强大的排查命令是resolvectl queryresolvectl statistics。前者可以显示一个域名完整的解析链条和缓存情况,后者则展示缓存命中率、失败次数等统计信息,对于性能调优和问题诊断极有帮助。

resolvectl query baidu.com
resolvectl statistics

理解局限性:系统级配置与应用程序行为

必须清醒认识到,配置systemd-resolved是系统级的防护。它无法保护那些自行实现DNS解析、硬编码DNS服务器或使用特殊网络命名空间的应用程序。例如,某些容器化应用(如Docker容器)、虚拟机或特定的网络诊断工具(如nslookup的某些使用方式)可能会绕过systemd-resolved。对于容器,应在容器内部或编排层面配置安全的DNS;对于虚拟机,则需在客户机系统中进行类似配置。

此外,DNS-over-TLS加密的是你本地主机到上游DNS服务器之间的“最后一公里”,但无法保证上游服务器本身或其后续递归查询链路的绝对安全。因此,选择信誉良好的公共DNS服务商至关重要。Cloudflare和Quad9都承诺严格的隐私政策和不记录查询日志,Quad9还额外提供恶意域名拦截功能。

构建纵深防御体系

将systemd-resolved配置为使用DoT,是构建服务器安全纵深防御体系中网络层的关键一环。但这不应是唯一措施。一个完整的防御策略还应包括:定期更新系统和软件包以修补漏洞;使用防火墙(如UFW)严格限制入站和出站连接;配置并使用入侵检测系统(如Fail2ban)监控异常登录尝试;对关键服务强制使用HTTPS/SSL加密。DNS安全是基础,它与其他安全措施协同工作,共同构成一个难以被攻破的整体。

最后,养成定期检查DNS解析状态的习惯。通过自动化脚本或监控工具,定期验证解析结果的正确性和TLS连接的状态。在Ubuntu的运维世界里,主动的安全配置远胜于被动的故障响应。通过本文详述的步骤,你已经能够有效地利用systemd-resolved加固你的服务器,使其在面对日益普遍的DNS劫持攻击时,具备强大的抵御能力。