怎么创建卡密网站,17.zwd一起做网站池尾站,多多视频,网站一般几年目录 1. 概述2. alpn协议的简要理解2.1 ssl的握手过程2.2 通过抓包看一下alpn的细节3. nginx源码分析3.1 给ssl上下文设置alpn回调3.2 连接初始化3.3 处理alpn协议回调3.4 握手完成,启用http协议4.4 总结阅读姊妹篇:深入理解nginx的https alpn机制
1. 概述 应用层协议协商(… 目录 1. 概述2. alpn协议的简要理解2.1 ssl的握手过程 2.2 通过抓包看一下alpn的细节3. nginx源码分析3.1 给ssl上下文设置alpn回调3.2 连接初始化3.3 处理alpn协议回调3.4 握手完成,启用http协议 4.4 总结 阅读姊妹篇:深入理解nginx的https alpn机制
1. 概述 应用层协议协商(Application-Layer Protocol Negotiation,简称ALPN)是一个传输层安全协议(TLS) 的扩展, ALPN 使得应用层可以协商在安全连接层之上使用什么协议, 避免了额外的往返通讯, 并且独立于应用层协议。 ALPN 用于 HTTP/2 连接, 和HTTP/1.x 相比, HTTP 2的使用增强了网页的压缩率减少了网络延时。 ALPN 和 HTTP/2 协议是伴随着 Google 开发 SPDY 协议出现的。 nginx能够在一个ssl监听端口上同时提供http/1.1和http/2的服务,而http/2协议规定是必须基于tls安全通信协议的,因此,nginx在ssl握手过程中实现了ALPN的协议协商功能,能够自动完成和客户端的协议协商,从而根据客户端的协议支持能力提供http/1.1或者http/2的服务。 本文基于nginx,对alpn的实现原理进行深入的分析。
2. alpn协议的简要理解
2.1 ssl的握手过程 由上图可以看到,alpn的协商过程是在ssl握手的最早的两个阶段,即ClientHello和ServerHello中完成的,通过将应用层协议协商信息附加到ClientHello和ServerHello报文中完成的交互。
2.2 通过抓包看一下alpn的细节 下面通过TLS v1.2握手协议来查看alpn的细节,对于TLS v1.3协议,在ServerHello响应的时候由于alpn部分的信息被加密,所以查看起来比较会麻烦。抓包通过wireshark来实现,通过以下命令来模拟http2的请求:
curl --http2 "https://www.test.com" -kv下到的报文如下: ClientHello报文: ServerHello报文: 在ClientHello报文中可以看到application_layer_protocol_negotiation的信息,表明了客户端可以同时支持h2和http/1.1,而在ServerHello报文中也可以看到application_layer_protocol_negotiation的信息,表明服务器选择了h2协议作为应用层协议。
3. nginx源码分析
3.1 给ssl上下文设置alpn回调 nginx在启动的时候,ngx_http_ssl_module模块在ngx_http_ssl_merge_srv_conf的时候,有以下这段代码对ssl的上下文进行初始化: /* 创建ssl上下文 */if (ngx_ssl_create(conf-ssl, conf-protocols, conf) != NGX_OK) {return NGX_CONF_ERROR;}/* 注册用于ssl上下文资源回收的回调函数cln = ngx_pool_cleanup_add(cf-pool, 0);if (cln == NULL) {ngx_ssl_cleanup_ctx(conf-ssl);return NGX_CONF_ERROR;}cln-handler = ngx_ssl_cleanup_ctx;cln-data = conf-ssl;/* 设置ClientHello消息回调 */
#if defined(T_INGRESS_SHARED_MEMORY_PB) OPENSSL_VERSION_NUMBER = 0x10101000LSSL_CTX_set_client_hello_cb(conf-ssl.ctx,ngx_http_ssl_client_hello_callback, NULL);
#endif/* 设置SNI消息回调 */
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAMEif (SSL_CTX_set_tlsext_servername_callback(conf-ssl.ctx,ngx_http_ssl_servername)== 0){ngx_log_error(NGX_LOG_WARN, cf-log, 0,"nginx was built with SNI support, however, now it is linked ""dynamically to an OpenSSL library which has no tlsext support, ""therefore SNI is not available");}#endif/* 设置ALPN消息回调 */
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiationSSL_CTX_set_alpn_select_cb(conf-ssl.ctx, ngx_http_ssl_alpn_select, NULL);
#endif没错,最以上源码的最后部分,nginx向openssl底层库设置了alpn的回调函数ngx_http_ssl_alpn_select,以期待接收到从客户端发过来的ClientHello中分析出有alpn扩展信息的时候回调这个函数。
3.2 连接初始化 在3.1节中所述的ssl上下文准备好以后,ssl连接当然是还没有建立的,只能说仍然只是停留在配置阶段,那么接下去可以想到客户端发起了tcp连接,nginx接受了这个连接,就需要开始对这个连接进行初始化,连接的初始化过程是由ngx_http_init_connection函数来完成的。那么如果开启了https,就会执行如下代码: