本文发布于2020-06-13,由于加密技术日新月异,可能本文在介绍某些技术时已不是最新版本,仅供参考,本文部分内容来自Cloudflare Blog:https://blog.cloudflare.com/zh/esni-zh/https://blog.cloudflare.com/zh/encrypted-sni-zh/,Firefox启用ESNI参考https://tecrobe.github.io/blog/post/doh-and-esni/,转载请同时带上作者名称。

前言

虽然TLS已经发展到了1.3版本了,可是一个短板至今仍未完全补齐。服务器为了区分您要访问的不同域名,根据不同域名返回不同的证书,为此TLS引入了一个扩展:SNI(详情看这)您的ISP(互联网服务提供商)、网络中的设备可能都会看到您所访问的网站的域名。而G|F|W中也使用了SNI阻断(根据SNI来屏蔽网站)这一技术。因此,ESNI就应运而生了。

为什么使用SNI

从根本上说,SNI的存在是为了允许您在一个IP地址上托管多个加密的网站。早期的浏览器没有包含SNI扩展。因此,当发出建立HTTPS连接的请求时,web服务器没有太多信息来继续进行,并且只能回收web服务器正在监听的每个IP地址的单个SSL证书。

这个问题的一个解决方案是,创建具有多个主题备用名称(SANs)的证书。这些证书将加密多个域的流量,这些域都可以托管在同一个IP上。Cloudflare就是这样处理来自不支持SNI的旧浏览器的HTTPS流量的。然而,我们限制这一功能仅供我们的付费客户使用,这和SANs不是一个很好的解决方案的原因一样:它们是一种黑客攻击,管理起来很麻烦,如果包含了太多域,可能会降低性能。

最具弹性的解决方案是SNI。我认为的一个合理的类比是,把它想象成一个邮政信封。信封里的东西是受保护的,邮差是看不到的。而信封外面是街道地址,邮差根据它来将信封送到正确的建筑位置。在互联网上,web服务器的IP地址就相当于街道地址。

然而,如果你住在一个多单元的大楼里,仅仅通过一个街道地址是不足以把信封送到正确的收件人手中的。为了补充街道地址,你要写上一个公寓号码或收件人的名字。这相当于SNI。如果web服务器承载多个域,SNI可以确保将请求路由到正确的站点,以便返回正确的SSL证书,从而能够加密和解密任何内容。

ESNI检测地址

https://www.cloudflare.com/ssl/encrypted-sni/

可以看看你的浏览器是否支持ESNI

ESNI原理

先从SNI讲起2020-6-14 11-55-57.png

比如我访问GitHub时浏览器会在Client Hello时将当前要访问的网站的域名以明文方式放在TLS扩展中一起传输。

而支持ESNI的这不会有这一部分。ESNI的原理就是加密SNI的密钥与DNS记录一同分发,有的人会想DNS不也是明文传输的吗?但事实上在现在DoH,DoT的普及,使得这已不是个问题。

Firefox 启用ESNI的方法

首选项 - 常规 - 网络设置;启用基于HTTPS的DNS

地址栏输入about:config,搜索network.security.esni.enabled,将值设为True,完成。

访问前文提到的检测ESNI的网址,选择Run the test,看到Encrypted SNI打钩即可。