dnsmasq 读取 addn-hosts 配置但忽略它,并返回到系统的 /etc/hosts

dnsmasq 读取 addn-hosts 配置但忽略它,并返回到系统的 /etc/hosts

我在 Fedora 39 机器上dnsmasq以插件形式运行NetworkManager

我的配置是:

  1. /etc/dnsmasql.conf(默认,没有任何改变):
user=dnsmasq
group=dnsmasq
interface=lo
bind-interfaces
conf-dir=/etc/NetworkManager/dnsmasq.d,*.conf
conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig
  1. /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
[main]
dns=dnsmasq
  1. /etc/NetworkManager/dnsmasq.d/00-add-hosts.conf
log-queries
no-hosts
addn-hosts=/etc/hosts.d
address=/development/127.0.0.1

/etc/hosts.d是一个包含主机文件的目录,它们包括我想要“sinkhole”的域,例如:

0.0.0.0 1.example.com
0.0.0.0 2.example.com
...

从日志文件中我看到dnsmasq配置正常并且我的addn-hosts目录的主机文件已被读取:

Dec 30 16:18:40 fedora dnsmasq[61823]: chown of PID file /run/NetworkManager/dnsmasq.pid failed: Operation not permitted
Dec 30 16:18:40 fedora dnsmasq[61823]: DBus support enabled: connected to system bus
Dec 30 16:18:40 fedora dnsmasq[61823]: warning: no upstream servers configured
Dec 30 16:18:40 fedora dnsmasq[61823]: read /etc/hosts.d/private - 10 names
Dec 30 16:18:40 fedora dnsmasq[61823]: setting upstream servers from DBus
Dec 30 16:18:40 fedora dnsmasq[61823]: using nameserver 192.168.0.1#53(via wlp2s0)

但是这些主机文件没有任何效果,来自它们的域名仍然没有解析为 0.0.0.0 (正如我预期的那样),而是解析为域名的真实外部 IP 地址。

另一方面,当我将相同的域添加到时/etc/hosts,它们会按预期解析为 0.0.0.0,尽管no-hosts选项在配置文件中明确使用并作为选项传递给 dnsmasq 守护程序:

ps aux | grep dnsmasq

dnsmasq    61161  0.4  0.0 228096  4480 ?        S    16:08   0:00 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/run/NetworkManager/dnsmasq.pid --listen-address=127.0.0.1 --cache-size=400 --clear-on-reload --conf-file=/dev/null --enable-dbus=org.freedesktop.NetworkManager.dnsmasq --conf-dir=/etc/NetworkManager/dnsmasq.d

我的/etc/resolv.conf样子是这样的:

# Generated by NetworkManager
nameserver 127.0.0.1
options edns0 trust-ad

我知道有些dnsmasq配置没问题,例如address=/development/127.0.0.1按预期工作。但不知何故,与主机文件相关的配置被忽略了。可能是什么问题?

答案1

问题解决了,感谢这个答案

TLDR;在本地主机上运行的 DNS 服务器dnsmasq并不一定意味着它被使用NetworkManager,即使 /etc/resolv.conf明确说明了这一点;如果您的本地计算机正在使用路由器的 DHCP 服务器,您也可以从中获取 DNS 服务器设置。

TIL;默认情况dig下使用来自的 DNS 服务器/etc/resolv.conf,即使由管理的连接也NetworkManager使用从 DHCP 获得的 DNS 服务器地址;因此dig,如何curl解析相同的主机名存在差异。

故障排除:

  1. 检查我的本地主机 DNS 是否dnsmasq确实按预期工作:
# dig or nslookup a host from my addn-hosts's hosts file
$ dig 1.example.com
[...]
;; ANSWER SECTION:
1.example.com.      0   IN  A   0.0.0.0
[...]
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)

主机名按预期由(本地 DNS 服务器)解析为0.0.0.0(如 hosts 文件所述)。addn-hosts127.0.0.1dnsmasq

curl那么为什么来自或浏览器到同一主机名的所有请求都没有通过我的本地DNS得到解析dnsmasq,而是显然通过另一个上游DNS得到解析,尽管/etc/resolv.conf 说:

cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 127.0.0.1
options edns0 trust-ad

这意味着有东西正在覆盖 DNS 设置。一定是NetworkManager

  1. 检查NetworkManager正在使用的 DNS:
$ nmcli device show | grep -i dns
IP4.DNS[1]:                             192.168.0.1
IP6.DNS[1]:                             2a02:8383:d:c::1000
IP6.DNS[2]:                             2a02:8383:d:c::1

确实,正如所言/etc/resolv.confNetworkManager它使用我的 WiFi 路由器的 DNS 地址。这是因为我本地计算机上的 WiFi 连接使用路由器的DHCP设置。

  1. 设置上游 DNS 服务器dnsmasq

在修复 使用的 DNS 之前NetworkManager,我们需要添加一些上游 DNS,这些 DNS 将在检查 hosts 文件后使用。这是我的整个dnsmasq配置现在的样子:

$ cat /etc/NetworkManager/dnsmasq.d/00-add-hosts.conf

# NB! When making changes, don't forget restart dnsmasq & NetworkManager.service:
# $ killall dnsmasq
# $ systemctl restart NetworkManager

# No need to read /etc/resolv.conf as it contains the localhost
# addresses of dnsmasq itself
no-resolv

# Upstream DNS servers
# My router, Google, CloudFlare
server=192.168.0.1
server=8.8.8.8
server=1.1.1.1

# Add debug logging
# $ journalctl --follow -u NetworkManager
log-queries

# Ignore /etc/hosts
no-hosts

# Add custom hosts files; 
# If path is a directory, all files from it are loaded
addn-hosts=/etc/hosts.d
  1. NetworkManager修复 的连接设置中的 DNS 服务器:

打开nm-connection-editor(或设置 -> WiFi -> 您所连接的网络设置),然后IPv4

  • 方法 -> 仅限自动 (DHCP) 地址
  • DNS 服务器 -> 127.0.0.1(而不是自动)

然后是IPv6

  • 方法 -> 自动,仅 DHCP(注意,它与 不同IPv4

这对应于以下变化/etc/NetworkManager/system-connections/YOUR-CONNECTION-NAME.nmconnection

[ipv4]
dns=127.0.0.1;
ignore-auto-dns=true
method=auto

[ipv6]
addr-gen-mode=stable-privacy
dns=::1;
ignore-auto-dns=true
method=dhcp

现在,重新启动dnsmasqNetworkManager

$ sudo killall dnsmasq
$ sudo systemctl restart NetworkManager

et voilà!NetworkManager使用 localhost 作为 DNS 服务器,来自curl或 Web 浏览器的所有请求都通过它进行解析,来自 的额外 hosts 文件dnsmasqaddn-hosts受到尊重:

$ nmcli device show | grep -i dns
IP4.DNS[1]:                             127.0.0.1
IP6.DNS[1]:                             ::1
$ curl -v 1.example.com
* processing: 1.example.com
*   Trying 0.0.0.0:80...
* connect to 0.0.0.0 port 80 failed: Connection refused
*   Trying [2604:a880:400:d0::2082:1001]:80...
* Immediate connect fail for 2604:a880:400:d0::2082:1001: Network is unreachable
* Failed to connect to lobste.rs port 80 after 1 ms: Couldn't connect to server
* Closing connection

相关内容