dnsmasq通过address=/domain/格式精确匹配域名实现本地终结解析,禁用resolv-file并设置no-resolv可阻断外发;需配合防火墙锁定、停用systemd-resolved及抓包验证确保无DNS泄露。

用 dnsmasq 的 local 属性(配合 address= 和域名范围限定)可确保指定测试域名绝不向外转发,所有查询都在本地终结——这是防止开发联调环境敏感域名意外泄露到公网的最可靠手段。
明确 local 域名范围,避免泛匹配误伤
dnsmasq 不提供单独的 “local” 开关,而是通过 address= 指令 + 域名后缀精确控制。关键在于:只对明确的、带点号的完整域名或严格子域前缀做解析,不使用模糊通配符。
- ✅ 正确写法(强制本地响应,不转发):
address=/test-api.internal/192.168.50.10address=/dev.saneri.com/192.168.50.10 - ❌ 危险写法(可能匹配过多,且部分场景仍会 fallback 转发):
address=/.internal/192.168.50.10—— 这类泛域名规则在某些版本中可能触发上游查询兜底 - ⚠️ 注意:dnsmasq 对
/domain/格式默认视为“该域名及其所有子域名”,但仅当查询完全匹配或为子域时才生效;它不会把foo.internal当作.internal的子域去查——所以/test-api.internal/不会影响api.test-api.internal,除非显式加点
禁用上游转发,切断外网出口路径
即使写了 address 规则,若未关闭上游转发机制,dnsmasq 在无法本地匹配时仍可能尝试向 resolv-file 中配置的 DNS 服务器发起查询——这正是数据外泄的潜在通道。
- 在
/etc/dnsmasq.conf中必须设置:no-resolv—— 忽略resolv-file配置,彻底禁用上游 DNS - 同时移除或注释掉
resolv-file=行,避免残留配置干扰 - 如需保留部分公网解析能力(例如只放行 *.example.com),应改用
server=/example.com/8.8.8.8显式指定,而非依赖全局 resolv-file
验证是否真正“不外发”,三步实测确认
配置生效后,必须人工验证是否彻底阻断外网解析路径,不能仅凭服务启动就认为安全。
- 用内网机器执行:
dig @192.168.50.10 test-api.internal A +short—— 应返回你设定的 IP,且;; SERVER:行显示的是你的 dnsmasq 地址 - 抓包验证无外发:
sudo tcpdump -i any port 53 and host not 192.168.50.10 -nn,再执行上述 dig;期间不应出现任何发往 114.114.114.114、8.8.8.8 等外部 DNS 的 UDP 包 - 故意查一个不存在的测试子域:
dig @192.168.50.10 fake.test-api.internal A—— 应返回status: NXDOMAIN,而非NOERROR+ 外网IP(说明没fallback)
加固运行时环境,防配置被绕过
即便 dnsmasq 配置正确,若系统其他组件(如 systemd-resolved、NetworkManager)仍在接管 DNS,或防火墙未限制 53 端口出向流量,仍存在旁路风险。
- 停用并屏蔽 systemd-resolved:
sudo systemctl disable --now systemd-resolvedsudo rm -f /etc/resolv.conf && echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf - 锁定 resolv.conf 防篡改:
sudo chattr +i /etc/resolv.conf - 防火墙禁止本机向外发 DNS 请求:
sudo iptables -A OUTPUT -p udp --dport 53 ! -d 192.168.50.10 -j REJECT(假设 dnsmasq 运行在 192.168.50.10)


















