企业级内网DNS实战:用 dnsmasq 搭个内网 DNS
内网服务一多,Jenkins、Git、测试环境各一个 IP,开发运维各记一套,换台机器还得重新配。
与其继续维护 hosts,不如在内网放一台自己的 DNS:内部域名统一解析,外部域名缓存转发,客户端只改一个 DNS 地址。dnsmasq 轻量、配置直观,很适合干这件事。
先写 dnsmasq 配置
先在宿主机上建一个工作目录,把配置文件和 compose 文件放在一起,后面改起来方便。
1 | mkdir ~/dnsmasq-docker && cd ~/dnsmasq-docker |
配置文件可以这样写:
1 | # 监听所有地址(容器内 0.0.0.0 才能被外部访问) |
用 Docker Compose 启动
同目录下新建 docker-compose.yml:
1 | services: |
启动并看状态:
1 | docker compose up -d |
如果启动后发现 53 端口被占用
有时候 docker compose up -d 之后容器反复重启,docker logs dnsmasq 里能看到 53 端口绑定失败。先确认一下宿主机上是谁占着:
1 | ss -lunpt | grep :53 |
比较常见的情况是宿主机上的 systemd-resolved 在监听 127.0.0.53:53,和 dnsmasq 要绑定的 0.0.0.0:53 冲突了。
不建议直接 systemctl disable systemd-resolved。这样做会连带影响 Netplan 的 DNS 渲染、VPN 的分离 DNS,以及部分软件对 systemd-resolved 的依赖。更稳妥的做法是只关闭它的 53 监听,保留服务本身:
1 | sudo mkdir -p /etc/systemd/resolved.conf.d/ |
执行完后再启动一次容器:
1 | docker compose up -d |
测试 DNS 解析
先在宿主机上直接向容器查询:
1 | dig @127.0.0.1 jenkins.internal.com |
应返回你在 dnsmasq.conf 中配置的 10.8.0.2。
然后从另一台内网机器测试:
1 | dig @192.168.1.10 jenkins.internal.com |
这一步很关键。如果本机成功但远程失败,通常是两个原因。
- 宿主机防火墙未放行 53 端口
- dnsmasq 在容器内监听的地址不对。
如果dnsmasq.conf里写的是listen-address=127.0.0.1,容器内的 dnsmasq 只监听容器自己的回环地址,外部流量根本进不来。需要改成listen-address=0.0.0.0,或者按你的规划改成宿主机具体内网 IP。
让内网服务器把 DNS 指向 dnsmasq
dnsmasq 跑通后,还需要让内网机器把查询发给它。不同系统改法不一样,但原则相同:首选 DNS 指向 dnsmasq,备用 DNS 放一个可用的公网上游,避免 dnsmasq 本身故障时整网解析中断。
使用 systemd-resolved 的系统,编辑 /etc/systemd/resolved.conf:
1 | [Resolve] |
然后重启:
1 | sudo systemctl restart systemd-resolved |
使用 Netplan 的 Ubuntu 服务器,在对应网卡下添加:
1 | nameservers: |
改完后用 dig 或 resolvectl 确认解析结果。到这里,内网 DNS 的主体部分就已经可用了。







