Skip to main content
Re:Linked

在 Firefox 上设置 DoH 和 ESNI/ECH,完成加密浏览的最后一块拼图

· #security · 约 4.7k 字
本文距离上次更新已经超过 900 天。因此,其中的信息可能已经过时。

EDIT 2021/5/30:根据 Matters 的评论与现实中的草案进展,进行大量修正与更新。

TLS 1.3 是 TLS 很大的一步。它新增的特性中相当令人瞩目的两个,一个是 0-RTT,另一个就是随着 KeyShareEntry 的出现而变为现实的 ESNI (Encrypted SNI,后由 ECH (Encrypted Client Hello) 取代)草案。带上 ECH,这份草案目前已经有了十个版本(最新的在这里:draft-ietf-tls-esni-10),也受部分浏览器(Firefox 支持过 ESNI,现在支持 ECH;Chromium 跳过了 ESNI,ECH 支持在做了)以及部分服务商(CloudFlare 的许多网站支持 ESNI)的支持。

SNI (Server Name Indication) 主要用于同 IP 托管多个域名的情况。在这种情况下,客户端需要告知服务端其所访问的域名,服务端才能回复正确的证书,从而继续 TLS 握手过程。因此,虽然 TLS 使得用户的浏览内容和 HTTP 头都受到加密,第三方无法解密(如果你像 CNNIC 一样能用根证书做中间人攻击,当我没说),但在访问使用了 SNI 的网站时,客户端告知域名的信息需要以明文的形式传递。这是一个鸡生蛋、蛋生鸡的问题:没有域名就无法发送证书,而没有证书就不能进行加密。此时,中间人便可以从 SNI 信息获取客户端所访问的域名,从而进行相应的处理(例如拦截)。这也是 SNI 封锁的原理。有了 ECH 的加持,HTTP 的整个过程就都被 TLS 等组件保护,变得全副武装。因此,也有人说 ECH 是加密浏览的最后一块拼图。

基于国家安全和网络主权原因,在某些国家和地区, ESNI 已经全部被封锁(不过 ECH 可能还没)。不过,不受此影响的用户可以继续往下看。

那 ESNI/ECH 的加密是怎么来的?

没有 SNI,就没有服务器证书,那 ESNI/ECH 考靠什么进行身份验证和加密呢?答案是 DNS。DoH (DNS over HTTPS) 和 DoT (DNS over TLS) 的广泛应用已经使 DNS 请求的机密性和完整性 (integrity) 得到了良好的保护。因此,在 DoH 和 DoT (想的话还可以带上 DNSSEC)下, DNS 可以被认为是安全和私密的。不过明文 DNS 也罢,草案表示,如果 DNS 都被控制了,那这里其它的加密手段也没有意义。近期的一个新草案 DNS SVCB 和 HTTPS RR (draft-ietf-dnsop-svcb-https-05) 推出了一些基于 DNS 进行查询的扩展。ESNI 和 ECH 就利用了这些扩展,通过 DNS 查询得到的信息和服务器建立加密信道。这两个草案蛮复杂的,这里就不展开讲了。

上手 ESNI/ECH

配置 DNS over HTTPS

此段落只设计给想要开启 ESNI 的用户。ECH 可能不需要 DoH。

前文说到,为了实现 ESNI,浏览器需要一些 DNS 扩展。考虑到操作系统一般没有除了获取 IP 地址(getaddrinfo())之外的 DNS 相关 API,Firefox 另辟蹊径,通过其添加的 DNS over HTTPS 支持来实现自己需要的功能。因此,为了开启 ESNI,需要先启用 DNS over HTTPS。

这并不复杂。在设置页面(about:preferences)搜索 DNS,点击「网络设置」一节的设置按钮,翻到最底下,就能看到 DNS over HTTPS 的设定。

Enable DoH on Firefox

在这里,可以按照自己的喜好选择 DNS 服务提供商。如果对隐私有担忧,可以选择一些其它的 DoH 提供商,而不是那个位于美国的世界最大 MitM 公司

开启 ESNI

Firefox 85 起用 ECH 替代了 ESNI,因此这条配置项可能已经从你使用的 Firefox 中移除

about:config 搜索条目 network.security.esni.enabled,将其设定改为 true 即可。

开启 ECH

ECH 尚未广泛部署。

about:config 搜索条目 network.dns.echconfig.enablednetwork.dns.use_https_rr_as_altsvc,将它们的设定改为 true 即可。

测试 ESNI

配置完成后(可能需要重新启动浏览器),可以访问 https://www.cloudflare.com/ssl/encrypted-sni/ ,按下 "Check My Browser" 按钮,就可以测试自己是否开启了 ESNI 了。

Result of ESNI enabled

esnicheck 提供了一些支持 ESNI 的网站列表,也可以用来测试某个网站是否支持 ESNI。

常见问题

Cloudflare 提醒我 ESNI 未启用!

可能是你的 DNS over HTTPS 并没有生效,Firefox 还在使用普通的 DNS 请求方式。这种情况下 ECH 无法工作。

你可以尝试按照 Mozilla Wiki 的指示,在 about:config 中将 network.trr.mode设置为 3,即只使用 TRR(也就是我们的 DNS over HTTPS),强制 Firefox 使用 DoH,这样就能确保使用 ESNI 了。

我按上条开启了 DoH only,但有的网站无法访问了!

主要有两种情况:

  • Firefox 默认不会接受通过 DoH 解析得来的本地地址结果[1] [2]。对于这种情况,在 about:config 中将 network.trr.allow-rfc1918 设置为 true 即可。
  • 如果你使用默认的 Cloudflare DNS,并且访问的是 archive.is 的话:包括 archive.is 在内的少数网站要求对其服务器 IP 进行查询的客户端支持 ECS 拓展,以提供最优化的解析结果,而 Cloudflare DNS 出于隐私原因故意不支持 ECS。两边无法调和,于是使用 Cloudflare DNS 的用户就无法访问这些站点了(除非更换 DNS 服务器)。

  1. https://searchfox.org/mozilla-central/source/netwerk/dns/DNSPacket.cpp#569 ↩︎

  2. https://searchfox.org/mozilla-central/source/netwerk/dns/DNSPacket.cpp#864 ↩︎

评论



LIKE