为Fedora43配置Cloudflare的私人DoT

2025年 11月 6日


现代网站越加重视网络安全和连接加密,尤其是在ECH不断推广受浏览器和网页服务器支持的现在和未来,防范DNS和SNI被监控和污染阻断是实现自由安全上网的一大步。

最近学习了HTTPS连接建立的过程(早就该学了只是太懒一直拖着没研究),随后发现连接建立过程中Client Hello默认不加密,这就给别有用心之人留下了利用SNI监控用户和阻断连接的把柄。

早些年开始推广ESNI,也就是加密Client Hello中的域名。近三年发展到ECH加密Client Hello中所有信息,很快就替代了ESNI作为主流浏览器默认启用的功能。再搭配HSTS限制客户端仅HTTPS连接,加密通信才算完全。唯一的遗憾就是无法加密也不可能加密连接的IP地址和端口,只能代理绕过了。

想要使用ECH,DoH/DoT是关键。ECH就是靠加密DNS提供信息指向正确的网站。目前主流的操作系统,包括Linux发行版、Android、Windows、MacOS都已支持启用和DoT相关配置。本文主要介绍如何在Fedora上配置Cloudflare Zero Trust提供的免费私人DoT服务。这个服务的域名、IP和443、853端口目前在部分地区没有被墙,之前折腾OpenWrt时也用它来提供DoH。

以下内容大部分翻译自 Configure DoT on systemd-resolved 略有增删。

Cloudflare Zero Trust添加默认DoT

  1. 进入 Zero Truest —— Gateway —— DNS位置。
  2. 点击 添加位置。
  3. 在 选择DNS终结点 处勾选 基于TLS的DNS(DoT),其他三个选项可选,建议全部勾选。
  4. 在 默认DNS位置 处勾选 启用EDNS客户端子网。如果这是你创建的唯一DNS配置,就把 设置为默认DNS位置 勾上。
  5. 点击 继续,如果想进一步限制哪些IP地址可用这个DNS配置,就勾选 DoT终结点筛选 后添加对应的IP,否则就忽略。
  6. 没问题就点击 完成。
  7. 复制 基于TLS的DNS 中的域名,比如 abc123.cloudflare-gateway.com,接下来就使用这个域名为操作系统配置全局DoT。

配置 systemd-resolved

首先你可以使用下面这个小脚本创建和更新DNS配置。注意把【abc123】换成你自己创建的真实子域名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh

RESOLVER="${1:-abc123.cloudflare-gateway.com}"

DNS_SERVERS=""

for dns in $(dig ${RESOLVER} +short && dig ${RESOLVER} +short AAAA); do
DNS_SERVERS+="$dns#${RESOLVER} "
done

cat <<EOF
[Resolve]
DNS=$DNS_SERVERS
FallbackDNS=$DNS_SERVERS
Domains=~.
DNSOverTLS=yes
DNSSEC=yes
EOF

这个脚本查询 abc123.cloudflare-gateway.com 的所有IP地址,并在末尾附加 #abc123.cloudflare-gateway.com,以告知 systemd-resolved 使用的 SNI 名称。由于 DoT 还依赖CA证书,它将从远程证书中获取名称,并与#之后提供的名称进行验证。如果不正确,DoT将因不受信任而连接失败。如果未指定SNI名称,DoT将回退到它所拥有的信息——IP地址——以验证证书的有效性。

脚本的输出是 systemd-resolved 的配置,其中包含通过 DNS= 和 FallbackDNS= 设置的 DNS 服务器,使用 Domains=~. 将它们作为默认域处理器。使用 DNSOverTLS=yes,启用DoT;使用 DNSSEC=yes 强制 DNSSEC。这样确保全局默认设置安全,且实际使用 abc123.cloudflare-gateway.com。

如果遇到查询某些域名报错的情况,比如查询 juejin.cn gitee.com 有以下报错信息:

1
gitee.com: resolve call failed: DNSSEC validation failed: no-signature

可以设置 DNSSEC=no 禁用 DNS 签名。由于 TLS 协议会对数据进行加密,所以在 Cloudflare DNS 服务器与客户端之间的通信依然加密,只不过DNS服务器进行递归查询时有被篡改的风险。参考

下一步则利用上面创建的脚本配置 systemd-resolved:

1
2
3
4
sudo mkdir -p /etc/systemd/resolved.conf.d/
generate-dns-config.sh | sudo tee /etc/systemd/resolved.conf.d/cloudflare-private-dot.conf
sudo systemctl restart systemd-resolved

路径 /etc/systemd/resolved.conf.d/ 可用于放置自定义配置,便于发行版更轻松地维护默认配置。使用 sudo tee … 可以将配置放入名为 cloudflare-private-dot.conf 的文件中,并在终端中获得相同的输出以进行验证。最后重启 systemd-resolved。如果 DNS 配置出现问题,只需删除该文件并重启守护进程即可恢复到默认设置。

配置 NetworkManager

