环境 链接到标题

项目 内容
硬件 Raspberry Pi 4 (4GB)
系统 Ubuntu Server 24.04.2 LTS (arm64)
Docker 29.3.0 + Compose v5.1.0

方案选型 链接到标题

旧的 DNS 服务器不打算继续用了,在树莓派 4 上重新搭一个。需求很简单:内网设备 hostname 解析 *.lan

备选方案:

方案 语言 特点 结论
dnsmasq C 极轻量,单二进制,2000年至今 ✅ 够用
systemd-resolved C Ubuntu 自带,零安装 ❌ 对外监听需额外配置,expand-hosts 不支持
unbound C 递归解析器,DNSSEC 强 ❌ 大炮打蚊子
CoreDNS Go 云原生,插件化 ❌ 太重
blocky Go Web UI,策略丰富 ❌ 功能过剩

dnsmasq 入选理由:轻量、稳定、内网场景足够。

注意 CVE 链接到标题

2026年5月 dnsmasq 被通报了 6 个 CVE(CVE-2026-2291 ~ CVE-2026-5172),包括堆溢出导致 DNS 缓存投毒、DNSSEC DoS、DHCPv6 提权等。修复版本 2.93。务必使用 2.93+,不要用系统仓库中的旧版。

安装 链接到标题

拉取镜像 链接到标题

Docker Hub 被墙,走 DaoCloud 镜像:

docker pull docker.m.daocloud.io/dockurr/dnsmasq:2.93

dockurr/dnsmasq 并非官方镜像(dnsmasq 无官方 Docker 镜像),但 GitHub 开源,500K+ pulls,支持 amd64/arm64/armv7。

配置 链接到标题

docker-compose.yml

services:
  dnsmasq:
    image: docker.m.daocloud.io/dockurr/dnsmasq:2.93
    container_name: dnsmasq
    network_mode: host
    cap_add:
      - NET_ADMIN
    volumes:
      - ./dnsmasq.conf:/etc/dnsmasq.conf
      - ./hosts:/etc/hosts
    restart: always

dnsmasq.conf

port=53
domain=lan
expand-hosts
local=/lan/
bind-interfaces
no-resolv
server=223.5.5.5
server=114.114.114.114

hosts(示例,按实际情况替换 IP 和主机名)

10.0.0.50	server-a
10.0.0.51	server-b
10.0.0.99	nas-01

链接到标题

踩坑记录 链接到标题

坑一:listen-address 导致 UDP 不响应 链接到标题

现象:dnsmasq 启动正常,日志无报错,端口 53 正常监听,但 DNS 查询全部超时。TCP 连接正常,UDP 无响应。

原因:Alpine 容器中 listen-address=0.0.0.0 与 musl libc 的 socket 行为不兼容,UDP 数据包无法被 dnsmasq 处理。

解决:改为 bind-interfaces,不显式指定 listen-address。

坑二:Docker bridge 网络 UDP 端口转发不通 链接到标题

现象:容器内端口正常,宿主机 ss 显示 53 监听,但宿主机到容器的 UDP 查询超时。tcpdump 显示数据包已到达 Docker bridge,但容器未响应。

原因:Docker bridge 模式下 UDP 端口转发存在兼容性问题(猜测与内核 iptables 或 Docker 版本有关)。

解决:改用 network_mode: host,容器直接使用宿主机网络栈,绕过 Docker bridge。

坑三:address= 指令与 expand-hosts 不兼容 链接到标题

现象:查询 server-a.lan 返回 NXDOMAIN。

原因expand-hosts 只对 /etc/hosts 文件中的条目生效,address= config 指令不参与域名扩展。

解决:直接把 IP 映射写在 /etc/hosts 文件中,由 expand-hosts + domain=lan 自动追加 .lan 后缀。

验证 链接到标题

$ dig +short server-a.lan @127.0.0.1
10.0.0.50

$ dig +short device-x.lan @127.0.0.1
10.0.0.60

$ dig +short baidu.com @127.0.0.1
1.2.4.8

本地解析和上游解析均正常。

总结 链接到标题

dnsmasq 仍然是内网 DNS 最省心的方案。这次升级到 2.93 解决了已知 CVE,同时补上了最近 Docker + Alpine + musl libc 的几个坑。配置文档在此:github.com/dockur/dnsmasq