dhclient 单播 DHCPREQUEST 日志过多

mis*_*nko 5 networking linux dhcp iptables centos-7

我正在使用 centos 7 和 dhclient 4.2.5:

\n\n
$ uname -a\nLinux hostname 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux\n\n$ dhclient -V\nInternet Systems Consortium DHCP Client 4.2.5\nCopyright 2004-2013 Internet Systems Consortium.\nAll rights reserved.\n
Run Code Online (Sandbox Code Playgroud)\n\n

最近我注意到日志包含很多以下记录:

\n\n
Dec 14 10:12:32 hostname dhclient[4186]: DHCPREQUEST on enp5s0f0 to 10.23.0.4 port 67 (xid=0xe1a88f7)\nDec 14 10:12:49 hostname dhclient[4186]: DHCPREQUEST on enp5s0f0 to 10.23.0.4 port 67 (xid=0xe1a88f7)\nDec 14 10:13:09 hostname dhclient[4186]: DHCPREQUEST on enp5s0f0 to 10.23.0.4 port 67 (xid=0xe1a88f7)\nDec 14 10:13:23 hostname dhclient[4186]: DHCPREQUEST on enp5s0f0 to 10.23.0.4 port 67 (xid=0xe1a88f7)\nDec 14 10:13:41 hostname dhclient[4186]: DHCPREQUEST on enp5s0f0 to 10.23.0.4 port 67 (xid=0xe1a88f7)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这似乎是由于 DHCP 服务器忽略了单播请求。还有其他人遇到这样的问题:https ://forum.pfsense.org/index.php?topic=51701.0

\n\n

我尝试使用 iptables 将数据包目标 ip 更改为 255.255.255.255:

\n\n
sudo iptables -t nat -I OUTPUT 1 -d 10.23.0.4 -p udp --dport 67 -j DNAT --to-destination 255.255.255.255\n
Run Code Online (Sandbox Code Playgroud)\n\n

但由于某种原因,规则不匹配来自 的数据包dhclient。然而它匹配来自 nc 的数据包:echo 123 | nc -u 10.23.0.4 67

\n\n

我发现这个链接说 dhclient 以不同的方式工作,不被 iptables 处理:

\n\n
For most operations, DHCP software interfaces to the Linux IP stack at\na level below Netfilter. Hence, Netfilter (and therefore Shorewall)\ncannot be used effectively to police DHCP. The \xc3\xa2\xe2\x82\xac\xc5\x93dhcp\xc3\xa2\xe2\x82\xac? interface option\ndescribed in this article allows for Netfilter to stay out of DHCP\'s\nway for those operations that can be controlled by Netfilter and\nprevents unwanted logging of DHCP-related traffic by\nShorewall-generated Netfilter logging rules.\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以我有几个问题:

\n\n
    \n
  • dhclient 使用一些不被 iptables 处理的较低级别的 API 是否正确?
  • \n
  • 有什么方法可以减少来自 dhclient 的未应答单播请求的日志量?
  • \n
\n

Mar*_*iae 5

  • dhclient 使用一些不被 iptables 处理的较低级别的 API 是否正确?

简短版本:是的,对于某些 DHCP 服务器(isc-dhcp 和 dnsmasq 的早期版本),对于其他一些服务器(dnsmasq 的更高版本)来说不是。

更长的版本:事情的起源是raw socket. 根据维基百科,原始套接字是:

...一种互联网套接字,允许直接发送和接收互联网协议数据包,无需任何特定于协议的传输层格式。

此 ISC Wiki 页面(互联网系统联盟是最常见的 DHCP 程序的作者)指出:

DHCP 协议有一些真正正常工作的特定要求 - 特别是能够传输和接收发送到全 1 有限广播地址 (255.255.255.255) 的数据包,并且能够在没有 ARP 的情况下发送单播。尽管 dhcpd 也打开了一个 BSD/UDP 套接字(称为“后备接口”),但您无法通过 BSD/UDP 套接字来执行此操作,您将在 netstat 中看到这一点。

这很有趣,因为它解释了为什么你经常会通过谷歌搜索发现人们试图通过UDP端口67和68来控制DHCP请求iptables。当然,并不是这些端口没有开放,只是这是不是服务器和客户端之间进行通信的唯一通道。

然而,这并不能完全成功:有些人已经走到了完全关闭他们的机器的极端(iptables 丢弃所有内容!),但他们无法通过原始数据包关闭自己的 DHCP)。

另一个有趣的实验是再次iptables关闭电脑,然后使用原始套接字进行 DNS 或 TCP 连接:尽管有 iptables,这些通信尝试还是成功了。

在 Netfilter 网站上可以找到对此非常权威的评论,其中指出:

原始套接字绕过 TCP/IP 堆栈。Netfilter 挂钩以及 iptables 位于 IP 堆栈内部。

这同样适用于数据包嗅探器。

在这里他们还解释了如何规避这个问题:小心,这是一个笑话,沙夫说

这不是一个周末项目。

最后,我还想指出dnsmasq的情况有所不同:在Debian Wiki 页面中,dnsmasq 的作者 Simon Kelly 指出:

Dnsmasq 打开一个原始套接字,但它从不从该套接字读取数据:相反,它用于与尚未完全配置且无法执行 ARP 的 DHCP 客户端通信。这不是安全问题。dnsmasq 的更高版本使用不同的技术,并且不再打开原始套接字。

编辑

有什么方法可以减少来自 dhclient 的未应答单播请求的日志量?

这并不简单,因为可以从 CLI 调用用于减少 -q 输出的 CLI 选项dhclient不能从dhclient.conf调用。另外,dhclient通常不是由网络管理器直接调用,而是由可执行文件直接调用ifup:事实上,

# strings `(which ifup)` | grep dhclient
/sbin/dhclient
/sbin/dhclient3
dhclient -v -r -pf /run/dhclient.%iface%.pid -lf    /var/lib/dhcp/dhclient.%iface%.leases %iface%
dhclient3 -r -pf /run/dhclient.%iface%.pid -lf /var/lib/dhcp3/dhclient.%iface%.leases %iface%
dhclient -1 -v -pf /run/dhclient.%iface%.pid -lf /var/lib/dhcp/dhclient.%iface%.leases %iface%  [[-e IF_METRIC=%metric%]]
dhclient3 -pf /run/dhclient.%iface%.pid -lf /var/lib/dhcp3/dhclient.%iface%.leases %iface%      [[-e IF_METRIC=%metric%]]
dhclient -6 -r -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases %iface%
dhclient -1 -6 -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases %iface%
dhclient -1 -6 -S -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases %iface%
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,使用(= verbose!) 选项ifup调用,这与您希望的相反。dhclient-v

你有什么选择?

  • 下载源代码,修改上面的调用,然后为您的内核重新编译它。这应该是小菜一碟。

  • 您可以使用二进制编辑器将其转换-v-q.

  • 您可以修改脚本文件 ,/etc/init.d/networking通过将 的调用替换ifup

    ifup .... > /dev/null 2>&1
    
    Run Code Online (Sandbox Code Playgroud)

    重新启动或重新启动服务networking将完成此修改。这不太理想,因为它会将无用的警告严重的错误消息都扔进垃圾箱。

  • 最后,您可以执行以下 hack:移动/sbin/dhclient/sbin/dhclient-true,然后创建一个名为 的可执行文件,/sbin/dhclient其内容如下:

     #!/bin/bash
     ARGS=$(echo "$@" | sed 's/ -v / /g')
     exec /sbin/dhclient-true "-q" "$ARGS"
    
    Run Code Online (Sandbox Code Playgroud)