Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

TLS 的协议协商机制

  TLS 虽然是基于 TCP 的,但它依然是传输层的协议。就像 TCP 建立之后一样,除非是一个提供固定服务的服务器,否则根本不知道客户端建立这个连接是想要干嘛。服务器可能会把自己支持的应用层协议逐个尝试解析,失败后再 fallback 到下一个协议,这显然是不科学的。
  TCP 就是缺少这么一套协商机制,所以一些服务器在处理一个端口同时支持 TCP 和 TLS 或者更多协议时就需要去不断尝试,然后 fallback。TLS 同样作为传输层协议,它的解决方案就是在握手过程中客户端告诉服务器自己所支持的所有协议,服务器根据自己所支持的协议,选择最适合的告诉客户端。在 TLS 建立完成后客户端使用这个协商后的协议去请求服务器,服务器就不用再把所有自己支持的协议一个个尝试了。
  TLS 的这套机制本来叫做 NPN(Next Protocol Negotiation),字面意思也很好理解,就是协商一下 TLS 建立之后下一个要使用的协议是什么。后来规范化后就改为 ALPN(Application-Layer Protocol Negotiation),同样可以字面理解为应用层协议协商。
  目前 node 是支持的,所以我们很容易写一个测试程序 var fs = require('fs'); var tls = require('tls'); tls.createServer({ key: fs.readFileSync("localhost.key"), cert: fs.readFileSync("localhost.crt"), ALPNProtocols: [ 'h2', 'http/1.1' ], NPNProtocols: [ 'h2', 'http/1.1' ] }, connection => { console.log('Server:', connection.alpnProtocol); }).listen(8081); process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; var connection = tls.connect({ port: 8081, ALPNProtocols: [ 'spdy', 'http/1.1' ], NPNProtocols: [ 'spdy', 'http/1.1' ] }, () => { console.log('Client:', connection.alpnProtocol); });   这里我把 ALPN 和 NPN 都写上了,有些比较古老的程序可能只支持 NPN,所以如果只写标准的 ALPN 会有设备不支持。这个测试程序中客户端表示自己支持 spdy 和 http/1.1,而服务器端支持的是 h2(注意不是 http 2 的写法不是 http/2.0,而是 h2(为啥我突然想到了 h5))。于是服务器端就会选择一个大家都支持的 http/1.1,所以执行这个程序会得到这样的结果。

  如果我们用 Chrome 之类的浏览器直接去访问这个 8081 端口,服务器就会使用 h2,因为浏览器会告诉服务器自己支持 h2。

  其实我并没有看过 openssl 的源码,只是最近在搞 h2 于是跑出来装个 B。
网名:
3.80.32.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^