systemd-resolved 和 dnsmasq 抢 53 端口
想在机器上跑个 dnsmasq 给内网做解析,装完 systemctl start dnsmasq
直接失败,日志只有一句 failed to create listening socket for port 53。
先看是谁占着
sudo ss -lunp | grep ':53'
# UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=756,fd=17))
# UNCONN 0 0 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=756,fd=19))
两个监听:127.0.0.53 是给本机应用用的 stub,
127.0.0.54 是给 systemd-networkd 做 DNS 代理的。
只要 resolved 在跑,这两条就占着。
三种处理
1. 关掉 stub listener(改配置)
最温和,保留 resolved 的其他功能,只放开 127.0.0.53:53:
# /etc/systemd/resolved.conf
[Resolve]
DNS=223.5.5.5 119.29.29.29
DNSStubListener=no
sudo systemctl restart systemd-resolved
注意 127.0.0.54:53 那条还在,但 dnsmasq 默认只绑 0.0.0.0,
会跟它冲突。给 dnsmasq 加一句 bind-interfaces
和明确的 listen-address 就行。
2. 直接停掉 resolved
sudo systemctl disable --now systemd-resolved
sudo rm -f /etc/resolv.conf
printf 'nameserver 127.0.0.1\n' | sudo tee /etc/resolv.conf
干净,但要记得 /etc/resolv.conf 原本是指向
/run/systemd/resolve/stub-resolv.conf 的符号链接,
删之前确认一下:
ls -l /etc/resolv.conf
删了软链后有些工具(比如 networkd 相关的)会再把它重建回来,
所以还要 chattr +i 或者干脆别删。
3. 让 dnsmasq 换个端口
如果只是想让内网机器用,不一定非要 53,port=5353 也能工作,
反正上游可以在别处配。这种方式对系统零侵入,我最常用。
顺带说个坑
dig 查本机解析时结果和 getent hosts 不一致,
是因为它们走不同的路径:dig @127.0.0.1 直连 dnsmasq,
而 getent 走 /etc/nsswitch.conf 加
/etc/resolv.conf。排查「解析不对」之前先分清是哪一层。
getent hosts example.com
dig +short example.com @127.0.0.1
resolvectl query example.com
三条命令跑一遍,问题基本就定位了。