重新编译 curl 以支持 HTTP3

技术 秋水逸冰 395浏览 0评论

从 2022 年 6 月 HTTP/3 的 RFC 发布,截至目前,常用的 Web Server,比如 Caddy Web ServerNginx 已经支持 HTTP/3。与此同时,常用的浏览器比如 Google Chrome,Microsoft Edge,Mozilla Firefox,Apple Safari 等也都开始支持 HTTP/3。这里吐槽一下,Apache httpd 支持 HTTP/3 还遥遥无期。
常用的 Client 软件比如 curl 其实也早已开始支持 HTTP/3,但是目前各大 Linux 发行版编译的 curl 都不包含 HTTP3 特性,故此我打算自己来。
本文主要详细讲述如何在下列 RHEL 系统中安装已经重新编译好的 curl,以及在编译 curl 中遇到的问题。
Enterprise Linux 8 (CentOS Stream 8, RHEL 8, Rocky Linux 8, AlmaLinux 8, Oracle Linux 8)
Enterprise Linux 9 (CentOS Stream 9, RHEL 9, Rocky Linux 9, AlmaLinux 9, Oracle Linux 9)

如何安装已经编译好的 curl


(以下均为使用 root 用户操作)
1. 开启 EPEL Repository

dnf install -y yum-utils epel-release
dnf config-manager --enable epel

2. 执行以下命令安装 Teddysun Linux Repository:
适用于 Enterprise Linux 8 (CentOS Stream 8, RHEL 8, Rocky Linux 8, AlmaLinux 8, Oracle Linux 8) 的安装命令

dnf install -y https://dl.lamp.sh/linux/rhel/el8/x86_64/teddysun-release-1.0-1.el8.noarch.rpm

适用于 Enterprise Linux 9 (CentOS Stream 9, RHEL 9, Rocky Linux 9, AlmaLinux 9, Oracle Linux 9) 的安装命令

dnf install -y https://dl.lamp.sh/linux/rhel/el9/x86_64/teddysun-release-1.0-1.el9.noarch.rpm

3. 重建 Repository 缓存,执行如下命令:

dnf makecache

4. 通过 dnf 来安装重新编译的 curl,执行如下命令:

dnf install -y curl libcurl libcurl-devel

dnf 会自动安装一些依赖包。安装成功后,查看 curl 的版本号,执行命令:curl -V
在 Enterprise Linux 8 (CentOS Stream 8, RHEL 8, Rocky Linux 8, AlmaLinux 8, Oracle Linux 8) 系统下,显示的是:

curl 8.10.0 (x86_64-redhat-linux-gnu) libcurl/8.10.0 OpenSSL/3.3.2 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 libidn2/2.3.7 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.63.0 nghttp3/1.5.0 librtmp/2.6 libgsasl/1.10.0 OpenLDAP/2.4.46
Release-Date: 2024-09-11
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli gsasl GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

在 Enterprise Linux 9 (CentOS Stream 9, RHEL 9, Rocky Linux 9, AlmaLinux 9, Oracle Linux 9) 系统下,显示的是:

curl 8.10.0 (x86_64-redhat-linux-gnu) libcurl/8.10.0 GnuTLS/3.8.3 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 libidn2/2.3.7 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.63.0 ngtcp2/1.7.0 nghttp3/1.5.0 librtmp/2.6 libgsasl/1.10.0 OpenLDAP/2.6.6
Release-Date: 2024-09-11
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli gsasl GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

5. 特性说明
在 Enterprise Linux 8 使用 OpenSSL/3.3.2 + nghttp3/1.5.0,Enterprise Linux 9 则使用 GnuTLS/3.8.3 + ngtcp2/1.7.0 + nghttp3/1.5.0 作为后端,从而支持 HTTP/3。
支持 rtmp, ws, wss 等 Protocol。
支持 brotli, gsasl, zstd 等 Feature。
编译了 curl 的各个依赖软件到最新版本。
6. 测试是否支持 HTTP/3
使用以下命令来查看是否支持 HTTP/3。

curl -I --http3-only https://nghttp2.org/

返回值示例如下所示:

HTTP/3 200 
date: Sun, 15 Sep 2024 05:37:12 GMT
content-type: text/html
last-modified: Tue, 27 Aug 2024 09:49:44 GMT
etag: "66cda138-18b4"
accept-ranges: bytes
content-length: 6324
x-backend-header-rtt: 0.001521
strict-transport-security: max-age=31536000
server: nghttpx
via: 2 nghttpx
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff

第一行的 HTTP/3 200 就表示已经支持 HTTP/3。

在编译 curl 中遇到的问题

1. ngtcp2 和 nghttp3 的 rpm 不存在
开启 HTTP/3 特性需要 ngtcp2 和 nghttp3 来支持,但是目前并没有相关的 rpm,于是我参考了 nghttp2 的 spec 文件,自行制作了这两个依赖的 rpm 包。
ngtcp2 同时还需要 Crypto helper library 才能实现 QUIC 协议,目前受支持的 TLS 后端也就是如下列表:

quictls
GnuTLS >= 3.7.5
BoringSSL (commit e13f7e2ff5432205f09b4679c8a7715f1c130372); or aws-lc >= 1.19.0
Picotls (commit 89fe56f4d79200a5801a08ed3b6ac8322e01ccd5)
wolfSSL >= 5.5.0
LibreSSL >= v3.9.2

Enterprise Linux 9 中默认安装的 GnuTLS 版本是 3.8.3,满足条件,因此是首选。编译出 libngtcp2_crypto_gnutls 的 Crypto helper library,加上 nghttp3 来开启 HTTP/3 特性。
Enterprise Linux 8 中默认安装的 GnuTLS 版本是 3.6.16,不满足条件。又没有别的更好的 TLS 后端,于是编译了 openssl3 到最新的 3.3.2(该版本已经实现了 QUIC),加上 nghttp3 来开启 HTTP/3 特性。
2. 默认安装的依赖软件版本比较旧
比如 brotli,zstd,libidn2,libpsl,libssh2,libgsasl,发行版自带的默认版本比较旧,补丁摞补丁,就是不升级版本(当然了,这是为了稳定性,毕竟是企业级系统,可以理解)。
对于自用,这些依赖升级了也不会出现大问题,至少目前我还没发现。
3. 有些依赖软件不存在
比如 librtmp,这款软件名为 rtmpdump,属于 ffmpeg 项目下的一个 toolkit,用于支持 RTMP 流。在 RHEL 下默认就没有该 rpm 包,RpmFusion 里只有古老的版本。稀奇的是今年在其 git 里竟然更新了。
其最新 git commit log 是 v2.6 版本,结果编译出来的 library 和头文件还是 v2.3,于是只能自己写个补丁,把版本号改正过来,再制作编译 rpm 到最新版 2.6-1.20240301.git6f6bb13。
前前后后遇到不少问题,花了不少时间,总算是搞出来了。目前为止,自己用着挺满意,今天分享出来,希望大家也满意。

写在最后

请关注我的 Telegram 频道:https://t.me/qiushuiyibing
我会在此不定期发布一些杂七杂八的作品。
同时也欢迎加入交流群:https://t.me/qiushui2018

转载请注明:秋水逸冰 » 重新编译 curl 以支持 HTTP3

发表我的评论
取消评论

请输入正确答案后提交评论 *超出时限。 请再次填写验证码。

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址