要真正利用这个全局配置,必须禁用 NetworkManager 提供的每个接口配置。你可以添加另一个补充配置,但这次是针对 NetworkManager 的:

1
2
3
4
5
6
7
sudo mkdir -p /etc/NetworkManager/conf.d/
sudo tee /etc/NetworkManager/conf.d/cloudflare-dot.conf <<EOF
[main]
dns=none
systemd-resolved=false
EOF

dns=none 告诉 NetworkManager 不要修改 /etc/resolv.conf,因为你仍然希望在那里使用 systemd-resolved 服务。systemd-resolved=false 告诉 NetworkManager 停止与 systemd-resolved 通信,因此不再将任何自动获取自接口的 DNS 设置传递给它。

这种配置的缺点是,NetworkManager 中的 DNS 设置现在变得无效。但作为回报,所有接口都将使用全局配置,该配置指向 abc123.cloudflare-gateway.com。

想要检查结果是否正确,可以执行命令 resolvectl。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Global
Protocols: LLMNR=resolve -mDNS +DNSOverTLS DNSSEC=yes/supported
resolv.conf mode: stub
Current DNS Server: 162.159.55.66#abc123.cloudflare-gateway.com
DNS Servers: 162.159.55.77#abc123.cloudflare-gateway.com
162.159.36.20#abc123.cloudflare-gateway.com
2606:4700:abc::abc1:abc1#abc123.cloudflare-gateway.com
2606:4700:abc::abc2:abc2#abc123.cloudflare-gateway.com
Fallback DNS Servers: 162.159.55.66#abc123.cloudflare-gateway.com
162.159.55.77#abc123.cloudflare-gateway.com
2606:4700:abc::abc1:abc1#abc123.cloudflare-gateway.com
2606:4700:abc::abc2:abc2#abc123.cloudflare-gateway.com
DNS Domain: ~.

Link 2 (enp0s25)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
Protocols: +DefaultRoute +LLMNR -mDNS +DNSOverTLS DNSSEC=yes/supported
Current DNS Server: 1.1.1.1
DNS Servers: 1.1.1.1 9.9.9.9
DNS Domain: ~.
Default Route: yes

在这些输出中你会注意到 enp0s25 仍然有自己的 DNS 服务器配置。执行 sudo resolvectl dns enp0s25 "" 移除它。

之后看起来像这样(不同版本的系统结果有所区别):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Global
Protocols: LLMNR=resolve -mDNS +DNSOverTLS DNSSEC=yes/supported
resolv.conf mode: stub
Current DNS Server: 162.159.55.66#abc123.cloudflare-gateway.com
DNS Servers: 162.159.55.77#abc123.cloudflare-gateway.com
162.159.36.20#abc123.cloudflare-gateway.com
2606:4700:abc::abc1:abc1#abc123.cloudflare-gateway.com
2606:4700:abc::abc2:abc2#abc123.cloudflare-gateway.com
Fallback DNS Servers: 162.159.55.66#abc123.cloudflare-gateway.com
162.159.55.77#abc123.cloudflare-gateway.com
2606:4700:abc::abc1:abc1#abc123.cloudflare-gateway.com
2606:4700:abc::abc2:abc2#abc123.cloudflare-gateway.com
DNS Domain: ~.

Link 2 (enp0s25)
Current Scopes: LLMNR/IPv4 LLMNR/IPv6
Protocols: -DefaultRoute +LLMNR -mDNS +DNSOverTLS
DNSSEC=yes/supported
Default Route: no

这之后,如果你想,可以用 Wireshark 抓包验证结果。现在执行 resolvectl query cloudflare.com 你应该只会看见加密流量:

1
2
3
4
5
6
7
8
9
cloudflare.com: 2606:4700::6810:84e5           -- link: enp0s25
2606:4700::6810:85e5 -- link: enp0s25
104.16.132.229 -- link: enp0s25
104.16.133.229 -- link: enp0s25

-- Information acquired via protocol DNS in 359.7ms.
-- Data is authenticated: yes; Data was acquired via local or encrypted transport: yes
-- Data from: network

结论

总的来说,到目前为止,这个方法效果非常好,不再有未加密的 DNS 网络流量。这不仅可以防止基于网络的 DNS 攻击,还能减少信息泄露。这是实现更安全网络通信的重要一步。DNS 几乎是互联网上所有应用的基础,因此即使你甚至没有注意到差异,在最好的情况下,它也有助于为未来更安全的互联网做好准备。请注意,攻击者或网络提供商仍然可以通过收集 SNI 头信息来跟踪您访问的网站,除非客户端和服务器支持ECH。

值得一提的是,这种设置在使用如 Docker 和 Podman 等容器技术时并不能完美运行,因为在使用网络隔离时,容器将无法联系 systemd-resolved。不过,这可以通过提供 --dns 参数或在配置中设置特定的常规 DNS 服务器来解决。当然,这意味着容器无法从安全 DNS 中受益。

检查 DNS 加密状态

相关参考链接


Comments: