如何在 Ubuntu 中为特定接口的所有程序/层永久配置 DNS 解析

如何在 Ubuntu 中为特定接口的所有程序/层永久配置 DNS 解析

有没有办法可以永久设置 Ubuntu 笔记本电脑针对特定网络接口的 DNS 首选项?

我所依赖的 WiFi 网络不是那么可预测的。我无法访问 wifi 路由器管理控制台的编辑模式,并且 wifi 连接时不时地断开然后又恢复。

这意味着我必须不断调用此命令来“刷新”我的 DNS 条目:sudo resolvectl dns 3 1.1.1.1 8.8.8.8

这个问题最初是由我看到的网络浏览器DNS_*错误(许多不同的DNS_PROBE_STARTED,例如,,,,DNS_PROBE_FINISHED_NO_INTERNET等)产生的,所以我发现这个wifi网络(路由器)正在使用来自ISP(互联网服务提供商)的专用DNS条目。我可以在路由器配置仪表板上看到这些详细信息(自定义 IP 地址),但无法更改这些设置。DNS_PROBE_FINISHED_NXDOMAINDNS_PROBE_FINISHED_BAD_CONFIGDNS_PROBE_FINISHED_NO_INTERNET

另外:我可以看到我的 Ubuntu DNS 依赖于 wifi 网络的默认网关(路由器)。我通过 IP 地址匹配的这些命令发现了这一点:

# check my local Ubuntu DNS details for all interfaces
resolvectl dns
# find out the default gateway (it should be the router IP address)
ip route

我认为这意味着我的笔记本电脑动态依赖网关(路由器)进行 DNS 解析,并且路由器配置为使用来自 ISP(互联网服务提供商)的一些模糊的 IP 地址。它是否正确?

/etc/systemd/resolved.conf 我通过修改此文件并附加以下内容来更改全局 DNS :

DNS=1.1.1.1 8.8.8.8
FallbackDNS=8.8.4.4

然后我这样做了:

# make sure to restart the DNS daemon
sudo systemctl restart systemd-resolved.service
# check what DNS is being used by each interface
resolvectl status

但当然,这被我的 wifi 接口覆盖,我不知道如何操作,也不知道如何配置才能使其与我首选的 DNS 条目一起工作。

为了完整起见,我还这样做是为了确保 Web 浏览器依赖于新的 DNS 缓存而不会引发DNS_*错误(我不确定这是否正确/需要,是吗?):

# check current DNS cache
resolvectl statistics
# flush DNS cache
resolvectl flush-caches

如果我检查文件底部/etc/resolv.conf,我会看到以下内容:

nameserver 127.0.0.53
options edns0 trust-ad
search lan

我认为这个 DNS 问题可能与该条目有关nameserver 127.0.0.53 ,但我也知道该文件/etc/resolv.conf是自动生成的(并且可能自动刷新),systemd-resolved.service127.0.0.53意味着笔记本电脑依赖于由其管理的 DNS 的本地 IP 地址,systemd-resolved 所以我认为我应该不用手动更改它。

我有这种感觉,不同的程序/命令使用不同的位置/层来确定 DNS 配置。就像如果我以某种方式更改resolvectl/systemd-resolved.service设置,那么浏览器可能会从其他地方(例如该/etc/resolv.conf文件或类似的东西)读取 DNS 配置/etc/nsswitch.conf?是这样吗?

我想:

  • 使此命令sudo resolvectl dns 3 1.1.1.1 8.8.8.8永久有效(在重新启动和 wifi 断开/连接周期中)
  • 更改所有其他配置文件,例如/etc/resolv.conf/etc/nsswitch.conf类似的

依赖于我首选的 DNS 配置详细信息。我该怎么做呢?

答案1

您尚未表明这是桌面安装还是服务器安装。不管怎样,我会尽力解释。

首先我们看一下内容/etc/resolv.conf

nameserver 127.0.0.53
options edns0 trust-ad
search lan

这显示127.0.0.53为名称服务器,这是预期的,并且是本地缓存存根解析器。事实上,如果您输入 command ls -l /etc/resolv.conf,您会注意到它是一个符号链接/run/systemd/resolve/stub-resolv.conf(或者至少应该是),这是定义本地名称服务器的位置。

$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Dec 31  2021 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

存根解析器会缓存 DNS 查询,以便将来的查询更快,并且不必查询任何上行链路名称服务器。让我们看看实际情况。

