从容器中运行 dnsmasq 作为 DHCP 代理

从容器中运行 dnsmasq 作为 DHCP 代理

我正在尝试配置 dnsmasq 以 DHCP 代理模式运行,向客户端提供 PXE 网络启动信息,同时我的路由器继续充当 DHCP 服务器。

理想情况下,我想在 Docker 容器中运行 dnsmasq。

我首先尝试在运行 Linux 的 VMware VM 中进行设置,如下所示:

# Verbose DHCP logging
log-dhcp

# Disable DNS
port=0

# Enable TFTP
enable-tftp
tftp-root=/tftproot

# Answer DHCP discovery requests coming in over the virtual machine
dhcp-range=172.0.0.0,proxy,255.0.0.0

dhcp-vendorclass=set:bios,PXEClient:Arch:00000
pxe-service=tag:bios,x86PC,"Netboot",netboot.xyz.kpxe,172.16.80.2

我启动了另一台 VMware VM,并将其设置为从网络启动。经过漫长的等待后,它确实开始通过 DHCP 进行配置,并成功启动。这是 dnsmasq 的输出:

dnsmasq-dhcp: 705858459 available DHCP subnet: 172.0.0.0/255.0.0.0
dnsmasq-dhcp: 705858459 vendor class: PXEClient:Arch:00000:UNDI:002001
dnsmasq-dhcp: 705858459 PXE(ens33) 00:0c:29:12:8b:9b proxy
dnsmasq-dhcp: 705858459 tags: bios, ens33
dnsmasq-dhcp: 705858459 broadcast response
dnsmasq-dhcp: 705858459 sent size:  1 option: 53 message-type  2
dnsmasq-dhcp: 705858459 sent size:  4 option: 54 server-identifier  172.16.80.2
dnsmasq-dhcp: 705858459 sent size:  9 option: 60 vendor-class  50:58:45:43:6c:69:65:6e:74
dnsmasq-dhcp: 705858459 sent size: 17 option: 97 client-machine-id  00:56:4d:e4:12:5a:70:00:5b:07:fb:d3:7b:cc...
dnsmasq-dhcp: 705858459 sent size: 31 option: 43 vendor-encap  06:01:03:0a:04:00:50:58:45:08:07:80:00:01...
dnsmasq-dhcp: 705858459 available DHCP subnet: 172.0.0.0/255.0.0.0
dnsmasq-dhcp: 705858459 vendor class: PXEClient:Arch:00000:UNDI:002001
dnsmasq-dhcp: 705858459 available DHCP subnet: 172.0.0.0/255.0.0.0
dnsmasq-dhcp: 705858459 vendor class: PXEClient:Arch:00000:UNDI:002001
dnsmasq-dhcp: 705858459 PXE(ens33) 172.16.80.3 00:0c:29:12:8b:9b netboot.xyz.kpxe
dnsmasq-dhcp: 705858459 tags: bios, ens33
dnsmasq-dhcp: 705858459 bootfile name: netboot.xyz.kpxe
dnsmasq-dhcp: 705858459 next server: 172.16.80.2
dnsmasq-dhcp: 705858459 sent size:  1 option: 53 message-type  5
dnsmasq-dhcp: 705858459 sent size:  4 option: 54 server-identifier  172.16.80.2
dnsmasq-dhcp: 705858459 sent size:  9 option: 60 vendor-class  50:58:45:43:6c:69:65:6e:74
dnsmasq-dhcp: 705858459 sent size: 17 option: 97 client-machine-id  00:56:4d:e4:12:5a:70:00:5b:07:fb:d3:7b:cc...
dnsmasq-dhcp: 705858459 sent size:  7 option: 43 vendor-encap  47:04:80:00:00:00:ff
dnsmasq-tftp: error 0 TFTP Aborted received from 172.16.80.3
dnsmasq-tftp: failed sending /tftproot/netboot.xyz.kpxe to 172.16.80.3
dnsmasq-tftp: sent /tftproot/netboot.xyz.kpxe to 172.16.80.3

现在我在 Docker 容器内运行同样的事情:

docker run --rm -it \
    --cap-add NET_ADMIN \
    -v /tftproot:/tftproot:ro \
    -v $(pwd)/dnsmasq.conf:/etc/dnsmasq.conf:ro \
    -p 67:67/udp \
    -p 69:69/udp \
    -p 4011:4011/udp \
    andyshinn/dnsmasq:2.81 --no-daemon

容器检测到客户端正在执行以下任务DHCPDISCOVER并尝试响应:

dnsmasq-dhcp: 705858459 available DHCP subnet: 172.0.0.0/255.0.0.0
dnsmasq-dhcp: 705858459 vendor class: PXEClient:Arch:00000:UNDI:002001
dnsmasq-dhcp: 705858459 PXE(eth0) 00:0c:29:12:8b:9b proxy
dnsmasq-dhcp: 705858459 tags: bios, eth0
dnsmasq-dhcp: 705858459 broadcast response
dnsmasq-dhcp: 705858459 sent size:  1 option: 53 message-type  2
dnsmasq-dhcp: 705858459 sent size:  4 option: 54 server-identifier  172.17.0.2
dnsmasq-dhcp: 705858459 sent size:  9 option: 60 vendor-class  50:58:45:43:6c:69:65:6e:74
dnsmasq-dhcp: 705858459 sent size: 17 option: 97 client-machine-id  00:56:4d:e4:12:5a:70:00:5b:07:fb:d3:7b:cc...
dnsmasq-dhcp: 705858459 sent size: 31 option: 43 vendor-encap  06:01:03:0a:04:00:50:58:45:08:07:80:00:01...
[above repeats a few times]

客户端才不是当 dnsmasq 在 Docker 容器内以相同的配置运行时,确认网络启动信息。

我有两个理论:

  1. 由于 Docker 网络的一些特性,发送到客户端的数据包从未到达那里。

  2. dnsmasq返回server-identifier的是 Docker 容器接口的 IP 地址,而不是运行容器的主机的面向网络的 IP 地址(应为 172.16.80.2)。

答案1

dnsmasq 使用端口 68 上的 UDP 广播数据包响应客户端,除非使用,否则该数据包不会离开桥接的 Docker 网络--net=host

一种解决方法是在 Docker 网络中添加一个socat转发到主机的监听器:

socat:
  image: alpine/socat
  command: >
    UDP4-LISTEN:68,reuseaddr,fork
    TCP4:172.18.0.1:24000

然后在主机上监听并重新广播到网络:

socat \
  TCP4-LISTEN:24000,bind=172.18.0.1,reuseaddr,fork \
  UDP-DATAGRAM:255.255.255.255:68,broadcast

这将会得到客户端的响应,但可能还有很多工作要做。

相关内容