彻底解决 Ubuntu 系统 127.0.0.53 DNS 解析异常问题
## 摘要
在 Ubuntu 系统中,默认的 DNS 机制会将解析地址持续指向 `127.0.0.53`。在某些特定场景下,如果不及时处理,会导致所有的域名解析请求失败,致使服务器断网。这对高度依赖网络稳定性的服务而言是致命的。本文将深入探讨此问题的根源,并给出有效的解决方案。
## Ubuntu 默认 DNS 策略概述
Ubuntu 系统的 DNS 主要由 `systemd-resolved` 服务接管。默认情况下,它会在 `127.0.0.53:53` 端口运行一个本地 DNS 存根监听器,系统应用会向这个地址发送解析请求。`systemd-resolved` 会优先利用自身缓存进行应答,若未命中,则进一步向配置好的上游 DNS 发起查询。
然而,这种默认策略在设计上存在明显缺陷,极易引发 DNS 解析彻底死锁,最终导致设备无法访问外部网络。为了保障核心业务的不间断运行,禁用该存根监听器是极其必要的。
## 禁用 DNS 存根监听器的步骤
如前所述,既然问题出在 `systemd-resolved` 服务上,我们只需修改其配置文件 `/etc/systemd/resolved.conf` 即可关闭存根监听功能。
### 1. 修改配置文件
使用任意文本编辑器打开 `/etc/systemd/resolved.conf`。
初始状态下的文件内容通常如下所示(包含大量被注释掉的默认项):
```ini
[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#quad9.net 149.112.112.112#quad9.net 2620:fe:
:fe#quad9.net 2620:fe::9#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=8.8.8.8 1.1.1.1`)。
* **`FallbackDNS`**:备用 DNS 服务器。当主节点全部解析失败时生效,同样支持多地址。
* **`Domains`**:指定这些 DNS 服务器匹配的搜索域。
* **`DNSSEC=no`**:控制是否开启 DNSSEC 验证。`no` 即不启用。
* **`DNSOverTLS=no`**:设定是否利用 TLS 加密发起 DNS 查询。`no` 代表不加密。
* **`MulticastDNS=no`**:设定是否开启 mDNS(多播 DNS)解析(如 `.local` 域名)。`no` 代表关闭。
* **`LLMNR=no`**:设定是否启用链路本地多播名称解析(LLMNR)。`no` 代表关闭。
* **`Cache=no-negative`**:控制 DNS 缓存机制。`no-negative` 表示不对查询失败等负面结果进行缓存。
* **`CacheFromLocalhost=no`**:是否对本地回环接口传来的响应执行缓存。`no` 代表不缓存。
* **`DNSStubListener=yes`**:是否在 `127.0.0.53:53` 运行 DNS 存根监听器以供本地程序调用。`yes` 即代表启用。
* **`DNSStubListenerExtra=`**:用于在额外的地址上启动监听器。
* **`ReadEtcHosts=yes`**:解析时是否读取 `/etc/hosts` 文件。`yes` 代表读取。
* **`ResolveUnicastSingleLabel=no`**:是否尝试解析单标签名称(不含点的名称)。`no` 代表不尝试。
我们要解决的就是 `DNSStubListener=yes` 这个默认开启的项。
取消其注释并把值改为 `no`:
```ini
DNSStubListener=no
```
### 2. 重启服务生效
保存配置文件后,执行以下指令重启服务:
```bash
systemctl restart systemd-resolved
```
### 3. 完整配置示例
下方是经过实践检验的完整配置范例。该范例采用了 Cloudflare 的 `1.1.1.1` DNS,并开启了 DNSSEC 与 TLS 加密查询,能有效防范传输过程中的 DNS 污染与篡改。你可以直接复制修改使用:
```ini
[Resolve]
DNS=1.1.1.1
FallbackDNS=8.8.8.8
#Domains=
DNSSEC=allow-downgrade
DNSOverTLS=yes
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
DNSStubListener=no
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no
```
在 Ubuntu 系统中,默认的 DNS 机制会将解析地址持续指向 `127.0.0.53`。在某些特定场景下,如果不及时处理,会导致所有的域名解析请求失败,致使服务器断网。这对高度依赖网络稳定性的服务而言是致命的。本文将深入探讨此问题的根源,并给出有效的解决方案。
## Ubuntu 默认 DNS 策略概述
Ubuntu 系统的 DNS 主要由 `systemd-resolved` 服务接管。默认情况下,它会在 `127.0.0.53:53` 端口运行一个本地 DNS 存根监听器,系统应用会向这个地址发送解析请求。`systemd-resolved` 会优先利用自身缓存进行应答,若未命中,则进一步向配置好的上游 DNS 发起查询。
然而,这种默认策略在设计上存在明显缺陷,极易引发 DNS 解析彻底死锁,最终导致设备无法访问外部网络。为了保障核心业务的不间断运行,禁用该存根监听器是极其必要的。
## 禁用 DNS 存根监听器的步骤
如前所述,既然问题出在 `systemd-resolved` 服务上,我们只需修改其配置文件 `/etc/systemd/resolved.conf` 即可关闭存根监听功能。
### 1. 修改配置文件
使用任意文本编辑器打开 `/etc/systemd/resolved.conf`。
初始状态下的文件内容通常如下所示(包含大量被注释掉的默认项):
```ini
[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#quad9.net 149.112.112.112#quad9.net 2620:fe:
:fe#quad9.net 2620:fe::9#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=8.8.8.8 1.1.1.1`)。
* **`FallbackDNS`**:备用 DNS 服务器。当主节点全部解析失败时生效,同样支持多地址。
* **`Domains`**:指定这些 DNS 服务器匹配的搜索域。
* **`DNSSEC=no`**:控制是否开启 DNSSEC 验证。`no` 即不启用。
* **`DNSOverTLS=no`**:设定是否利用 TLS 加密发起 DNS 查询。`no` 代表不加密。
* **`MulticastDNS=no`**:设定是否开启 mDNS(多播 DNS)解析(如 `.local` 域名)。`no` 代表关闭。
* **`LLMNR=no`**:设定是否启用链路本地多播名称解析(LLMNR)。`no` 代表关闭。
* **`Cache=no-negative`**:控制 DNS 缓存机制。`no-negative` 表示不对查询失败等负面结果进行缓存。
* **`CacheFromLocalhost=no`**:是否对本地回环接口传来的响应执行缓存。`no` 代表不缓存。
* **`DNSStubListener=yes`**:是否在 `127.0.0.53:53` 运行 DNS 存根监听器以供本地程序调用。`yes` 即代表启用。
* **`DNSStubListenerExtra=`**:用于在额外的地址上启动监听器。
* **`ReadEtcHosts=yes`**:解析时是否读取 `/etc/hosts` 文件。`yes` 代表读取。
* **`ResolveUnicastSingleLabel=no`**:是否尝试解析单标签名称(不含点的名称)。`no` 代表不尝试。
我们要解决的就是 `DNSStubListener=yes` 这个默认开启的项。
取消其注释并把值改为 `no`:
```ini
DNSStubListener=no
```
### 2. 重启服务生效
保存配置文件后,执行以下指令重启服务:
```bash
systemctl restart systemd-resolved
```
### 3. 完整配置示例
下方是经过实践检验的完整配置范例。该范例采用了 Cloudflare 的 `1.1.1.1` DNS,并开启了 DNSSEC 与 TLS 加密查询,能有效防范传输过程中的 DNS 污染与篡改。你可以直接复制修改使用:
```ini
[Resolve]
DNS=1.1.1.1
FallbackDNS=8.8.8.8
#Domains=
DNSSEC=allow-downgrade
DNSOverTLS=yes
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
DNSStubListener=no
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no
```
评论
暂无评论。