我花了将近一天的时间尝试为我的公司和社会构建支持 EL6 和 EL7 的 ALPN 和 http2 的 Apache httpd,就像我之前对 NGINX 所做的(针对 OpenSSL 1.0.2h 静态构建)。
首先,我尝试使用来自 Fedora 的 OpenSSL 1.0.2h 重建 src rpm,并安装生成的 rpm(openssl-devel-1.0.2h-1.el7.centos.x86_64.rpm、openssl-1.0.2h-1.el7.centos.x86_64.rpm)来替换系统版本。是的,我知道,对于公共版本来说这不是正确的方法,但我需要知道它是否可行。
然后我重建了 nghttp2-1.7.1-1.fc24.src.rpm 并安装了 libnghttp2-devel-1.7.1-1.el7.centos.x86_64.rpm 和 libnghttp2-1.7.1-1.el7.centos.x86_64.rpm。
最后,在删除一些补丁并破解 apr 和 apr-util 之后,我成功将 httpd-2.4.18-1.fc23.src.rpm 构建为 httpd-2.4.18-1.el7.centos.x86_64.rpm。
普通的 HTTP/1.1 对我来说可以正常工作,并且还支持 ALPN,但是 HTTP/2 不起作用:
$ curl -v --insecure --http2 --tlsv1.2 https://192.168.1.148
* Rebuilt URL to: https://192.168.1.148/
* Trying 192.168.1.148...
* Connected to 192.168.1.148 (192.168.1.148) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* ALPN, server accepted to use h2
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
* Server certificate:
* subject: [email protected],CN=centos7.dcodeit.net,OU=SomeOrganizationalUnit,O=SomeOrganization,L=SomeCity,ST=SomeState,C=--
* start date: май 25 13:11:19 2016 GMT
* expire date: май 25 13:11:19 2017 GMT
* common name: centos7.dcodeit.net
* issuer: [email protected],CN=centos7.dcodeit.net,OU=SomeOrganizationalUnit,O=SomeOrganization,L=SomeCity,ST=SomeState,C=--
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55ccf55b44c0)
> GET / HTTP/1.1
> Host: 192.168.1.148
> User-Agent: curl/7.43.0
> Accept: */*
>
* http2_recv: 16384 bytes buffer at 0x55ccf55b4e08 (stream 1)
* http2_recv: 16384 bytes buffer at 0x55ccf55b4e08 (stream 1)
* Unexpected EOF
* Closing connection 0
curl: (56) Unexpected EOF
我认为 Fedora 的一些补丁可能存在问题,并尝试重建其他部分,但没有成功。最后,我删除了所有“devel”rpm,下载了最新的稳定版 httpd-2.4.20,将 apr 和 apr-util 未修改的最新源放入其 srclib 目录,并尝试使用以下命令进行构建:
CFLAGS="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic"; export CFLAGS
LDFLAGS="-Wl,-z,relro,-z,now"; export LDFLAGS
"./configure" \
"--prefix=/etc/httpd" \
"--exec-prefix=/usr" \
"--bindir=/usr/bin" \
"--sbindir=/usr/sbin" \
"--mandir=/usr/share/man" \
"--libdir=/usr/lib64" \
"--sysconfdir=/etc/httpd/conf" \
"--includedir=/usr/include/httpd" \
"--libexecdir=/usr/lib64/httpd/modules" \
"--datadir=/usr/share/httpd" \
"--enable-layout=Fedora" \
"--with-installbuilddir=/usr/lib64/httpd/build" \
"--enable-mpms-shared=all" \
"--enable-suexec" \
"--with-included-apr" \
"--with-suexec" \
"--enable-suexec-capabilities" \
"--with-suexec-caller=apache" \
"--with-suexec-docroot=/var/www" \
"--without-suexec-logfile" \
"--with-suexec-syslog" \
"--with-suexec-bin=/usr/sbin/suexec" \
"--with-suexec-uidmin=1000" \
"--with-suexec-gidmin=1000" \
"--enable-pie" \
"--with-pcre" \
"--enable-mods-shared=all" \
"--enable-ssl" \
"--with-ssl=/root/openssl-1.0.2h" \
"--enable-ssl-staticlib-deps" \
"--with-nghttp2=/root/nghttp2-1.11.0" \
"--enable-nghttp2-staticlib-deps" \
"LDFLAGS=-Wl,-z,relro,-z,now" \
"CFLAGS=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic"
如您所见,我尝试使用最新版本的库静态构建 mod_ssl 和 mod_http2,但 http2 仍然无法正常工作,并显示完全相同的错误消息:服务器断开连接而没有任何回复。日志中找不到任何数据:请求根本没有显示在日志中,而 http/1.1、http/1.1 over SSL 和 h2c 请求均已正确记录和处理。
我的配置文件现在几乎是原装的(来自未修改的 httpd-2.4.20),但启用了 mod_ssl、mod_http2 和“协议 h2 http/1.1”。
还有一件奇怪的事情:我尝试添加“LogLevel http2:info”来调试 http2,但我看不到任何初始化行,如“[http2:info] [pid XXXXX:tid numbers] mod_http2 (v1.0.0, nghttp2 1.3.4), initializing...”。但是,我相信 http2 模块已打开,因为此日志级别没有配置错误。我还用 h2c(http2 over plain http)检查了它,它与 curl 和“101 Switching protocol”回复完美配合。
因此,我尝试使用不同版本的 lib 静态地、动态地构建它,最后我使用了干净、未修改的 nghttp2、openssl、apr、apr-util 源和配置文件,但没有任何成功,但是 HTTP/2 和 ALPN 可以单独正常工作。
请指教。
答案1
我注意到您正在使用此密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
但是该密码在 HTTP/2 中被列入黑名单:https://www.rfc-editor.org/rfc/rfc7540
默认情况下,mod_http2 不允许您与黑名单密码进行协商:https://httpd.apache.org/docs/2.4/mod/mod_http2.html#h2moderntlsonly
所以我想知道这是否是唯一的问题,您只需要启用更现代的密码套件吗?具体来说,是带有 GCM 的 ECDHE,而不是像 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA25 这样的 CBC 套件。您可以随时关闭上述标志以进行 curl 测试,但 Chrome 同样使用此黑名单,因此您无论如何都需要启用其他密码(既然您已经为此经历了升级 openssl 的麻烦,为什么您不想这样做呢)。
如果这不是问题,那么您可以查看我在此处提供的有关如何从源代码构建的分步说明:https://www.tunetheweb.com/performance/http2/。我使用 Centos 7,这些步骤对我有用。