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
更直接的测试是使用dig或kdig(来自ldnsutils包)工具查询一个域名,并观察其使用的服务器和端口。安装kdig后执行:
sudo apt install ldnsutils kdig example.com @127.0.0.53
虽然此命令显示查询发往本地存根解析器,但为了验证与上游服务器的连接是否加密,你可以使用tcpdump或tshark抓包。在另一个终端执行抓包命令(监听你的出站网卡,如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 query和resolvectl 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劫持攻击时,具备强大的抵御能力。
