首页 / 帮助文档 / Ubuntu运维中的systemd-resolved缓存投毒防护

Ubuntu运维中的systemd-resolved缓存投毒防护

在Ubuntu运维中,systemd-resolved服务的缓存投毒攻击是一个真实且棘手的威胁,攻击者通过伪造DNS响应来污染本地缓存,将你的域名解析导向恶意服务器。要防护它,你需要立即检查并配置systemd-resolved的DNSSEC验证和DNS-over-TLS,同时限制可接受的DNS服务器。下面我将详细拆解每一步操作。

理解systemd-resolved与缓存投毒的原理

systemd-resolved是Ubuntu 18.04及更高版本默认的DNS解析器,它集成了缓存功能以提升查询速度。然而,传统的DNS查询(端口53上的UDP协议)是明文的且易于被欺骗。攻击者可以在你的服务器发起DNS查询后,抢在合法响应到达之前,向你的系统发送大量伪造的DNS响应包。如果伪造包的ID、端口号和查询内容与你的请求匹配,systemd-resolved就可能将其误认为合法响应并存入缓存。此后,所有指向该域名的请求都会被重定向到攻击者指定的IP地址,导致钓鱼、中间人攻击或恶意软件分发。

首要防护:强制启用并验证DNSSEC

DNSSEC(域名系统安全扩展)通过数字签名确保DNS响应的真实性和完整性,是防御缓存投毒的基石。在Ubuntu中,你需要确认并强制systemd-resolved使用DNSSEC验证。

首先,检查当前DNSSEC状态:

systemd-resolve --status | grep -A5 "DNSSEC"

关键配置位于/etc/systemd/resolved.conf。使用文本编辑器(如nano)打开它:

sudo nano /etc/systemd/resolved.conf

找到或添加以下行,确保配置如下:

[Resolve]
DNSSEC=yes
DNSOverTLS=opportunistic
FallbackDNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google

DNSSEC设置为yes会强制要求所有DNS查询必须通过DNSSEC验证;如果上游DNS服务器不支持DNSSEC,解析将失败。若你希望在不支持DNSSEC时仍能降级解析,可将其设为allow-downgrade,但这会降低安全性。DNSOverTLS=opportunistic会在DNS服务器支持时自动启用TLS加密,防止查询被窃听或篡改。FallbackDNS设置了备用DNS,建议选择支持DNSSEC和DoT的公共DNS,如Cloudflare(1.1.1.1)或Google DNS(8.8.8.8)。

加固网络接口的DNS服务器配置

即使配置了DNSSEC,如果系统连接的DNS服务器本身不可信,风险依然存在。你需要确保NetworkManager或netplan只指向可信的、支持DNSSEC的DNS服务器。

对于使用Netplan的系统(如Ubuntu 20.04+),编辑YAML配置文件(通常在/etc/netplan/目录下):

sudo nano /etc/netplan/01-netcfg.yaml

在每个网络接口的配置部分,明确指定DNS服务器:

network:
  version: 2
  ethernets:
    eth0:
      addresses: [192.168.1.10/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1, 8.8.8.8]
        search: [yourdomain.local]

保存后应用更改:sudo netplan apply。这确保了系统在启动时只向这些指定的、安全的DNS服务器发送查询,而不是依赖可能被攻击者篡改的DHCP提供的DNS。

禁用或限制LLMNR和mDNS以减少攻击面

除了标准的DNS查询,systemd-resolved还支持LLMNR(链路本地多播名称解析)和mDNS(多播DNS),这些协议在局域网内用于主机发现,但同样容易遭受投毒攻击。在安全的服务器环境中,通常建议禁用它们。

/etc/systemd/resolved.conf中继续添加:

[Resolve]
LLMNR=no
MulticastDNS=no

将两者设置为no可以完全关闭这些协议,迫使所有解析都通过你配置的、受DNSSEC保护的上游DNS通道进行,消除了局域网内针对这些协议的欺骗攻击可能性。

监控与验证:检查解析的安全状态

配置完成后,你必须验证防护是否生效。重启systemd-resolved服务:

sudo systemctl restart systemd-resolved

然后,使用systemd-resolve工具进行诊断。查询一个已知支持DNSSEC的域名(如isc.org),并查看安全标志:

systemd-resolve --validate=yes isc.org

如果输出中显示“fully validated”或类似信息,表明DNSSEC验证成功。你也可以使用dig命令检查:

dig @127.0.0.1 isc.org | grep -E "flags|ad"

在返回的头部中,如果看到ad标志(Authenticated Data),则证明响应已经过DNSSEC验证。此外,定期检查系统日志可以捕获潜在的安全事件:

sudo journalctl -u systemd-resolved --since today | grep -i "security\|failure\|invalid"

高级策略:使用DNS-over-TLS(DoT)进行全程加密

仅靠DNSSEC验证响应内容,但查询过程仍可能被监听。DNS-over-TLS(DoT)在应用程序(systemd-resolved)和DNS服务器之间建立一个加密的TLS隧道,彻底防止了查询在传输过程中被窃听或投毒。

resolved.conf中,我们已经设置了DNSOverTLS=opportunistic。这意味着只要上游DNS服务器(如1.1.1.1或8.8.8.8)支持DoT,连接就会自动加密。为了获得最高安全性,你可以将其设置为yes,这将强制要求加密,如果服务器不支持DoT则解析失败。但请确保你的备用DNS也支持DoT。

要验证DoT是否正在工作,可以监听网络流量。安装tcpdump后,运行:

sudo tcpdump -i any port 853 -n

端口853是DoT的标准端口。当你发起DNS查询时,如果看到流向1.1.1.1或8.8.8.8等服务器853端口的流量,就说明DoT已启用。查询内容将被加密,攻击者无法在中间篡改。

应对复杂环境:防火墙规则与沙盒限制

在严格受控的服务器环境中,你可以通过防火墙进一步限制DNS流量,只允许系统向指定的、可信的DNS服务器(如1.1.1.1和8.8.8.8)发起出站查询,并拒绝所有其他地址的DNS请求。使用UFW(Uncomplicated Firewall)可以轻松实现:

sudo ufw allow out to 1.1.1.1 port 53,853 proto tcp
sudo ufw allow out to 8.8.8.8 port 53,853 proto tcp
sudo ufw deny out 53/udp
sudo ufw deny out 53/tcp

这些规则允许向指定IP的53(DNS)和853(DoT)端口发起TCP连接(systemd-resolved在DoT和回退时使用TCP),同时默认拒绝所有其他出站DNS流量。注意,这可能会影响依赖于特定内部DNS服务器的企业网络,请根据实际情况调整。

此外,systemd-resolved本身在systemd沙盒中运行,这提供了一定程度的隔离。你可以通过systemctl cat systemd-resolved查看其单元文件,通常不建议修改这些安全限制,但了解其存在有助于整体安全评估。

总结:构建纵深防御体系

防护systemd-resolved缓存投毒没有单一的银弹,而是一个纵深防御的配置组合。核心是强制DNSSEC验证以确保数据真实性,辅以DNS-over-TLS加密以保护传输过程。在此基础上,通过严格配置可信的上游DNS服务器禁用不必要的解析协议(LLMNR/mDNS)以及使用防火墙限制出站流量,你可以将攻击面降至最低。定期使用systemd-resolvedig工具验证DNSSEC和DoT状态,并监控系统日志,是确保这些防护措施持续有效的关键。在Ubuntu服务器运维中,将这些配置作为标准基线,能显著提升你整个基础设施的DNS安全韧性。