修改 Linux 的 DNS 配置完全指南
引言:理解 DNS 在 Linux 中的作用与重要性
在当今的网络世界中,域名系统(DNS,Domain Name System)扮演着至关重要的角色。它就像互联网的电话簿,将人类易于记忆的域名(如 www.google.com
)转换成机器可以理解的 IP 地址(如 172.217.160.196
)。当我们尝试访问一个网站、连接到一个网络服务或进行任何基于域名的通信时,我们的操作系统首先会向配置的 DNS 服务器查询目标域名的 IP 地址。
对于 Linux 用户而言,正确配置 DNS 不仅关系到能否正常访问互联网资源,还可能影响网络连接的速度、稳定性和安全性。有时,出于以下原因,我们可能需要修改 Linux 系统的 DNS 配置:
- 提升速度: 使用距离更近或性能更好的 DNS 服务器可以加快域名解析速度,从而感觉网络更快。
- 增强隐私: 默认使用 ISP(互联网服务提供商)的 DNS 服务器,他们的日志可能会记录你的浏览历史。切换到注重隐私的第三方 DNS 提供商(如 Cloudflare 的 1.1.1.1)可以减少这种跟踪。
- 绕过限制或过滤: 某些网络环境(如学校、公司)可能通过 DNS 屏蔽特定网站。更换 DNS 服务器有时可以绕过这些限制。
- 访问特定内部资源: 在企业或局域网环境中,可能需要配置指向内部 DNS 服务器以解析内部域名。
- 故障排除: 当遇到网站无法访问或网络连接问题时,测试不同的 DNS 服务器是常见的故障排除步骤。
- 使用特定功能: 一些公共 DNS 提供商提供额外的功能,如恶意网站过滤(如 OpenDNS)、家庭安全保护等。
然而,在 Linux 中修改 DNS 配置有时可能不像在图形界面中简单填写几个数字那样直观。这是因为 Linux 的 DNS 配置可以通过多种方式进行管理,不同的发行版、不同的网络管理工具以及不同的网络连接方式(DHCP 或静态 IP)都会影响最终的配置方式。本指南将详细探讨在 Linux 中修改 DNS 配置的各种方法,帮助你理解背后的原理,并找到适用于你系统的最佳实践。
核心文件:/etc/resolv.conf
的作用与困境
在 Linux 系统中,用于配置域名解析的核心文件是 /etc/resolv.conf
。这个文件包含了 DNS 客户端(resolver)用于查询域名的信息。它的基本格式非常简单,主要由以下指令组成:
nameserver <IP 地址>
:指定一个 DNS 服务器的 IP 地址。可以有多行nameserver
指令,系统会按照它们出现的顺序依次尝试。通常最多可以指定 3 个或 4 个。search <域名1> [域名2 ...]
:指定一个域名搜索列表。当用户输入的域名不是完全限定域名(FQDN,Fully Qualified Domain Name,例如www.google.com.
最后的点表示根)时,系统会尝试将搜索列表中的每个域名后缀附加到用户输入的域名后面进行解析。例如,如果搜索列表包含mydomain.com
,用户输入webserver
,系统会先尝试解析webserver.mydomain.com
。domain <域名>
:指定默认的域名。这与search
指令类似,但通常只指定一个默认域名。如果同时存在search
和domain
,search
通常会覆盖或扩展domain
。options <选项> [...]
:指定一些解析器选项,例如timeout
(查询超时时间)、attempts
(查询重试次数)、ndots
(在尝试搜索列表之前,域名中包含多少个点才认为是 FQDN)。
示例 /etc/resolv.conf
文件:
“`conf
Generated by NetworkManager
search mydomain.com
nameserver 8.8.8.8
nameserver 8.8.4.4
“`
这个文件看起来非常简单,理论上我们只需编辑它就可以修改 DNS。然而,/etc/resolv.conf
的一个常见“困境”是它经常是临时的或由其他服务自动生成和管理的。这意味着你手动修改的内容很可能在系统重启、网络服务重启、网络接口状态变化(如从有线切换到 Wi-Fi,或者 DHCP 租约更新)之后被覆盖掉。
为什么会这样?因为在现代 Linux 发行版中,网络配置通常由后台服务(守护进程)管理,它们负责根据网络连接状态动态生成 /etc/resolv.conf
文件。常见的管理工具有:
- NetworkManager: 桌面和笔记本电脑上最常见的网络管理工具,尤其是在 GNOME、KDE 等桌面环境中。它根据用户在图形界面或
nmcli
命令中配置的信息生成/etc/resolv.conf
。 systemd-resolved
:systemd
项目提供的一个网络名字解析服务。它作为一个本地的 Stub Resolver(存根解析器)运行,应用程序查询systemd-resolved
,然后由它负责转发请求到实际的上游 DNS 服务器。在这种模式下,/etc/resolv.conf
通常被配置为一个指向本地地址(127.0.0.53
)的符号链接或文件,实际的上游 DNS 服务器配置则保存在systemd-resolved
的内部配置或由其通过其他方式(如systemd-networkd
、DHCP)获取。resolvconf
(utility): 一个较旧但仍在一些系统上使用的框架,它收集来自不同来源(如 DHCP 客户端、手动配置)的 DNS 信息,并据此生成/etc/resolv.conf
。- 传统网络脚本: 在没有 NetworkManager 或 systemd 的较旧系统或某些服务器发行版上,网络可能是通过
/etc/network/interfaces
(Debian/Ubuntu) 或/etc/sysconfig/network-scripts/
(RHEL/CentOS) 等文件配置,并在其中直接指定 DNS 服务器。
因此,仅仅编辑 /etc/resolv.conf
通常只能实现临时性的修改。要实现永久修改,我们需要识别出系统中负责管理 /etc/resolv.conf
的服务,并通过该服务提供的接口进行配置。
识别你的系统如何管理 /etc/resolv.conf
在你开始进行永久性修改之前,了解你的系统是如何管理 /etc/resolv.conf
是非常重要的。以下是一些检查方法:
- 查看文件头部的注释: 打开
/etc/resolv.conf
文件,通常文件顶部会有注释说明它是如何生成的,例如# Generated by NetworkManager
或# Generated by systemd-resolved
。 - 检查是否是符号链接: 运行
ls -l /etc/resolv.conf
。如果它是一个符号链接,它会指向另一个位置,比如/run/systemd/resolve/stub-resolv.conf
(systemd-resolved) 或/etc/resolvconf/resolv.conf
(resolvconf utility)。 - 检查运行中的服务: 使用
systemctl status systemd-resolved
或systemctl status NetworkManager
来查看这些服务是否正在运行。 - 检查 DHCP 客户端: 如果你的网络配置是通过 DHCP 获取的,那么 DHCP 客户端(如
dhclient
、dhcpcd
)可能会在获取 IP 地址的同时获取 DNS 信息并更新/etc/resolv.conf
。检查你的系统使用了哪个 DHCP 客户端。
了解了是哪个服务在管理 /etc/resolv.conf
后,你就可以选择相应的配置方法来实现永久修改。
方法一:手动修改 /etc/resolv.conf
(临时性)
这是最简单、最直接的方法,适用于需要快速测试某个 DNS 服务器或临时修改解析行为的场景。
-
打开终端:
bash
sudo nano /etc/resolv.conf
# 或者使用你喜欢的编辑器,如 vi, vim, gedit 等 -
编辑文件内容:
删除或注释掉原有的nameserver
行,添加你想使用的 DNS 服务器地址。例如,使用 Google Public DNS:
“`conf
# Generated by NetworkManager (或者其他注释,保留或删除均可)
# 原有的 nameserver 行可以注释掉或删除
# nameserver 192.168.1.1添加新的 DNS 服务器
nameserver 8.8.8.8
nameserver 8.8.4.4可选:添加搜索域名,如果需要
search mylocaldomain.com
“`
-
保存并关闭文件:
在 nano 中,按Ctrl+X
,然后按Y
确认保存,最后按Enter
键。
效果: 你的系统会立即开始使用新的 DNS 服务器进行域名解析。
局限性: 如前所述,这种修改在大多数现代系统上是临时的,可能会在网络服务重启、系统重启或网络状态变化后被覆盖。不要依赖这种方法进行永久性配置。
方法二:使用 NetworkManager 进行配置 (图形界面 & CLI)
NetworkManager 是许多桌面 Linux 发行版的默认网络管理工具。它提供了图形界面和命令行接口 (nmcli
) 来配置网络,包括 DNS。通过 NetworkManager 进行的配置是持久性的。
2.1 使用图形界面配置 (适用于桌面环境)
具体步骤可能因桌面环境(GNOME, KDE, XFCE 等)而异,但基本流程相似:
- 打开网络设置: 通常在系统设置或控制面板中找到“网络”或“网络连接”选项。
- 选择你的网络连接: 找到你当前使用的连接(例如,有线连接 Ethernet, Wi-F 无线连接名称)。
- 编辑连接设置: 点击连接旁边的齿轮图标、属性按钮或“编辑”选项。
- 进入 IPv4/IPv6 设置: 在连接设置窗口中,找到 IPv4 或 IPv6 选项卡(根据你的网络类型选择)。
- 修改 DNS 设置:
- 找到 DNS 部分。
- 默认通常是“自动 (DHCP)”。
- 切换为“自动 (仅地址)”或者“手动”。
- 如果选择“手动”,会有一个输入框让你填写 DNS 服务器地址。将你想要使用的 DNS 服务器地址列表输入到框中,多个地址之间用逗号分隔。
- 如果选择“自动 (仅地址)”,系统会通过 DHCP 获取 IP 地址、网关等信息,但 DNS 将使用你手动输入的地址。
- 有时也会有“搜索域”的设置,对应
/etc/resolv.conf
中的search
指令。
- 保存设置并应用: 点击“保存”、“应用”或“确定”。可能需要断开并重新连接网络,或者禁用再启用网络适配器,以使更改生效。
通过图形界面配置后,NetworkManager 会自动更新 /etc/resolv.conf
文件,并会在网络状态变化时维护这些设置。
2.2 使用 nmcli
命令配置 (适用于命令行)
nmcli
是 NetworkManager 的命令行工具,非常强大和灵活,适用于服务器或通过 SSH 连接进行远程管理时。
-
列出你的网络连接名称:
首先,你需要知道你想要修改的连接的名称。
bash
nmcli connection show
你会看到一个列表,例如Wired connection 1
,MyWiFi
,eth0
,wlan0
等。记住你当前正在使用的连接名称。 -
修改 DNS 服务器:
使用nmcli connection modify
命令来修改指定连接的 IPv4 或 IPv6 DNS 设置。以修改名为"Wired connection 1"
的连接的 IPv4 DNS 为例,设置为 8.8.8.8 和 8.8.4.4:
bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns "8.8.8.8, 8.8.4.4"
如果你使用的是 IPv6,使用ipv6.dns
:
bash
sudo nmcli connection modify "Wired connection 1" ipv6.dns "2001:4860:4860::8888, 2001:4860:4860::8844" -
设置 DNS 方法 (可选,但推荐如果你想完全手动控制 DNS):
默认情况下,NetworkManager 会结合 DHCP 获取的 DNS 信息和你手动设置的。如果你只想使用手动设置的 DNS,可以强制其使用手动方法:
bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns-method manual
# 如果使用 IPv6
# sudo nmcli connection modify "Wired connection 1" ipv6.dns-method manual
如果你想重新允许 NetworkManager 通过 DHCP 获取 DNS(并可能与手动设置的结合),可以设置为auto
:
bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns-method auto
如果设置为dhcp
,则完全只使用 DHCP 提供的 DNS。设置为ignore
则忽略 DHCP 提供的 DNS。设置为manual
则只使用ipv4.dns
/ipv6.dns
中指定的服务器。通常manual
是最直接的方式来强制使用你指定的 DNS。 -
修改搜索域 (可选):
bash
sudo nmcli connection modify "Wired connection 1" ipv4.dns-search "mydomain.com, anotherdomain.net"
# 如果使用 IPv6
# sudo nmcli connection modify "Wired connection 1" ipv6.dns-search "mydomain.com, anotherdomain.net" -
应用更改:
修改连接设置后,你需要重新激活该连接才能使更改生效。
bash
sudo nmcli connection down "Wired connection 1"
sudo nmcli connection up "Wired connection 1"
或者,你可以简单地重启 NetworkManager 服务(会中断所有网络连接):
bash
sudo systemctl restart NetworkManager
更温和的方法是先关闭网络,再打开:
bash
sudo nmcli networking off
sudo nmcli networking on
通过 nmcli
配置的 DNS 将会持久化到 NetworkManager 的配置文件中(通常在 /etc/NetworkManager/system-connections/
下),并在每次连接激活时应用。
方法三:使用 systemd-resolved
进行配置
在许多使用 systemd
的现代 Linux 发行版(如 Ubuntu 17.10+,Fedora 33+)中,systemd-resolved
负责处理名字解析。在这种情况下,/etc/resolv.conf
文件通常是一个指向 /run/systemd/resolve/stub-resolv.conf
或 /usr/lib/systemd/resolv.conf
的符号链接,文件内容是 nameserver 127.0.0.53
,表示系统将 DNS 请求发送给本地运行的 systemd-resolved
服务。
3.1 使用 resolvectl
命令
resolvectl
是与 systemd-resolved
交互的命令行工具。你可以用它来查看当前 DNS 设置和临时修改设置。
-
查看当前 DNS 设置:
bash
resolvectl status
这将显示每个网络接口的 DNS 服务器、全局 DNS 服务器以及当前的 DNS 路由。 -
临时修改 DNS 服务器:
你可以为特定的网络接口(例如eth0
)临时设置 DNS 服务器:
bash
sudo resolvectl dns eth0 8.8.8.8 8.8.4.4
或者设置全局的 fallback DNS 服务器(当接口没有指定 DNS 时使用):
bash
sudo resolvectl fallback-dns 8.8.8.8 8.8.4.4
注意: 使用resolvectl
命令进行的修改通常不是永久的,可能会在网络服务重启后丢失。
3.2 通过配置文件进行永久配置
要永久配置 systemd-resolved
,你需要编辑其配置文件。主要有两种方式:
-
全局配置 (
/etc/systemd/resolved.conf
):
这个文件用于设置systemd-resolved
的全局行为,包括全局的 DNS 服务器和 DNS 搜索域。
bash
sudo nano /etc/systemd/resolved.conf
找到[Resolve]
部分,取消注释或添加DNS
和FallbackDNS
行:
conf
[Resolve]
# 设置全局首选 DNS 服务器
DNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
# 设置全局备用 DNS 服务器(在首选服务器都失败时使用)
FallbackDNS=1.1.1.1 1.0.0.1
# 设置全局搜索域
# Domains=mydomain.com yourdomain.net
# 设置 DNS over TLS (DoT) 模式,可选的值有 no, yes, opportunistic
# DNSOverTLS=no
# 设置 LLMNR/mDNS/DNSSEC 等选项
# ...
保存文件后,需要重启systemd-resolved
服务:
bash
sudo systemctl restart systemd-resolved -
按接口配置 (
/etc/systemd/networkd/*.network
或/etc/NetworkManager/system-connections/*
):
systemd-resolved
通常与systemd-networkd
或 NetworkManager 集成。如果你的网络是由systemd-networkd
管理的,你可以在对应的.network
文件中配置 DNS。例如,为eth0
配置 DNS:
bash
sudo nano /etc/systemd/networkd/20-wired.network # 文件名和内容可能因系统而异
在[Network]
部分添加DNS
和Domains
行:
“`conf
[Match]
Name=eth0[Network]
DHCP=ipv4
DNS=8.8.8.8 8.8.4.4
Domains=mydomain.com…其他配置…
保存文件后,重启 `systemd-networkd` 服务:
bash
sudo systemctl restart systemd-networkd
``
systemd-resolved
如果你的系统使用 NetworkManager,如前所述,NetworkManager 会将 DNS 配置信息传递给。通过 NetworkManager 的方式(GUI 或
nmcli)配置 DNS 即可,
systemd-resolved` 会自动获取这些信息。
使用 systemd-resolved
时,应用程序应该通过其提供的本地接口(通常是 127.0.0.53
或 D-Bus)进行解析,而不是直接读取 /etc/resolv.conf
。systemd-resolved
会处理缓存、并发查询、DNSSEC 等高级功能。
方法四:使用 resolvconf
实用程序
resolvconf
(注意与 /etc/resolv.conf
文件的区别) 是一个用于管理 /etc/resolv.conf
文件的框架或程序。它收集来自系统各个部分的 DNS 配置信息(如 DHCP 客户端、VPN 客户端、手动配置)并将它们合并,然后生成最终的 /etc/resolv.conf
文件。一些 Debian/Ubuntu 系统可能仍在使用它。
如果你发现 /etc/resolv.conf
是一个指向 /run/resolvconf/resolv.conf
或类似路径的符号链接,那么你的系统可能正在使用 resolvconf
。
要通过 resolvconf
添加永久的 DNS 服务器,你可以编辑 /etc/resolvconf/resolv.conf.d/
目录下的文件。这个目录下通常有几个文件:
head
: 这个文件的内容会放在生成的/etc/resolv.conf
的顶部。适合放你想要总是优先使用的nameserver
。base
: 这个文件的内容会放在生成的/etc/resolv.conf
的head
部分之后,但在动态生成的配置之前。适合放基本的搜索域等。tail
: 这个文件的内容会放在生成的/etc/resolv.conf
的末尾。适合放你想要总是在动态配置之后使用的nameserver
或其他选项。
最常见的方式是编辑 head
文件来添加你首选的 DNS 服务器:
- 编辑
head
文件:
bash
sudo nano /etc/resolvconf/resolv.conf.d/head -
添加 DNS 服务器:
在文件中添加你的nameserver
行。例如:
“`conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND — YOUR CHANGES WILL BE OVERWRITTEN我的自定义 DNS 服务器,放在顶部优先使用
nameserver 8.8.8.8
nameserver 8.8.4.4下面是动态生成的或 base 文件内容
“`
保存并关闭文件。 -
更新
resolvconf
:
你需要通知resolvconf
重新生成/etc/resolv.conf
:
bash
sudo resolvconf -u
resolvconf
会合并来自各个源的信息(包括你手动编辑的 head
文件),并更新 /etc/resolv.conf
。这种方式的修改会持久存在,除非 resolvconf
本身被移除或替换。
方法五:通过静态 IP 配置指定 DNS
如果你选择为网络接口配置静态 IP 地址,那么通常可以在配置静态 IP 的文件中直接指定 DNS 服务器。这种方法适用于服务器或不需要 NetworkManager 等高级工具的场景。
5.1 Debian/Ubuntu (使用 /etc/network/interfaces
)
在基于 Debian/Ubuntu 的系统上,如果你不使用 NetworkManager 来管理某个接口,通常会在 /etc/network/interfaces
文件中配置它。
- 编辑接口配置文件:
bash
sudo nano /etc/network/interfaces -
为你的接口添加
dns-nameservers
和dns-search
行:
找到对应接口的配置段(例如iface eth0 inet static
),在其中添加以下行:
conf
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
# 添加 DNS 服务器
dns-nameservers 8.8.8.8 8.8.4.4
# 添加搜索域
dns-search mydomain.com yourdomain.net
保存并关闭文件。 -
重启网络服务或接口:
bash
sudo systemctl restart networking
# 或者只重启特定接口
# sudo ifdown eth0 && sudo ifup eth0
5.2 RHEL/CentOS/Fedora (使用 Network Scripts – 较旧方法)
在一些较旧的或特定配置的 RHEL/CentOS/Fedora 系统上,网络配置可能存储在 /etc/sysconfig/network-scripts/ifcfg-<interface>
文件中。
- 编辑接口配置文件:
bash
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0 # 替换 eth0 为你的接口名称 -
添加
DNS1
,DNS2
,DOMAIN
/SEARCH
变量:
确保BOOTPROTO
设置为static
或none
。添加或修改以下行:
conf
TYPE=Ethernet
BOOTPROTO=static
# ... 其他静态 IP 配置 ...
DNS1=8.8.8.8
DNS2=8.8.4.4
# 添加搜索域
DOMAIN="mydomain.com yourdomain.net"
# 或者使用 SEARCH 变量,有些系统可能支持
# SEARCH="mydomain.com yourdomain.net"
保存并关闭文件。 -
重启网络服务或接口:
bash
sudo systemctl restart network
# 或者只重启特定接口
# sudo ifdown eth0 && sudo ifup eth0
通过这种方式配置的 DNS 信息通常会被对应的网络服务读取,并在接口激活时用来更新 /etc/resolv.conf
。
方法六:通过 DHCP 客户端配置覆盖 DNS
如果你的系统通过 DHCP 获取网络配置,DNS 服务器通常是由 DHCP 服务器提供的。然而,你可以配置 DHCP 客户端来忽略、替换或添加 DHCP 提供的 DNS 服务器。这取决于你使用的 DHCP 客户端程序(如 dhclient
, dhcpcd
)。
6.1 使用 dhclient
(常见于 Debian/Ubuntu)
dhclient
的配置文件通常是 /etc/dhcp/dhclient.conf
。你可以在这里指定 DNS 行为。
- 编辑
dhclient.conf
:
bash
sudo nano /etc/dhcp/dhclient.conf -
修改
request
或添加prepend
/supersede
行:- 忽略 DHCP 提供的 DNS: 从
request
选项中移除domain-name-servers
。
conf
# request subnet-mask, broadcast-address, time-offset, routers,
# domain-name, domain-name-servers, host-name,
# interface-mtu, expire, root-path, non-local-source-routing;
# 修改为(移除 domain-name-servers):
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, host-name, interface-mtu, expire, root-path,
non-local-source-routing; - 优先使用指定的 DNS (prepend): 在 DHCP 提供的 DNS 服务器列表前面添加你指定的服务器。
conf
prepend domain-name-servers 8.8.8.8, 8.8.4.4; - 完全使用指定的 DNS (supersede): 忽略 DHCP 提供的所有 DNS 服务器,只使用你指定的。
conf
supersede domain-name-servers 8.8.8.8, 8.8.4.4;
选择其中一种方式进行配置。
- 忽略 DHCP 提供的 DNS: 从
-
保存并关闭文件。
-
续订或重启 DHCP 客户端:
你需要让 DHCP 客户端重新获取或更新租约。可以通过重启网络接口或重启 DHCP 客户端服务来实现:
bash
sudo systemctl restart network # 或者 networking
# 或者针对特定接口续订
# sudo dhclient -r -v eth0 # 释放租约
# sudo dhclient -v eth0 # 获取新租约
6.2 使用 dhcpcd
(常见于 Alpine, Slackware, Arch 等)
dhcpcd
的配置文件通常是 /etc/dhcpcd.conf
。
- 编辑
dhcpcd.conf
:
bash
sudo nano /etc/dhcpcd.conf -
添加或修改
nohook
,static domain_name_servers
,static domain_search
行:- 阻止
dhcpcd
更新/etc/resolv.conf
: 添加nohook resolv.conf
。这会阻止dhcpcd
修改/etc/resolv.conf
,然后你可以使用手动编辑或其他方法来管理/etc/resolv.conf
。
conf
nohook resolv.conf -
指定静态 DNS 服务器 (覆盖 DHCP 提供的):
“`conf
# 为所有接口指定 DNS
static domain_name_servers=8.8.8.8 8.8.4.4
# 或为特定接口指定 DNS
# interface eth0
# static domain_name_servers=8.8.8.8 8.8.4.4指定搜索域
static domain_search=mydomain.com yourdomain.net
“`
选择合适的方式进行配置。
- 阻止
-
保存并关闭文件。
-
重启
dhcpcd
服务或接口:
bash
sudo systemctl restart dhcpcd
# 或者针对特定接口
# sudo ip link set eth0 down
# sudo ip link set eth0 up
# sudo dhcpcd eth0
方法七:使用 chattr +i
使 /etc/resolv.conf
文件不可更改 (不推荐用于永久方案)
这是一种简单粗暴的方法,通过文件系统的属性使 /etc/resolv.conf
文件变成不可修改(immutable)。这样做可以防止任何程序(包括 NetworkManager, systemd-resolved, DHCP 客户端等)修改这个文件。
-
首先,手动编辑
/etc/resolv.conf
文件,按照你的意愿配置好 DNS 服务器:
bash
sudo nano /etc/resolv.conf
# 添加你的 nameserver 行
# nameserver 8.8.8.8
# nameserver 8.8.4.4
# 保存并关闭 -
使用
chattr
命令设置 immutable 属性:
bash
sudo chattr +i /etc/resolv.conf -
验证属性是否设置成功:
bash
lsattr /etc/resolv.conf
输出应该包含i
标志,例如--i--------e-- /etc/resolv.conf
。
效果: 现在,即使有服务尝试修改 /etc/resolv.conf
,也会因为文件不可修改而失败。你的手动配置将会一直保持。
移除 immutable 属性:
如果你需要再次修改这个文件,必须先移除 immutable 属性:
bash
sudo chattr -i /etc/resolv.conf
然后你就可以像往常一样编辑它了。
警告: 这种方法 不推荐 作为标准的、长期的 DNS 配置方案。它绕过了系统设计的网络管理流程,可能会导致其他依赖于动态更新 /etc/resolv.conf
的服务(如 VPN 连接推送 DNS、某些应用程序的网络配置)出现问题。它主要适用于紧急情况、特定测试场景或你完全清楚你在做什么并且接受其潜在风险的情况。
测试你的 DNS 配置
无论你使用了哪种方法修改了 DNS,都需要验证更改是否生效以及是否能够正确解析域名。
-
检查
/etc/resolv.conf
文件内容:
首先,确认/etc/resolv.conf
文件中的nameserver
行是否是你期望的。
bash
cat /etc/resolv.conf
注意: 如果你的系统使用systemd-resolved
并且/etc/resolv.conf
指向127.0.0.53
,那么这个文件本身的内容并不能直接显示上游 DNS。你需要使用resolvectl status
或其他工具来查看。 -
使用
ping
命令测试基本连通性:
尝试 ping 一个域名,看是否能解析成功并与对应的 IP 地址通信。
bash
ping google.com
如果能看到PING google.com (...)
并且有回复,说明 DNS 解析和网络连通性都没问题。 -
使用
nslookup
或dig
命令测试域名解析:
nslookup
和dig
是专门用于查询 DNS 的工具,它们能提供更详细的解析过程信息。dig
通常功能更强大且输出更详细,推荐使用dig
。-
使用
nslookup
:
bash
nslookup google.com
输出会显示用于解析的 DNS 服务器地址 (Server
字段) 和解析结果 (Address
字段)。 -
使用
dig
:
bash
dig google.com
dig
的输出更详细,其中SERVER
字段显示了实际进行查询的服务器地址,ANSWER SECTION
显示了查询结果。你可以使用+short
选项只看结果:
bash
dig google.com +short
你还可以指定使用特定的 DNS 服务器进行查询,以测试某个服务器是否工作正常:
bash
dig @8.8.8.8 google.com
这会强制使用 8.8.8.8 这个 DNS 服务器来解析google.com
。
-
-
使用
resolvectl
(仅适用于systemd-resolved
):
bash
resolvectl status
查看Current DNS Servers
和DNS Servers
字段,确认列出的服务器是你配置的。bash
resolvectl query google.com
测试使用systemd-resolved
解析一个域名。
常见问题与故障排除
- 修改
/etc/resolv.conf
后又被还原了: 这是最常见的问题。说明有其他服务(NetworkManager, systemd-resolved, DHCP 客户端等)在管理这个文件。请回到“识别你的系统如何管理/etc/resolv.conf
”这一节,找出罪魁祸首,并使用对应的方法进行永久配置。 - 网络连接正常,但域名无法解析:
- 防火墙: 检查你的防火墙是否阻止了到 DNS 服务器(默认端口 UDP/TCP 53)的出站连接。使用
sudo ufw status
或sudo firewall-cmd --list-all
查看规则。 - DNS 服务器本身有问题: 尝试 ping 你配置的 DNS 服务器 IP 地址,确认是否能连接到它。如果能 ping 通 IP 但不能解析域名,可能是 DNS 服务器本身故障或配置错误。
- 本地 DNS 缓存: 某些系统或应用程序可能有本地 DNS 缓存。尝试重启网络服务,或清除本地缓存(如
sudo systemctl restart systemd-resolved
,或对于dnsmasq
等服务进行相应操作)。浏览器也有自己的 DNS 缓存,可以尝试重启浏览器或清空浏览器缓存。 - 配置语法错误: 仔细检查你修改的配置文件(如
/etc/resolv.conf
,dhclient.conf
,resolved.conf
等)是否存在语法错误。
- 防火墙: 检查你的防火墙是否阻止了到 DNS 服务器(默认端口 UDP/TCP 53)的出站连接。使用
- 域名解析很慢:
- DNS 服务器响应慢: 你选择的 DNS 服务器可能延迟较高。尝试切换到其他公共 DNS 服务器,并使用
ping
或dig
测试它们的响应时间。 - 网络延迟: 你到 DNS 服务器的网络路径可能存在延迟。
- DNS 搜索域配置过多或不正确: 如果配置了多个搜索域,系统在解析非 FQDN 时会依次尝试,如果这些域不存在或查询耗时,会导致解析变慢。检查
/etc/resolv.conf
或相关配置中的search
或domain
行。 - DNSSEC 验证问题: 如果使用了支持 DNSSEC 的解析器(如
systemd-resolved
),验证失败有时可能导致解析延迟。
- DNS 服务器响应慢: 你选择的 DNS 服务器可能延迟较高。尝试切换到其他公共 DNS 服务器,并使用
- 某些特定域名无法解析:
- 内网域名: 如果你需要解析内部网络中的域名,确保你配置的 DNS 服务器能够解析这些内部域名(通常是局域网内的路由器或内部 DNS 服务器)。
- ISP 劫持或过滤: 某些 ISP 可能会劫持 DNS 请求或对特定域名进行过滤。切换到公共 DNS 服务器通常可以解决这类问题。
dig
或nslookup
可以解析,但应用程序无法访问网站:
DNS 解析只是网络连接的第一步。如果解析正确,但应用程序仍然无法连接,问题可能出在:- 防火墙: 应用程序使用的端口被防火墙阻止(不仅是 DNS 端口 53,还有 HTTP 的 80,HTTPS 的 443 等)。
- 代理设置: 应用程序可能配置了错误的代理服务器。
- 路由问题: 系统无法找到到达目标 IP 地址的正确路由。
- 服务器端问题: 目标服务器本身故障或阻止了你的连接。
选择合适的 DNS 服务器
选择一个合适的 DNS 服务器很重要。一些流行的公共 DNS 服务包括:
- Google Public DNS:
8.8.8.8
和8.8.4.4
(IPv4),2001:4860:4860::8888
和2001:4860:4860::8844
(IPv6)。速度快,全球节点多。 - Cloudflare:
1.1.1.1
和1.0.0.1
(IPv4),2606:4700:4700::1111
和2606:4700:4700::1001
(IPv6)。强调隐私和速度。 - OpenDNS:
208.67.222.222
和208.67.220.220
(IPv4)。提供可选的过滤功能。 - Quad9:
9.9.9.9
(IPv4),2620:fe::fe
(IPv6)。注重安全,会阻止恶意域名的解析。 - 你的 ISP 的 DNS 服务器: 通常会自动通过 DHCP 获取,速度可能较快因为它离你近,但隐私和功能方面可能不如公共 DNS。
- 你的路由器的 DNS 服务器: 许多家庭路由器充当本地 DNS 转发器,将内网设备的请求转发给 ISP 的 DNS 或路由器本身配置的 DNS。使用路由器地址 (通常是网关地址,如
192.168.1.1
) 作为 DNS 可以利用路由器的缓存,但最终取决于路由器的上游 DNS 配置。 - 本地 DNS 缓存服务器: 你可以在本地运行 DNS 缓存服务(如
dnsmasq
),它可以缓存查询结果,加快重复查询的速度,并可以用于简单的内网域名解析或广告过滤。在这种情况下,你的系统会将本地缓存服务器的地址(通常是127.0.0.1
)配置为 DNS 服务器,然后由本地服务负责向上游 DNS 查询。
选择时可以考虑:
- 速度/延迟: 使用
ping
或dig
测试延迟,或者使用namebench
等工具测试多个 DNS 服务器的性能。 - 隐私政策: 阅读 DNS 提供商的隐私政策,了解他们是否记录查询日志以及如何使用这些日志。
- 安全性/功能: 是否提供 DNSSEC 验证、恶意网站过滤、内容过滤等功能。
总结
修改 Linux 的 DNS 配置并非只有一种方法。核心在于 /etc/resolv.conf
文件,但它的内容通常由系统中的其他服务动态管理。要实现永久修改,你需要识别出是哪个服务在控制 /etc/resolv.conf
,并使用该服务提供的配置接口:
- 如果使用 NetworkManager (常见于桌面版),通过图形界面或
nmcli
命令配置连接属性。 - 如果使用
systemd-resolved
(常见于较新系统),配置/etc/systemd/resolved.conf
或使用resolvectl
(临时),或者通过 NetworkManager/systemd-networkd 配置接口的 DNS。 - 如果使用
resolvconf
实用程序,编辑/etc/resolvconf/resolv.conf.d/
下的文件并运行resolvconf -u
。 - 如果配置 静态 IP,在接口的配置文件(如
/etc/network/interfaces
或/etc/sysconfig/network-scripts/ifcfg-*
)中直接指定 DNS。 - 如果使用 DHCP,配置 DHCP 客户端文件(如
/etc/dhcp/dhclient.conf
或/etc/dhcpcd.conf
)来覆盖或添加 DHCP 提供的 DNS。 - 手动编辑
/etc/resolv.conf
配合chattr +i
是强制性的方法,但通常不推荐用于长期方案。
理解你的系统当前的网络管理方式是成功修改 DNS 的关键。通过本指南,你应该能够根据自己的系统环境和需求,选择最合适的方法来配置你的 Linux DNS,从而优化网络体验。在进行任何更改后,务必使用 cat /etc/resolv.conf
、ping
、nslookup
或 dig
命令来验证配置是否生效。