摘要

在 Ubuntu 系统中,默认的 DNS 设置会导致服务器会将 DNS 不间断的设置为127.0.0.53

在一些情况下,如果您不对其做出迅速反应,将会导致所有 DNS 解析请求均失败,导致服务器无法访问外网,对于需要高稳定性且较为依赖 DNS 的服务,无异于灭顶之灾。

本文将对该问题进行研究,并提出一种解决该问题的方法

关键词: Linux ; Ubuntu ; DNS

Ubuntu 默认 DNS 策略概述

在 Ubuntu 中,DNS 由systemd-resolved服务管辖,其默认配置会在 127.0.0.53:53 上运行一个 DNS 存根监听器,以便本地应用程序可以将解析请求发送给它。这意味着当系统尝试解析域名时,它会首先向这个地址发送请求。 systemd-resolved服务会尝试解析这些请求,如果它自己的缓存中没有相应的记录,它会进一步向配置的上游 DNS 服务器查询。

由于Ubuntu 的 DNS 设计存在显著问题,这一默认策略可能导致 DNS 解析失败导致无法访问外网的后果。因此为了保证服务的稳定性,禁用其是必要的

禁用 DNS 存根监听器

在前文已提到,DNS 由systemd-resolved服务管辖,该服务的配置文件在/etc/systemd/resolved.conf。因此需要尝试修改该配置文件以禁用 DNS 存根监听器。

修改配置文件

首先,使用你喜欢的编辑器打开/etc/systemd/resolved.conf

默认配置一般如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Resolve]
# Some examples of DNS servers which may be used for DNS= and FallbackDNS=
:
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4
700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
# Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#d
ns.google 2001:4860:4860::8844#dns.google
# Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe:
:fe#dns.quad9.net 2620:fe::9#dns.quad9.net
#DNS=
#FallbackDNS=
#Domains=
#DNSSEC=no
#DNSOverTLS=no
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
#DNSStubListener=yes
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no

在该配置文件中,被注释掉的配置中的内容通常是在该配置项没有被配置时,服务将默认使用的配置项

每个配置项的含义说明如下:

  • DNS:主要 DNS ,系统将使用这些 DNS 服务器查询。你可以指定多个服务器,用空格分隔(例如 DNS=8.8.8.8 1.1.1.1
  • FallbackDNS:备用 DNS,当主要DNS均无法查询时,系统将使用这里列出的备用服务器,同样你可以指定多个备用服务器
  • Domains: 用于指定这些 DNS 服务器应使用的搜索域。
  • DNSSEC=no: 是否启用 DNSSEC 验证。no 表示不启用。
  • DNSOverTLS=no: 是否通过 TLS 加密向 DNS 服务器发送查询。no 表示不加密。
  • MulticastDNS=no: 是否启用多播 DNS (mDNS) 解析(如 .local 域名)。no 表示不启用。
  • LLMNR=no: 是否启用链路本地多播名称解析 (LLMNR)。no 表示不启用。
  • Cache=no-negative: 配置 DNS 缓存行为。no-negative 表示不缓存负面(查询失败)响应。
  • CacheFromLocalhost=no: 是否缓存来自本地回环接口(localhost)的响应。no 表示不缓存。
  • DNSStubListener=yes: 是否在 127.0.0.53:53 上运行一个 DNS 存根监听器,以便本地应用程序可以将解析请求发送给它。yes 表示启用。
  • DNSStubListenerExtra=: 在额外地址上启用 DNS 存根监听器。
  • ReadEtcHosts=yes: 是否在解析域名时读取 /etc/hosts 文件。yes 表示读取。
  • ResolveUnicastSingleLabel=no: 是否尝试通过 DNS 解析单标签名称(没有点的名称)。no 表示不尝试。

在其中,我们可以发现DNSStubListener=yes这一配置项是我们需要配置的,系统默认的配置项为yes表示启用,我们需要禁用它。

因此,我们需要解除其注释并修改成no,其配置项如下:

1
DNSStubListener=no

以下为我设置的完整配置文件,我使用谷歌8.8.8.8DNS并启用了DNSSECTLS查询,可保证DNS查询结果在网络传输中不被篡改,你可以直接应用或自行更改配置项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Resolve]
DNS=8.8.8.8 8.8.4.4
FallbackDNS=1.1.1.1
#Domains=
DNSSEC=allow-downgrade
DNSOverTLS=yes
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
DNSStubListener=no
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no