打开两个终端窗口。在一个终端(我们将其称为 Terminal #1)中,tcpdump使用以下命令运行 a。替换wlp9s0为预期 DNS 查询会发出的接口。如果它是连接到互联网的唯一接口,那么就使用它。

sudo tcpdump -ni wlp9s0 -p port 53

然后在另一个窗口(Terminal #2)上运行以下命令:

dig google.com

终端 #2 中的输出如下所示,并指示127.0.0.53名称服务器:

$ dig google.com

; <<>> DiG 9.16.1-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54920
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;google.com.            IN  A

;; ANSWER SECTION:
google.com.     294 IN  A   142.251.46.206

;; Query time: 8 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Jul 12 19:47:07 PDT 2023
;; MSG SIZE  rcvd: 55

在终端 #1tcpdump运行时,要么没有输出,要么有一些活动。如果您以前访问过此站点,则查询应该位于您的本地缓存中,并且不会显示 的任何输出tcpdump。如果没有,那么您应该会看到包含对上行链路服务器的查询的输出。我假设您之前在我继续操作时查询过 google.com,这意味着目前还没有输出。

接下来,让我们清除本地 DNS 缓存。在终端 #2 中,输入以下内容:

sudo resolvectl flush-caches

然后dig google.com在 Terminal #2 中再次运行。这一次,您应该tcpdump在终端 #1 中看到查询您已定义或通过 DHCP 接收的上行链路服务器的输出。在下面的输出中,我看到正在查询的服务器208.65.212.34,这是通过我的 wifi 链接上的 DHCP 提供给我的 DNS 服务器之一。

$ sudo tcpdump -ni wlp9s0 -p port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlp9s0, link-type EN10MB (Ethernet), capture size 262144 bytes
19:50:55.534164 IP 172.23.123.82.39024 > 208.65.212.34.53: 36626+ [1au] A? google.com. (39)
19:50:55.550242 IP 208.65.212.34.53 > 172.23.123.82.39024: 36626 1/0/1 A 142.251.46.206 (55)

在我们完成的两个查询中,输出dig google.com显示127.0.0.53为正在查询的名称服务器,并且情况始终如此。但在幕后,如果之前没有查询过并存储在缓存中,则会查询上行链路服务器。

现在让我们在桌面环境和服务器的特定接口上设置 DNS 服务器。


定义每个接口的 DNS 服务器 - DESKTOP

在桌面环境中,在每个接口上分配 DNS 服务器非常容易。如果有 wifi 接口,很可能是通过 DHCP 设置的。因此,打开 wifi 设置,单击 IPv4 页面,然后只需添加一个类似于下图的 DNS 服务器,我将其定义8.8.8.8为附加 DNS 服务器:

在此输入图像描述

如果您不想使用 DHCP 服务器提供给您的任何 DNS 服务器,只需取消选中即可自动的

在终端中运行resolvectl status,您将看到这个额外的 DNS 服务器已添加到该接口中。如果还没有,您可能需要打开/关闭 wifi 适配器或重新启动。

Link 3 (wlp9s0)
      Current Scopes: DNS          
DefaultRoute setting: yes          
       LLMNR setting: yes          
MulticastDNS setting: no           
  DNSOverTLS setting: no           
      DNSSEC setting: no           
    DNSSEC supported: no           
  Current DNS Server: 208.65.212.34
         DNS Servers: 208.65.212.34
                      208.65.212.2 
                      8.8.8.8      
          DNS Domain: ~. 

对于其他接口,只需根据需要重复即可。


为每个接口定义 DNS 服务器 - SERVER

在服务器环境中,您可以在 Netplan 配置文件中为每个接口定义名称服务器。以下示例来自我创建的具有两个接口的虚拟机。第一个接口 ,eth0通过 DHCP 获取它的 IP 地址,但我覆盖了给我的 DNS 服务器,有效地忽略它们,然后定义我自己的。第二个接口eth1,设置有静态 IP 地址和手动定义的 DNS 服务器。

version: 2
renderer: networkd
ethernets:
  eth0:
    dhcp4: true
    dhcp4-overrides:
      use-dns: false
    nameservers:
      addresses:
        - 1.1.1.1
        - 9.9.9.9
  eth1:
    dhcp4: false
    addresses: [192.168.5.11/24]
    nameservers:
      addresses:
        - 8.8.8.8
        - 8.8.4.4

进行任何更改后,运行sudo netplan try以应用更改。然后运行resolvectl status​​,你会看到每个接口都有自己的 DNS 服务器。如果没有,您可能需要重新启动系统才能使更改真正生效,这是我在进行更改时遇到的情况。

$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 2 (eth0)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 1.1.1.1
       DNS Servers: 1.1.1.1 9.9.9.9

Link 3 (eth1)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 8.8.8.8
       DNS Servers: 8.8.8.8 8.8.4.4

然而,这种配置已经达到了 Netplan 的极限。要完全控制接口 DNS 设置,特别是关于 DNS 默认路由,则需要配置接口网络化直接而不是 Netplan。请参阅手册页系统网络(5)


最后,我们这里讨论的基本上是分割 DNS,您可以在其中配置特定的域来查询特定的服务器。这对于 VPN、DNS 默认路由、搜索域等有所帮助。要了解有关该主题的更多信息,请查看以下链接:

相关内容