title: TLS/ESNI/ECH/DoT/DoH/JA3 - 谈谈 HTTPS 网络下浏览体验安全性的最后缝隙 layout: post thread: 281 date: 2022-10-09 author: Joe Jiang categories: Document tags: [TLS, ESNI, ECH, DoT, DoH, JA3, HTTPS, 网络安全, 加密, DNS] excerpt: 有了 HTTPS 我们的网络访问就完美无缺了吗?TLS 在握手 Client Hello 阶段的数据包,包含客户端想访问的地址等信息,而这些信息是明文传输的,这使得第三方可以通过监听等手段知道你想访问哪些网址。本文会按照加密方式的加工流程倒序介绍,先介绍关于 TLS 握手阶段的 SNI 相关信息,再谈谈 DNS 安全层,最后会介绍下 TLS 握手指纹…… toc: true header: image: ../assets/in-post/2022-10-09-Secure-Your-Browsing-Experience-with-More-Encrypted-Tools-0.png
TLS,全称 Transport Layer Security,安全传输层协议,前身为 SSL (Secure Socket Layer,安全套接层),位于 TCP 与应用层之间。HTTPS 相对于 HTTP 来说,协议本身并未改变,而是在 TCP 与 HTTP 间添加了一层 TLS 用作加密以保证信息安全。
从 TLS 的角度说起,它希望解决网络流量明文传输存在的几类风险:窃听、篡改、伪造,这里摘录 https://zinglix.xyz/2019/05/07/tls-handshake/ 对 TLS 解决三类风险的一段总结:
但这么做就完美了吗?TLS 在握手 Client Hello 阶段的数据包,包含客户端想访问的地址等信息,而这些信息是明文传输的,这使得第三方可以通过监听等手段知道你想访问哪些网址。
本文会按照加密方式的加工流程倒序介绍,先介绍关于 TLS 握手阶段的 SNI 相关信息,再谈谈 DNS 安全层,最后会介绍下 TLS 握手指纹,通过本文,你或许可以对以下信息有更深入的了解:
本文基于个人理解与学习进行整理,如有不准确的地方还望指出,所参考的资料均在文末参考一章中罗列。本文在最后一章节对全文整理的内容进行了概况总结,已经有相关基础的同学可以直接跳转查看。
当多个网站托管在一台服务器上并共享一个 IP 地址,并且每个网站都有自己的 SSL 证书,在客户端设备尝试安全地连接到其中一个网站时,服务器可能不知道显示哪个 SSL 证书。这是因为 SSL/TLS 握手发生在客户端设备通过 HTTP 指示连接到某个网站之前。
SNI (Server Name Indication,服务器名称指示) 是为了解决一个服务器使用多个域名和证书的 TLS扩展,主要解决一台服务器只能使用一个证书的缺点。SNI 是 TLS 协议(以前称为 SSL 协议)的扩展,该协议在 HTTPS 中使用。它包含在 TLS/SSL 握手流程中,以确保客户端设备能够看到他们尝试访问的网站的正确 SSL 证书。该扩展使得可以在 TLS 握手期间指定网站的主机名或域名,而不是在握手之后打开 HTTP 连接时指定。
开启 SNI 后,允许客户端在发起 SSL 握手请求时就提交请求的域名信息,负载均衡收到 SSL 请求后,会根据域名去查找证书,如果找到域名对应的证书,则返回该证书;如果没有找到域名对应的证书,则返回缺省证书。负载均衡在配置 HTTPS 监听器支持此功能,即支持绑定多个证书。
TLS 的做法,是在 TLS 握手第一阶段 ClientHello (客户端问候)的报文中就添加包含主机名。SNI 在 TLSv1.2 开始得到支持。从 OpenSSL 0.9.8 版本开始支持。
SNI 将域名添加到TLS握手过程,以便 TLS 程序到达正确的域名并接收正确的 SSL 证书,从而使其余 TLS 握手能够正常进行。
虽然 TLS 能够加密整个通信过程,但是在协商的过程中依旧有很多隐私敏感的参数不得不以明文方式传输,其中最为重要且棘手的就是将要访问的域名,即 SNI。
加密 SNI (Encrypted Server Name Indication, ESNI) 通过加密客户端问候的 SNI 部分来添加到 SNI 扩展,这可以防止任何在客户端和服务器之间窥探的人看到客户端正在请求哪个证书,从而进一步保护客户端。Cloudflare 和 Mozilla Firefox 于 2018 年推出了对 ESNI 的支持。
ESNI 可以确保正在侦听的第三方无法监视 TLS 握手流程并以此确定用户正在访问哪些网站。
ESNI 通过公钥加密客户端问候消息的 SNI 部分(仅此部分),来保护 SNI 的私密性。加密仅在通信双方(在此情况下为客户端和服务器)都有用于加密和解密信息的密钥时才起作用,就像两个人只有在都有储物柜密钥时才能使用同一储物柜一样。
由于客户端问候消息是在客户端和服务器协商 TLS 加密密钥之前发送的,因此 ESNI 加密密钥必须以其他方式进行传输。
Web 服务器可以在其 DNS 记录中添加一个公钥,这样,当客户端查找正确的服务器地址时,同时能找到该服务器的公钥。这有点像将房门钥匙放在屋外的密码箱中,以便访客可以安全地进入房屋。然后,客户端即可使用公钥来加密 SNI 记录,以便只有特定的服务器才能解密它。
ESNI 存在问题。首先是密钥的分发,Cloudflare 在部署时每个小时都会轮换密钥,这样可以降低密钥泄露带来的损失,但是 DNS 有缓存的机制,客户端很可能获得的是过时的密钥,此时客户端就无法用 ESNI 继续进行连接。其次是对网站的 DNS 请求可能返回有几个 IP 地址,每个地址分别代表了不同的 CDN 服务器,然而 ESNI 的 TXT 记录只有一个,可能会将该密钥发送给了错误的服务器导致握手失败。
自从 ESNI 规范草案在 IETF 上发布以来,分析表明仅仅加密 SNI 扩展提供的保护是不完整的。为了解决 ESNI 的问题,最近发布的规范不再只加密 SNI 扩展,而是对整个 Client Hello 信息进行加密,因此标准名称从 ESNI 也变成了 ECH。
ECH(Encrypted Client Hello,也称加密客户端问候)出现的目标就是就是为了克服 ESNI 的缺陷,同时也正如其名,ECH 有着更大的野心,不单单加密 SNI,而是要加密整个 Client Hello。
ECH 同样采用 DoH (后文会进行详细介绍,此处可暂时理解成 DNS 安全层的一种实现)进行密钥的分发,但是在分发过程上进行了改进。如果解密失败,ESNI 服务器会中止连接,而 ECH 服务器会提供给客户端一个公钥供客户端重试连接,以期可以完成握手。
ECH 协议实际上涉及两个 ClientHello 消息:ClientHelloOuter,它像往常一样以明文形式发送;ClientHelloInner,它被加密并作为 ClientHelloOuter 的扩展发送。服务器仅使用其中一个 ClientHello 完成握手:如果解密成功,则继续使用 ClientHelloInner;否则,它只使用 ClientHelloOuter。
ClientHelloInner 由客户端想要用于连接的握手参数组成。这包括它想要访问的源服务器的 SNI、ALPN 列表等。ClientHelloOuter 虽然也是一个成熟的 ClientHello 消息,但不用于预期的连接。相反,握手是由 ECH 服务提供者完成,在无法完成解密的情况下,它会向客户端发出信号,表明由于解密失败而无法到达其预期的目的地。此时,服务提供商还会发送正确的 ECH 公钥,客户端可以使用该公钥重试握手,从而“更正”客户端的配置。
DNS 是互联网的电话簿;DNS 解析器将人类可读的域名转换为机器可读的 IP 地址。默认情况下,DNS 查询和响应以明文形式(通过 UDP)发送,这意味着它们可以被网络、ISP 或任何能够监视传输的人读取。即使网站使用 HTTPS,也会显示导航到该网站所需的 DNS 查询。
这种隐私上的欠缺对安全有着巨大影响,如果 DNS 查询不是私密的,则攻击者可以轻松跟踪用户的Web 浏览行为。
基于 TLS 的 DNS(DNS over TLS,简称 DoT)是加密 DNS 查询以确保其安全和私密的一项标准。DoT 使用安全协议 TLS,这与 HTTPS 网站用来加密和认证通信的协议相同。DoT 在用于 DNS 查询的用户数据报协议(TCP)的基础上添加了 TLS 加密,这可以确保 DNS 请求和响应不会被在途攻击篡改或伪造。
与 DoT 采用在 TCP 协议上处理稍有不同的是,还存在另一个在 UDP 协议上加密的标准,DNS over DTLS,即基于 UDP 的 DNS TLS 加密协议标准。
基于 HTTPS 的 DNS 或 DoH 是 DoT 的替代标准。使用 DoH 时,DNS 查询和响应会得到加密,但它们是通过 HTTP 或 HTTP/2 协议发送,而不是直接通过 UDP 发送。与 DoT 一样,DoH 也能确保攻击者无法伪造或篡改 DNS 流量。从网络管理员角度来看,DoH 流量表现为与其他 HTTPS 流量一样,如普通用户与网站和 Web 应用进行的交互。
这两项标准都是单独开发的,并且各有各的 RFC 文档,但 DoT 和 DoH 之间最重要的区别是它们使用的端口。DoT 仅使用端口 853,DoH 则使用端口 443,后者也是所有其他 HTTPS 流量使用的端口。
由于 DoT 具有专用端口,因此即使请求和响应本身都已加密,具有网络可见性的任何人都发现来回的 DoT 流量。DoH 则相反,DNS 查询和响应伪装在其他 HTTPS 流量中,因为它们都是从同一端口进出的。
除了上文提到的几种标准外,想要达到 DNS 请求加密的目的,我们仍然有多种其他实现方式:
TLS 握手指纹又叫 SSL 指纹,或者 JA3 指纹,是根据客户端向服务端发送的 Client Hello 信息中部分字段计算得出的 hash 值信息。
此外,在 TLS 握手中还有服务端响应的 Server Hello,这类信息也有特征,根据类似的思路可以得到 JA3S 指纹。又由于服务端会根据不同的 Client Hello 响应不同的 Server Hello,根据这个又可以得到 JARM 指纹。
由于 TLS/SSL 协商以明文形式传输,因此可以使用 SSL Client Hello 数据包中的详细信息对客户端应用程序进行指纹识别。JA3 从 Client Hello 数据包中的以下字段收集十进制字节值:
SSLVersion,Cipher,SSLExtension,EllipticCurve,EllipticCurvePointFormat
// 分别代表 TLS/SSL 版本,可接受的密码,扩展列表,椭圆曲线,椭圆曲线格式
然后按顺序将这些值连接在一起,使用,
分隔每个字段,使用-
分隔每个字段中的每个值,如果没有 TLS/SSL 扩展则留空,最后对这些字符串进行 MD5 散列以生成易于使用和共享的32个字符指纹,这就是 JA3 客户端指纹。
对于服务端来说,同一台服务器会根据Client Hello
消息及其内容以不同的方式创建其Server Hello
消息。因此,这里不能像客户端和JA3那样,仅仅根据服务器的Hello消息来对其进行指纹识别。
JA3S是用于 SSL/TLS 通信的服务器端的JA3, 服务器对特定客户机响应的指纹。
JA3S 使用以下字段生成指纹:SSLVersion,Cipher,SSLExtension
,在应用中,需要通过结合JA3 + JA3S
对客户端与其服务器之间的整个加密协商进行指纹识别。因为服务器会对不同的客户端做出不同的响应,但对同一个客户端的响应总是相同的。
通过以上两类指纹可以来标记SSL握手中客户端、服务端特征。关于 JA3/JA3S 的详细定义可参见 https://github.com/salesforce/ja3
TLS Server 根据 TLS Client Hello 中参数的不同,返回不同的 Server Hello 数据包。而 Client Hello 的参数可以人为指定修改,因此通过发送多个精心构造(比如指定不同的TLS版本、支持套件等来试探服务端响应情况)的 Client Hello 获取其对应的特殊 Server Hello(包含服务器返回的加密套件、服务器返回选择使用的 TLS 协议版本、TLS 扩展 ALPN 协议信息、TLS 扩展列表等信息),最终形成 JARM 指纹信息,来标记服务器的特征。具体能够产生影响的参数包括但不限于:
与 JA3/JA3S 是在流量被动监听中得到的方式不同的是,JARM 是通过主动探测的方式得到。
详细定义可参见 https://github.com/salesforce/jarm
两者均是 TLS 握手信息(版本、支持套件)的简化表现形式。所以 JA3/JA3S 可以用来标记特质的客户端、服务端所产生的流量。
JA3S 指纹则根据客户端的不同环境(系统版本等)有变化。JARM 则可以用来威胁狩猎。
TLS 协议已经成为互联网上最流行的协议,以确保网络通信免受干扰和窃听。但在握手阶段,由于 SNI 信息是明文传输,这导致了客户端的访问网址等信息容易被窃听。
ESNI 是保护网络隐秘性和安全性的重要步骤,但其他新协议和功能也很重要。设计 Internet 时并未考虑安全性和隐私性,因此,在访问网站的过程中有很多步骤都是非私密的。但是,有各种新协议都有助于对每个步骤进行加密,使之免受恶意攻击者的攻击。
域名系统或 DNS 将人类可读的网站地址(如 www.example.com)与字母数字 IP 地址进行匹配。这就像在所有人都使用的大型地址簿中查找某人的地址一样。但是,普通的 DNS 未加密,这意味着任何人都可以看到某人正在查找哪个地址,并且任何人都可以伪装成地址簿。即使安装了 ESNI,攻击者仍然可以查看用户正在查询的 DNS 记录,并确定他们正在访问哪些网站。
其他三个附加协议旨在弥补这些空白:
基于 TLS 的 DNS 和基于 HTTPS 的 DNS 都在做同样的事情:使用 TLS 加密来加密 DNS 查询。它们之间的主要区别在于使用网络的哪个层以及使用哪个网络端口。DNSSEC 确认 DNS 记录真实并来自合法的 DNS 服务器,而非来自冒充 DNS 服务器的攻击者(例如,发生 DNS 缓存中毒攻击时)。
说完浏览私密性保证,我们再来看看对恶意流量的分析检测。由于网络管理人员可以识别和阻止自定义协议,很多恶意工具已经转向使用现有协议,TLS的流行为这些恶意工具提供了一个很好的选择,使用TLS协议的恶意工具可以将其流量隐藏在大量web浏览器和其他TLS的合法覆盖流量中以逃避检测。
从 TLS 连接(Client hello 阶段)中提取特定的一些字段生成指纹,通过分析恶意工具和常规工具在协议信息上的区别,可以进一步分析或者研究,通过连接模式或时间特征来检测恶意流量。