闲逛发现 nginx 官网 多了一行字: “Support for HTTP/3.”,距离第一次体验 HTTP3 已经过去了 4 年,4 年前,我们体验 HTTP3 是用 Cloudflare 提供的 quiche 这个库来实现的,如今,nginx 终于通过这个 ngx_http_v3_module 提供了官方支持。

SSL 库方面,最流行的 OpenSSL 决定自己实现 QUIC 支持,按照官网给出的 roadmap,看起来至少半年内是没什么希望的。
nginx 方面自己实现了一个 OpenSSL 的兼容层,1.25.0 以后版本的 nginx 中已经自带了。但是这个兼容层不支持 early data。有些营销号直接把 early data 机翻成了“早期数据”,并解释为旧数据,实际上 early data 指的是 TLS1.3 中的 0-RTT data,详见这里
所以目前 SSL 库最好从以下 3 个中 BoringSSL、 LibreSSL 或 QuicTLS 三选一。

开始体验

BoringSSL 为例

1
2
3
4
5
6
7
8
9
# 安装 go
wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz

tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz

export PATH=$PATH:/usr/local/go/bin

go version
# go version go1.21.3 linux/amd64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 安装 cmake 和 ninja
wget -c https://github.com/Kitware/CMake/releases/download/v3.28.0-rc2/cmake-3.28.0-rc2.tar.gz

tar zxvf cmake-3.28.0-rc2.tar.gz

cd cmake-3.28.0-rc2

./configure --prefix=/usr/local/cmake-3.28.0-rc2

gmake && gmake install

vim /etc/profile

PATH=/usr/local/cmake/bin:$PATH

export PATH

source /etc/profile

cmake --version

# cmake version cmake-3.28.0-rc2

yum install ninja-build
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 安装新版本 GCC 和 G++
yum install centos-release-scl
yum -y install devtoolset-10-gcc devtoolset-10-gcc-c++ devtoolset-10-binutils

# 临时指定版本
scl enable devtoolset-10 bash
# 持久化使用
source /opt/rh/devtoolset-10/enable

# cmake -D CMAKE_C_COMPILER=/opt/rh/devtoolset-10/root/usr/bin/gcc -D CMAKE_CXX_COMPILER=/opt/rh/devtoolset-10/root/usr/bin/gcc -GNinja -B build

# 编译 BoringSSL
git clone --depth=1 https://github.com/google/boringssl.git

cd boringssl && mkdir build && cd build

# 官方建议使用 [ninja](https://ninja-build.org/),比 make 更快
cmake -GNinja -B build

ninja -C build
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 安装 nginx (1.25.0 版本开始支持HTTP3)
wget https://nginx.org/download/nginx-1.25.2.tar.gz
tar zxvf nginx-1.25.2.tar.gz
cd nginx-1.25.2

./configure --prefix=/etc/nginx
--with-debug
--with-http_v3_module
--with-cc-opt="-I../boringssl/include"
--with-ld-opt="-L../boringssl/build/ssl
-L../boringssl/build/crypto"

./configure --prefix=/etc/nginx --with-debug --with-http_v3_module --with-cc-opt="-I../boringssl/include" --with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto"

./configure --prefix=/etc/nginx --with-debug --with-http_v3_module --with-openssl="../boringssl" --with-cc-opt="-I../boringssl/include" --with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto"

# configure 后,需要 touch 标记一下 ssl.h 文件的时间
touch ../boringssl/.openssl/include/openssl/ssl.h

make && make install

nginx -V
# built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL)
# TLS SNI support enabled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
; 基础配置,更多详细内容可以参考这里:
; https://nginx.org/en/docs/http/ngx_http_v3_module.html
server {
server_name xxx.com;

listen 443 quic reuseport;
listen 443 ssl;

ssl_certificate xxx.crt;
ssl_certificate_key xxx.key;
ssl_protocols TLSv1.3;

location / {
add_header Alt-Svc 'h3=":443"; ma=86400';
}
}
1
2
3
4
5
6
7
vim /etc/firewalld/zones/public.xml

# 放开对应的防火墙
<service name="http"/>
<service name="https"/>
<port protocol="udp" port="443"/>
<port protocol="tcp" port="443"/>

配置好之后,可以在这里监测一下,如图显示,我们已经成功启用了HTTP/3。

https://http3check.net/?host=xxx.com

同时,打开浏览器控制台,也能看到 protocol 这一项也已经升级为 h3。

如果前面的流程没有问题,还是显示不支持,可以在这里检测一下浏览器是否已经支持
https://quic.nginx.org/

记得关闭代理软件,有些代理协议不支持HTTP/3。