简介自从HTTP从1.1升级到2之后,一切都变了。虽然HTTP2没有强制要求必须使用加密协议进行传输,但是行业标准,包括所有流行的浏览器,都只在HTTPS的情况下支持HTTP2协议。那么如何给HTTPS增加HTTP2协议支持呢?今天这篇文章就和大家聊一聊SSL/TLS协议的扩展NPN和ALPN。SSL/TLS协议SSL(SecureSocketLayer)是Netscape于1994年设计的一套协议,1995年发布了3.0版本。TLS(TransportLayerSecurity)是IETF在SSL3.0的基础上设计的协议,它实际上相当于SSL的后续版本。SSL/TLS是一种密码通信框架,是世界上使用最广泛的密码通信方式。TLS主要分为两层。最底层是TLS记录协议,主要负责使用对称密码对消息进行加密。上层是TLS握手协议,主要分为四部分:握手协议、密码规范变更协议、应用数据协议。其中最重要的是握手协议,通过客户端和服务器端的交互,共享一些必要的信息,生成共享密钥和交互证书。接下来我们一步步介绍每一步的含义:clienthello客户端向服务端发送一条clienthello消息,包括以下内容:可用版本号当前时间客户端随机数SessionID可用密码套件列表可用压缩方法列表我们前面提到TLS其实是一套加密框架,其中的部分组件是可以更换的。可用的版本号、可用的密码套件列表、可用的压缩方法列表,就是向服务器询问对方支持哪些服务。客户端随机数是客户端生成的随机数,用于生成对称密钥。serverhello服务器收到clienthello消息后,会向client返回一条serverhello消息,包括以下内容:使用的版本号,当前时间,服务器的随机数,sessionID使用的密码套件、使用的压缩方法和使用的版本号。使用的密码套件,使用的压缩方法就是步骤1的答案。服务器nonce是服务器产生的随机数,用于生成对称密钥。可选步骤:certificate服务器发送自己的证书列表,因为证书可能是分层的,所以除了处理服务器自己的证书外,还需要发送为服务器签名的证书。客户端将验证服务器的证书。如果匿名通信则不需要证书。可选步骤:ServerKeyExchange如果第三步证书信息不足,可以发送ServerKeyExchange建立加密通道。ServerKeyExchange的内容可能包含两种形式:如果选择RSA协议,则传递RSA构造公钥密码的参数(E,N)。回想一下RSA中构造公钥的公式:$ciphertext=plaintext^E\mod\N$,只要知道E和N,那么RSA的公钥就知道了,E和N这两个数都经过这里。具体可以参考RSA算法详解。如果选择Diff-Hellman密钥交换协议,则传递密钥交换的参数。具体可以参考更安全的密钥生成方法Diffie-Hellman可选步骤:CertificateRequest如果是在限制访问的环境中,比如fabric,服务器还需要向客户端索要证书。如果不需要客户端身份验证,则不需要此步骤。serverhellodone服务器发送serverhellodone消息告诉客户端自己的消息结束了。可选步骤:证书响应步骤5,客户端将客户端证书发送给服务端ClientKeyExchange或者有两种情况:如果是公钥或者RSA方式,客户端会根据客户端生成的随机数和服务器随机数,生成初步主密码,用公钥加密后传回服务器。如果使用Diff-Hellman密钥交换协议,客户端发送其一方需要公开的值以生成Diff-Hellman密钥。具体可以参考更安全的密钥生成方法Diffie-Hellman,这样服务器就可以根据这个公开值计算出初步的主密码。可选步骤:CertificateVerify客户端向服务器证明它是客户端证书的持有者。ChangeCipherSpec(准备切换密码)ChangeCipherSpec是密码规范更改协议的消息,表示后面的消息将使用之前协商好的密钥进行加密。finished(握手协议结束)客户端告诉服务器握手协议结束。ChangeCipherSpec(准备切换密码)服务器告诉客户端它要切换密码。finished(握手协议结束)服务器告诉客户端握手协议结束。切换到应用数据协议后,服务器和客户端以加密方式进行通信。我们在NPN和ALPN上面引入SSL/TLS协议的时候,最后一步就是切换到应用数据协议,那么client怎么和server讨论协商使用哪种应用数据协议呢?是否使用HTTP1.1?还是HTTP2?或者SPDY呢?这里使用了TLS扩展协议。NPN(NextProtocolNegotiation)和ALPN(ApplicationLayerProtocolNegotiation)是TLS的两个扩展协议。它们主要在TLS中用于协商客户端和服务器应该使用什么应用程序数据协议进行通信。其中NPN是SPDY使用的扩展,ALPN是HTTP2使用的扩展。它们之间有什么区别?与NPN相比,ALPN在clienthellomessage中列出了client支持的应用层协议,server只需要选择自己支持的协议即可。比NPN少了一个交互步骤,所以推荐使用ALPN协议。下面是具体的交互流程图:交互示例下面以ALPN为例,说明一下具体的交互过程。首先,客户端发送一条“ClientHello”消息:HandshakeType:ClientHello(1)Length:141Version:TLS1.2(0x0303)Random:dd67b5943e5efd0740519f38071008b59efbd68ab3114587...SessionIDLength:0CipherSuitesLength:10CipherSuites(5套件)压缩方法长度:1压缩方法(1种方法)扩展长度:90[省略其他扩展]扩展:application_layer_protocol_negotiation(len=14)类型:application_layer_protocol_negotiation(16)长度:14ALPN扩展长度:12ALPN协议ALPN字符串长度:2ALPNNextProtocol:h2ALPNstringlength:8ALPNNextProtocol:http/1.1在clienthellomessage中可以看到Extension字段中使用了ALPN,列出了两个可以使用的ALPNProtocol:h2和http/1.1.对应的“serverhello”消息会选择出具体使用的ALPNprotocol如下:HandshakeType:ServerHello(2)Length:94Version:TLS1.2(0x0303)Random:44e447964d7e8a7d3b404c4748423f02345241dcc9c7e332...SessionIDLength:32SessionID:7667476d1d698d0a90caa1d9a449be814b89a0b52f470e2d...密码套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xc02f)压缩方法:空(0)扩展长度:22[省略其他扩展]扩展:application_layer_protocol_negotiation(len=5)类型:application_layer_protocol_negotiation(16)长度:5ALPN扩展长度:3ALPN协议ALPNstringlength:2ALPNNextProtocol:h2如上图,server端选择h2,最后client和server结束TLS握手时,会选择使用HTTP2作为后续的应用层数据协议。综上所述,NPN和ALPN都是TLS的扩展。相比之下,ALPN更容易使用。本文已收录于http://www.flydean.com/08-ssl-tls-npn-alpn/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!
