让 pi-hole docker 的 DHCP 与 libvirt dnsmasq 共存

不得不说,Linux 开发者都是一帮偏执的“天才”程序员。曾经有人提出过 dnsmasq 强制将 67 端口绑定至 0.0.0.0(所有网络界面),但是几位“天才”非要固执地说,这是为了负载平衡。结果,由 dnsmasq 魔改的 pihole-FTL,真的就和 libvirt 依赖的 dnsmasq 冲突了……

依照前人的解决办法,依然无法让 pi-hole 正常工作。在参阅了 pi-hole docker 文档另一位前人的笔记之后,终于找到了目前为止最好的解决方案。

背景

libvirt 安装好之后,会默认使用 NAT 模式将虚拟机连接到网络上。NAT 会生成一个网桥,并在网桥里面启用 dnsmasq。

解决办法就是完全停用 libvirt 生成的网桥,然后在 Linux 系统里手工建立一个网桥,并将虚拟机挂载到 Linux 网桥上。

完全关闭 libvirt 里面的默认网桥

virsh net-destroy default
virsh net-autostart --disable default

启动 pi-hole docker

sudo docker run -d \
    --name pihole \
...
    -e DNSMASQ_LISTENING=all \
    -e IPv6=false \
...
    --cap-add=NET_ADMIN \
    --net=host \
    pihole/pihole:latest

其中,DNSMASQ_LISTENING=all 可以在网络管理页面里面设置 Settings -> DNS -> Interface settings -> Permit all origins

建立系统网桥

这个步骤在不同的 Linux 发行版并没有统一的操作步骤,取决于 Linux 发行版采用哪种网络管理方式。

我使用的是 Ubuntu 24.04 LTS,采用的是 NetworkManager + Netplan 来管理网络。

首先,打开 Network Manager。

nm-connection-editor &

点击左下角的 + 号,然后设备类型选择 Bridge(网桥)。

在新建网桥的窗口中,填写网桥名称,然后点 Add 向网桥中添加网卡。
nm-br-1.png

弹出的窗口里面选好物理网卡,点击保存。
nm-br-2.png

切换到 IPv4 选项卡,设置 IP。在这里我使用了固定 IP,如果不需要固定 IP 的话,可以在第 2 步选择 DHCP,然后忽略第 3-5 步。
nm-br-3.png

最后,切换到 IPv6 选项卡,这里我关闭了 IPv6。然后点击保存。
nm-br-4.png

这样,网桥就建好了。

将虚拟机直接挂载到网桥

在虚拟机描述文件(domain XML)里面使用下面的方式定义网络连接。

    <interface type='bridge'>
      <mac address='52:54:00:3c:ac:6c'/>
      <source bridge='br0'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </interface>

在启动虚拟机之后,libvirt 会自动将虚拟机网卡加入到网桥中。

添加新评论