# 使用 nginx-quic 开启 HTTP/3

QUIC 是什么博主已经在以前的文章中提到过了,故不在赘述
本次使用 nginx-quic 开启 HTTP/3 支持,基于 ubuntu 22.04LTS 系统和宝塔面板

# 开始之前的准备

你的宝塔 nginx 必须是 1.22 版本或更高版本,如果不是请 卸载->编译安装
记得备份 nginx 主配置文件 (/www/server/nginx/conf/nginx.conf), 下面开始安装前置库:

apt install build-essential ca-certificates zlib1g-dev libpcre3 libpcre3-dev tar unzip libssl-dev wget curl git cmake ninja-build golang

随后执行:

apt install hgsubversion

如果报错,更改为:

apt install mercurial

# 编译 boringssl

众所周知,openssl 已经把 QUIC 支持扔到一边了,所以本次使用 boringssl 提供 ssl 支持
执行下列指令编译 boringssl:

下列指令需要 gcc 支持 C++14 或更高标准,建议升级为 gcc9 以上版本

git clone --depth=1 https://github.com/google/boringssl.git 
# github 速度问题自行解决
cd boringssl
mkdir build
cd build
cmake -GNinja ..
ninja
cd ../..

如果出现了网络问题,执行如下命令:

go env -w GOPROXY=https://goproxy.cn,direct

如果站点的 SSL 配置使用了 OSCP 装订 ( ssl_stapling ) 请直接注释
boringssl 不支持 OSCP 装订,会导致后续步骤无法执行

# 获取并编译 nginx-quic

# 获取 nginx-quic

使用 hg 获取 nginx-quic 的代码:

hg clone -b quic https://hg.nginx.org/nginx-quic
apt-get build-dep nginx

获取 nginx 编译参数:

nginx -V #或 /www/server/nginx/sbin/nginx -V

结果应该类似于下面:

nginx version: nginx/1.22.0
built by gcc 11.2.0 (Ubuntu 11.2.0-19ubuntu1) 
built with OpenSSL 1.1.1o
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module

configure arguments 记住并做更改:将 --with-openssl 参数删除,修改 --with-pcre=pcre-8.43--with-pcre=/www/server/nginx/src/pcre-8.43
添加下列参数在末尾: --with-http_v3_module --with-stream_quic_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' (boringssl 路径注意一下)

# 编译 nginx-quic

执行下列命令:

cd nginx-quic
./auto/configure "你的configure arguments"

等到配置结束后,删除 objs/Makefile 中的 -Werror 参数
随后更改 nginx 模块源码,让部分模块适配 nginx 1.23
打开 /www/server/nginx/src/lua_nginx_module/src/ngx_http_lua_headers_in.c 文件,转到 162 行,将 cookies 更改为 cookie
更改后的代码如下:

offsetof(ngx_http_headers_in_t, cookie),

打开 /www/server/nginx/src/nginx-sticky-module/ngx_http_sticky_module.c 文件,转到 207 行,将代码更改为如下内容:

if (ngx_http_parse_multi_header_lines(r, r->headers_in.cookie, &iphp->sticky_conf->cookie_name, &route) != NULL) {

随后开始编译:

make -j8 # -j 后为你的 CPU 核心数乘以 2

# 替换 nginx

开始替换原本的 nginx:

mv /www/server/nginx/sbin/nginx{,.bak}
cp objs/nginx /www/server/nginx/sbin
make upgrade

# 配置 HTTP/3

打开站点配置文件,在 listen 443 ssl http2 后增加:

listen 443 quic reuseport;

添加后所有站点都会开启 HTTP/3, 不要重复配置 (会报错)

root xxx 之后添加:

add_header Alt-Svc 'h3=":443"; ma=86400';

随后开启防火墙 udp (推荐使用宝塔防火墙应用), 将 443 端口更改为 tcp/udp
服务器安全组也需要开启 UDP443 端口

# 检验 HTTP/3 是否生效

edge 浏览器进入 edge://flags/ , 搜索 Experimental QUIC protocol 调整为 enable 即可打开
建议安装 http-indicator , 当小闪电变成橙色时 HTTP/3 就开启了
也可以使用网络面板,如果资源为 h3 协议,代表开启了 HTTP/3

# 常见问题

Q: 出现 nginx: [warn] "ssl_stapling" ignored, not supported 导致 make upgrade 无法运行
A: 调整站点配置文件 /www/server/panel/vhost/nginx/*.conf , 将 ssl_staplingssl_stapling_verify 删除

Q: 出现无原因的 nginx conf test failed
A: 卸载宝塔 nginx 防火墙后应该会解决

# 参考文章

教程:宝塔编译 Nginx 开启 HTTP/3
make it compatible with nginx 1.23