0x01 前言

因为太久没接触HTTP/2的相关设定,还不知道chrome对于HTTP/2的要求更加严格了,因为系统预设的openssl不支持ALPN使得chorme只能通过HTTP 1.1连接我的服务器。

在上周我将naxsi替换为modsecurity,终于能用上HTTP/2这一技术。但是在测试中发现curl、Firefox和其他软件在访问时都能通过HTTP/2进行连接,而chrome却一直是HTTP 1.1。

0x02 BUG

以下是通过curl命令获取头部信息,可以看到是支持HTTP/2协议的:

以下是chrome的结果:

0x03 DEBUG

其实问题很简单,在Chrome 51中Google移除了对SPDY协议和NPN协商协议的支持。

SPDY协议成为了HTTP/2协议,这个升级比较简单,只需要修改web服务器,也就是nginx即可;而NPN则是基于openssl的,取而代之的是一种新的协商协议:ALPN。

问题就出在ALPN协商协议的支持上:

图片来自Supporting HTTP/2 for Website Visitors

更多详细内容请点击以下链接:

从上图可以看出,目前仅有Debian 9和ubuntu 16.04系统中的openssl支持ALPN,而openssl也只有1.0.2或更新的版本才支持ALPN。

在centos 中默认的openssl版本为1.0.1e,而在我写这篇文章的时候已经可以升级到1.0.2k:

也就是说,在默认情况下编译nginx,因为openssl不支持ALPN的缘故,chrome不会使用HTTP/2进行连接,而采用HTTP/1.1。

解决办法也很简单,一种是升级系统中的openssl,只需要yum update即可;第二种是在编译nginx的时候指定openssl路径。

0x04 编译

如果系统中的业务对openssl的版本没有要求,那么直接update再编译是最好的选择;当然也可以指定openssl的路径自行编译。

首先准备好nginx源码和openssl:

下载链接可通过以下链接找到:

在选择openssl版本的时候需要注意,1.0.1所有的版本以及更旧的版本已经停止支持了,而1.0.2系列版本则到2019年12月31日才终止技术支持,目前稳定版本为1.1.0。如果可以,建议选择1.1.0系列版本的openssl。

下载完成后解压:

最后是编译:

configure无错误后可以看到以下内容:

然后编译和安装:

最后查看版本信息:

0x05 配置

我发现编译完成需要在nginx配置文件中的server字段中配置listen的参数,例如:

0x06 结语

centos7在编译安装nginx之前建议先升级系统,这样就不再需要那么繁琐的步骤了。