DHCP客户端在获取网络配置时,默认会接受服务器下发的所有选项,包括DNS服务器、域名搜索列表、NTP服务器等。这种默认信任机制存在明确的安全风险:恶意DHCP服务器或中间人攻击者可以推送恶意DNS服务器,将你的流量导向钓鱼网站;可以注入恶意搜索域名,让你的主机在不经意间泄露内部主机名;甚至可以下发恶意路由选项,篡改你的网络流量路径。在Debian系统中,我们可以通过配置dhclient来精确控制接受哪些DHCP选项、拒绝哪些选项,从而消除这些安全隐患。

理解DHCP选项的安全风险

DHCP协议定义了大量标准选项,每个选项编号对应不同的配置参数。选项6是DNS服务器,选项15是域名,选项119是域名搜索列表,选项42是NTP服务器,选项121是无类静态路由。攻击者最常利用的正是这些选项。假设你在咖啡店连接公共WiFi,网络中存在一个伪造的DHCP服务器,它抢先响应你的DHCP请求,下发选项6为攻击者控制的DNS服务器。此后你访问的所有域名解析都将经过这个恶意DNS,攻击者可以轻松实施中间人攻击。更隐蔽的攻击是利用选项119域名搜索列表,当你ping一个短主机名时,系统会自动拼接搜索域名,可能将你导向内网之外的恶意主机。选项121路由注入则更为危险,攻击者可以下发特定路由条目,让你的特定目标流量经过攻击者控制的网关。

Debian中dhclient的配置文件位置

在Debian系统中,dhclient是默认的DHCP客户端,配置文件位于/etc/dhcp/dhclient.conf。如果你使用的是NetworkManager管理网络,它底层仍然调用dhclient,配置文件路径相同。对于systemd-networkd用户,DHCP客户端行为由systemd-networkd的配置控制,本文主要讨论dhclient的配置方法,因为这是Debian最传统的网络管理方式。编辑配置文件需要root权限,使用sudo或直接切换到root用户操作。

dhclient配置语法基础

dhclient.conf使用类似脚本的语法,核心指令包括request、require、supersede、prepend、append和reject。request指令声明客户端主动请求的选项列表。require指令声明必须从服务器获取的选项,如果服务器不提供这些选项,客户端将拒绝该租约。supersede指令强制覆盖服务器下发的选项值。prepend和append分别在服务器下发值的前面或后面添加自定义值。reject指令则用于明确拒绝某些选项,即使服务器下发了这些选项,客户端也会直接忽略。理解这些指令的区别至关重要:reject是彻底忽略,supersede是接受但覆盖,request是主动索取但不强制。

具体配置:拒绝不安全的DHCP选项

打开配置文件/etc/dhcp/dhclient.conf,找到或添加reject指令。以下是一个安全加固的配置示例,拒绝常见的高风险选项:

# 拒绝域名搜索列表,防止DNS搜索域注入
reject rfc3442-classless-static-routes;
reject domain-name-servers;
reject domain-name;
reject domain-search;
reject netbios-name-servers;
reject netbios-node-type;
reject ntp-servers;
reject rfc3442-classless-static-routes;
reject ms-classless-static-routes;
reject static-routes;
reject routers;

上述配置中,我们拒绝了域名服务器(选项6)、域名(选项15)、域名搜索列表(选项119)、NetBIOS相关选项、NTP服务器(选项42)、无类静态路由(选项121)以及经典静态路由(选项33)和默认网关(选项3)。拒绝这些选项后,你需要通过其他方式手动配置这些参数。例如DNS服务器可以手动写入/etc/resolv.conf,路由可以通过ip route命令添加。这种做法的前提是你对网络环境有完全的控制权,或者你只连接可信任的网络。

更精细的控制方案:supersede替代reject

完全拒绝某些选项可能导致网络不可用,特别是在你需要DHCP获取基本网络参数时。更实用的做法是使用supersede指令,强制使用你信任的值覆盖服务器下发的值。以下配置示例展示了如何强制指定DNS服务器和域名搜索列表:

# 强制使用指定的DNS服务器,忽略服务器下发的值
supersede domain-name-servers 1.1.1.1, 9.9.9.9;

# 强制使用指定的域名搜索列表
supersede domain-search "internal.example.com";

# 拒绝NetBIOS相关选项,Windows网络遗留问题
reject netbios-name-servers;
reject netbios-node-type;

# 拒绝NTP服务器,使用自己配置的NTP
reject ntp-servers;

supersede指令的优先级高于服务器下发的值,这样即使恶意DHCP服务器推送了恶意DNS,你的系统也会使用你预设的1.1.1.1和9.9.9.9。这种方案在安全性和可用性之间取得了平衡,推荐大多数用户采用。你需要将DNS服务器地址替换为你信任的DNS服务,例如你的企业内网DNS或公共可信DNS。

处理无类静态路由选项的风险

选项121无类静态路由是攻击者进行流量劫持的利器。这个选项允许DHCP服务器向客户端推送特定目的网络的路由条目。攻击者可以推送一条目的为你的银行网站IP地址的路由,下一跳指向攻击者的主机,从而实现精准的流量劫持。在dhclient.conf中,你可以直接拒绝这个选项:

reject rfc3442-classless-static-routes;

如果你确实需要从DHCP获取路由信息,建议只在你完全信任的网络环境中启用,或者使用require指令配合白名单机制,只接受特定子网的租约。但更安全的做法是手动配置静态路由,完全杜绝DHCP路由注入的风险。

使用request指令实现选项白名单

更严格的安全策略是使用request指令明确列出你需要的选项,形成白名单机制。任何不在白名单中的选项都会被忽略。以下配置示例展示了只请求最基本的网络参数:

# 只请求IP地址、子网掩码、默认网关和租约时间
request subnet-mask, broadcast-address, routers, dhcp-lease-time, dhcp-message-type, dhcp-server-identifier;

# 强制覆盖DNS服务器
supersede domain-name-servers 1.1.1.1, 9.9.9.9;

# 拒绝其他所有未明确请求的选项
reject domain-name, domain-search, ntp-servers, netbios-name-servers, netbios-node-type, rfc3442-classless-static-routes;

这种白名单方式从根源上减少了攻击面,只接受IP地址、子网掩码、默认网关和租约时间这些必要的网络参数。DNS等容易受攻击的选项全部通过supersede强制覆盖。需要注意的是,request指令会覆盖dhclient的默认请求列表,所以你必须明确列出所有需要的选项,包括dhcp-message-type和dhcp-server-identifier这些协议必需的选项,否则DHCP交互可能失败。

验证配置是否生效

配置完成后,你需要验证设置是否真正生效。首先重启网络服务或重新获取DHCP租约:

sudo dhclient -r eth0
sudo dhclient eth0

然后检查/etc/resolv.conf文件,确认DNS服务器是否为你supersede指定的地址:

cat /etc/resolv.conf

如果看到nameserver 1.1.1.1和nameserver 9.9.9.9,说明supersede生效。接下来检查路由表,确认没有异常的静态路由注入:

ip route show

正常情况下,你应该只看到直连路由和默认路由,没有来路不明的特定目的网络路由。你还可以使用dhclient的调试模式查看详细的交互过程:

sudo dhclient -d eth0

调试模式会在前台运行并输出所有DHCP交互细节,你可以看到服务器下发了哪些选项,客户端接受了哪些、拒绝了哪些。这是排查配置问题最有效的手段。

结合iptables进行纵深防御

仅靠dhclient配置还不够,因为恶意DHCP服务器可能在你配置生效之前就已经造成影响,或者存在绕过dhclient的攻击手段。建议结合iptables规则限制DHCP通信,只允许来自可信MAC地址的DHCP响应。以下iptables规则示例限制只接受特定MAC地址的DHCP服务器响应:

# 允许来自可信DHCP服务器MAC地址的DHCP响应
sudo iptables -A INPUT -p udp --sport 67 --dport 68 -m mac --mac-source aa:bb:cc:dd:ee:ff -j ACCEPT
sudo iptables -A INPUT -p udp --sport 67 --dport 68 -j DROP

将aa:bb:cc:dd:ee:ff替换为你网络中合法DHCP服务器的MAC地址。这条规则确保只有指定MAC地址的DHCP服务器响应能被接受,其他所有DHCP响应包都会被丢弃。这种网络层的防御与dhclient应用层配置形成纵深防御体系,大幅提升安全性。

针对IPv6的DHCPv6安全配置

Debian系统同样支持DHCPv6,其配置文件通常位于/etc/dhcp/dhclient6.conf或/etc/dhcp/dhclient.conf中通过dhcp6前缀的指令控制。DHCPv6面临类似的安全风险,攻击者可以推送恶意的DNS服务器和域名搜索列表。配置方法与IPv4类似:

# DHCPv6安全配置
supersede dhcp6.name-servers 2606:4700:4700::1111, 2606:4700:4700::1001;
supersede dhcp6.domain-search "internal.example.com";
reject dhcp6.ntp-servers;

如果你不需要DHCPv6,最安全的做法是在sysctl中直接禁用IPv6的自动配置功能,或者在NetworkManager中禁用IPv6。减少攻击面永远是安全配置的首要原则。

监控与审计

安全配置不是一劳永逸的,你需要持续监控DHCP相关的异常行为。可以配置logwatch或自定义脚本定期检查/var/log/syslog中dhclient的日志,关注以下异常模式:DHCP服务器MAC地址变化、下发的DNS服务器地址变化、异常的静态路由推送。以下是一个简单的监控脚本示例:

#!/bin/bash
# 监控DHCP服务器MAC地址变化
CURRENT_DHCP_SERVER=$(grep "DHCPACK" /var/log/syslog | tail -1 | grep -oP 'from \K[0-9a-f:]+')
if [ "$CURRENT_DHCP_SERVER" != "aa:bb:cc:dd:ee:ff" ]; then
    echo "警告:DHCP服务器MAC地址变化!当前服务器:$CURRENT_DHCP_SERVER" | mail -s "DHCP安全告警" admin@example.com
fi

将此脚本加入crontab定时执行,可以及时发现DHCP欺骗攻击。对于企业环境,建议部署网络入侵检测系统如Suricata,配置DHCP相关的检测规则,从网络层面感知DHCP攻击行为。

DHCP客户端的安全配置是主机安全基线的重要组成部分。通过在dhclient.conf中使用reject拒绝高风险选项、使用supersede强制覆盖关键参数、使用request实施白名单策略,配合iptables网络层过滤和持续的监控审计,你可以有效防御DHCP层面的各类攻击。安全配置需要根据你的实际网络环境调整,在安全性和可用性之间找到最佳平衡点。对于移动办公频繁连接不可信网络的设备,建议采用最严格的白名单策略;对于固定办公连接企业内网的设备,可以采用supersede覆盖关键选项的折中方案。无论选择哪种策略,核心原则始终是:不要盲目信任DHCP服务器下发的任何配置。