HTTPS那些协议:TLS,SSL,SNI,ALPN,NPN
如今 HTTPS 已经普遍应⽤了,在带来安全性的同时也确实给 Web 引⼊了更多复杂的概念。
这其中就包括⼀系列从没见过的⽹络协议。现在 Harttle 从 HTTPS 的原理出发,尝试以最通
俗的⽅式来解读 HTTPS 涉及的这些协议。
HTTPS 概要
HTTPS 是建⽴在安全通信之上的 HTTP,使⽤传输层加密(TLS 或 SSL)的⼿段。其⽬的是保
护⽤户隐私(⽐如防⽌经过的⽹络节点截获 HTTP 内容)和数据完整性(⽐如运营商强插⼴告),
就是端到端加密来防⽌中间⼈攻击。
TLS/SSL 是在传输层之上应⽤层之下的协议,因此 HTTP 协议的内容不受影响。这些加密采
⽤⾮对称加密算法因此需要⼀个官⽅来发布公钥,这就是密钥基础设施(CA)。因此各浏览器
会内置⼀些 CA 的根证书,这些 CA 可以进⼀步授权其他的域名,这样你的浏览器就可以对
正在访问的域名进⾏⾝份认证。
如果你要⾃⼰的服务也⽀持 HTTPS 去 CA 注册⾃⼰的域名就可以了。有⼀些免费的 CA ⽐
如 GoDaddy, Let’s Encrypt, CloudFlare 等可以选择。
HTTPS 交互⽰例
TCP。前三⾏完成⼀对 SYN/ACK(即俗称的三次握⼿),⾄此 TCP 连接已经成功建
⽴。
TLS。4-5 ⾏开始了 TLS 握⼿,建⽴这个加密层。
TLS 有众多扩展协议⽐如 SNI,NPN,ALPN 等(见下⽂),就发⽣在 TLS 的
ClientHello 和 ServerHello 阶段。
TLS/SSL
TLS 的前⾝是 SSL,TCP/IP 协议栈中运⾏在 TCP 之上,⽤来交换密钥并形成⼀个加密层
(Record Layer)。 TLS 是 HTTPS 的核⼼协议,HTTPS 交互与 HTTP 交互的主要区别就在
这⼀层:
开始传输密⽂前需要进⾏互换密钥、验证服务器证书等准备⼯作,因此 TLS 也存在握⼿阶段,主要步骤为:客户端发送 ClientHello,服务器发送 ServerHello,服务器继续发送Certificate,然后互相发送 KeyExchange 消息,最后发送 ChangeCipherSpec 来通知对⽅后续都是密⽂。具体交互和协议字段请参考 RFC 5246(TLSv1.2)和 RFC 6176(TLSv2.0)。
TLS 作为 TCP/IP 协议栈中的加密协议有⼴泛的⽤途,为⽀持通⽤机制的协议扩展,定义了RFC 4366 - TLS Extensions。 TLS 先后被邮件服务、Web 服务、FTP 等采⽤,这⾥有⼀个扩展协议列表。
本⽂关注其中 Web 服务(HTTPS)相关的扩展,如 SNI, NPN, ALPN。这些协议通过扩展 TLS 的 ClientHello/ServerHello 消息为 TLS 增加新的功能。为此我们先看⼀下 ClientHello 消息的结构(ServerHello 类似):
1. struct {
2. ProtocolVersion client_version;
3. Random random;
4. SessionID session_id;
5. CipherSuite cipher_suites<2..2^16-2>;
6. CompressionMethod compression_methods<1..2^8-1>;
7. select (extensions_present) {
8. case false:
9. struct {};
10. case true:
11. Extension extensions<0..2^16-1>;
12. };
13. } ClientHello;
注意最后⼀个字段,最多可以有 65536 个 Extension,其中 Extension 定义为⼀个两字节的ExtensionType 以及对应的不透明数据。下⽂的 SNI,NPN,ALPN 都是其中之⼀。
SNI
SNI(Server Name Indication)指定了 TLS 握⼿时要连接的主机名。 SNI 协议是为了⽀持同⼀个 IP(和端⼝)⽀持多个域名。
因为在 TLS 握⼿期间服务器需要发送证书(Certificate)给客户端,为此需要知道客户请求的域名(因为不同域名的证书可能是不⼀样的)。这时有同学要问了,要连接的主机名不就是发起HTTP 时的 Host 么!这是对 HTTPS 机制的误解,TLS Handshake 发⽣时 HTTP 交互还没开始,⾃然 HTTP 头部还没到达服务器。SNI 协议就定义在 RFC 6066 中:
1. struct {
2. NameType name_type;
3. select (name_type) {
4. case host_name: HostName;
5. } name;
6. } ServerName;
7.
8. enum {
9. host_name(0), (255)
10. } NameType;
11.
12. opaque HostName<1..2^16-1>;
13. struct {
14. ServerName server_name_list<1..2^16-1>
15. } ServerNameList;
我们看本⽂刚开始的例⼦,第4⾏发往 github 的 ClientHello 中的 SNI Extension 字段:
1. Extension Header || Extension Payload (SNI)
2. ---------------------------------------------------------------------------------------------------
3. ExtensionType Length || PayloadLength Type ServerLength ServerName
4. ---------------------------------------------------------------------------------------------------
5. 00 00 00 0f 00 0d 00 00 0a 67 69 74 68 75 62 2e 63 6f 6d
6. sni(0) 15 || 13 host_name 10 github
ALPN/NPN
ALPN(Application-Layer Protocol Negotiation)也是 TLS 层的扩展,⽤于协商应⽤层使⽤的协议。它的前⾝是 NPN,最初⽤于⽀持 Google SPDY 协议(现已标准化为 HTTP/2)。 TLS 客户端和服务器版本的问题,导致 SPDY->HTTP/2 和 NPN -> ALPN 的切换过程引发了不少阵痛:
The day Google Chrome disables HTTP/2
从启⽤ HTTP/2 导致⽹站⽆法访问说起
因此以标准先⾏的⽅式来推进 Web 基础设施已成为今⽇ Web 平台的共识。这⾥我们不提那些仍然在进⾏作坊式⽣产的(类)浏览器⼚商,任何阻挡 Web 平台发展的实现(甚⾄标准,试看XHTML, OSI…)迟早会被淘汰。
⾔归正传,ALPN 定义在 RFC 7301 - Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension,
1. enum {
ssl协议全称2. application_layer_protocol_negotiation(16), (65535)
3. } ExtensionType;
4.
5. opaque ProtocolName<1..2^8-1>;
6.
7. struct {
8. ProtocolName protocol_name_list<2..2^16-1>
9. } ProtocolNameList;
我们看本⽂刚开始的例⼦,第4⾏发往 github 的 ClientHello 中的 ALPN Extension 字段:
1. Extension Header || Extention Payload (ALPN)
2. ---------------------------------------------------------------------------------------------------
3. ExtensionType Length || PayloadLength StringLength Protocol StringLength Protocol
4. ---------------------------------------------------------------------------------------------------
5. 00 10 00 0e 00 0c 02 68 32 08 68 74 74 70 2f 31 2e 31
6. alpn(16) 14 || 12 2 h2 8 http/1.1
Extention 的消息体包含多个字符串(protocol_name_list),表⽰客户端⽀持的所有应⽤层协议。上⾯的例⼦中有 h2 和 http/1.1 两个,⽀持 SPDY 的客户端这⾥会多⼀个 spdy/2。服务器给出的 ServerHello 中需要选择其中之⼀,本⽂的例⼦中 ServerHello 的 ALPN 字段为:
1. 00 10 00 0b 00 09 08 68 74 74 70 2f 31 2e 31
2. h t t p / 1 . 1
这样 Server 和 Client 就利⽤ ALPN 协议达成了共识,将会在握⼿结束后使⽤ HTTP/1.1 协议进⾏通信。
参考和致谢
从 HTTPS 的关键⼀层 TLS 开始,介绍了⼀个典型的 HTTPS 交互过程。结合抓包给出的字节序列,依次介绍了 TLS、SNI、ALPN 等协议原理和主要内容。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论