编译Nginx使博客支持QUIC-HTTP/3

博客支持HTTP/3,有多种方法可以实现,比如直接用Caddy v2;或者手工编译Nginx,打入Cloudflare开发的quiche补丁;Nginx官方10号宣布支持HTTP/3,于是又多出一种方法了。由于是Nginx老用户了,于是,分享打quiche补丁编译和官方编译Nginx-quic两种方法,以及博客配置的过程。

打补丁编译Nginx

首先是要下载Nginx和Cloudflare的quiche,但是实际编译中还需要cmake、go运行库、还有rust,咱们一步一步来。

下载nginx

Nginx官网:https://nginx.org/en/download.html

打开官网下载最新的nginx-1.19.0并解压:

wget -c https://nginx.org/download/nginx-1.19.0.tar.gz -O - | tar -xz

下载quiche

git clone --recursive https://github.com/cloudflare/quiche

下载go

下载go并解压到/usr/local路径下:

wget -c https://dl.google.com/go/go1.14.linux-amd64.tar.gz -O - | tar -xz -C /usr/local/

设置go环境变量,也可以写入到profile中

vi ~/.profile 写入下面内容:

1
2
3
4
5
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$HOME/.cargo/bin
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN

保存后,source ~/.profile

下载安装cmake

下载最新cmake,并编译安装:

1
2
3
4
5
6
#下载最新cmake
wget https://github.com/Kitware/CMake/releases/download/v3.16.8/cmake-3.16.8.tar.gz
#编译安装
tar zxf cmake-3.16.8.tar.gz && cd cmake-3.16.8 && ./bootstrap && make && make install
#创建软连接
ln -s /usr/local/bin/cmake /usr/bin/cmake

下载安装rust

curl https://sh.rustup.rs -sSf | sh

编译nginx

1
2
3
4
5
6
7
8
9
10
11
cd nginx-1.19.0
#打入quiche的path,官方说是支持nginx-1.16.1版,其实nginx-1.19.0版也是支持的
patch -p01 < ../quiche/extras/nginx/nginx-1.16.patch

#带插件编译nginx,这一步的路径和插件最好沿用老nginx的,以便无缝升级。
#nginx -V 查看老nginx路径和插件,复制下内容,然后加上下面的quiche插件就可以编译了。
#编译前应停止老版nginx,命令:systemctl stop nginx
./configure --prefix=$PWD --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-openssl=../quiche/deps/boringssl --with-quiche=../quiche
make
#最后一步make install是为了把文件打入指定路径,非必须执行
make install

编译好的Nginx二进制文件在/nginx-1.19.0/objs/文件夹里,或者直接在你编译时指定的路径里。

配置nginx.conf

vi /etc/nginx/nginx.conf

主要是在443端口下写入quic支持,和atl-svc响应头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
events {
worker_connections 1024;
}

http {
server {
# 开启quic
listen 443 quic reuseport;

listen 443 ssl http2;
#证书路径
ssl_certificate cert.crt;
ssl_certificate_key cert.key;

#要支持quic必须要开启TLSv1.3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

#Alt-Svc响应头
add_header alt-svc 'h3-27=":443"; ma=86400,h3-29=":443"; ma=86400';
}
}

保存,重启Nginx后,网站就应该支持HTTP/3了,可以按照下文的测试方法去测试一下。

下面分享编译官方Nginx-quic的方法:

编译官方Nginx-quic

首先放出nginx-quic官方网站:

https://hg.nginx.org/nginx-quic

因为官方用的也是BoringSSL库,所以可以借用上面quiche插件里面的BoringSSL,编译环境可参照上面,主要也就是cmake、go运行库、还有rust.

下载nginx-quic

下载并解压nginx-quic

wget -c https://hg.nginx.org/nginx-quic/archive/tip.tar.gz -O - | tar -xz

下载BoringSSL库

1
2
3
4
5
6
git clone https://boringssl.googlesource.com/boringssl
cd boringssl/
mkdir build
cd build/
cmake ..
make

如果你上面下载了quiche插件,这一步其实是不需要的,下面编译可以借用quiche里面的BoringSSL库。

编译nginx-quic

1
2
3
4
5
6
7
8
9
10
11
12
cd nginx-quic
#带插件编译nginx,这一步的路径和插件最好沿用老nginx的,以便无缝升级,编译前应停止老版nginx
#nginx -V 查看老nginx路径和插件,复制下内容,然后加上下面的boringssl就可以编译了
#boringssl库路径是沿用上面quiche文件夹里面的,如果是单独下载的BoringSSL,修改下路径就好了
./auto/configure --with-debug --with-http_v3_module --with-cc-opt="-I../quiche/deps/boringssl/include" --with-ld-opt="-L../quiche/deps/boringssl/build/ssl -L../quiche/deps/boringssl/build/crypto"

#下面是完整的编译路径,包括quic和geoip插件等,http/3只要用上面的就好
#./auto/configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_sub_module --with-mail --with-mail_ssl_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-pcre --with-stream --user=timo --with-http_mp4_module --with-http_auth_request_module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-debug --with-http_v3_module --with-cc-opt="-I../boringssl/include" --with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto" --add-dynamic-module=/root/ngx_http_geoip2_module

make
#最后一步make install是为了把文件打入指定路径,非必须执行
make install

nginx-quic配置nginx.conf

vi /etc/nginx/nginx.conf

主要是在443端口下写入http3支持,和atl-svc响应头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
events {
worker_connections 1024;
}

http {
#http3日志记录
log_format quic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$quic" "$http3"';

error_log /var/log/nginx/error.log crit;
access_log /var/log/nginx/access.log quic;

server {
# 开启http3,注意这一步不同于上面,上面填写的是quic
listen 443 http3 reuseport;

listen 443 ssl http2;
#证书路径
ssl_certificate cert.crt;
ssl_certificate_key cert.key;

#要支持quic必须要开启TLSv1.3
ssl_protocols TLSv1.2 TLSv1.3;

#Alt-Svc响应头,注意这个响应头填写也不同于上面
add_header alt-svc 'h3=":443"';
add_header QUIC-Status $quic;
}
}

启动nginx后,网站就应该支持http3了,可以按照下面方法测试一下。

测试HTTP/3支持

UDP端口测试

QUIC-HTTP/3是基于UDP协议的,因此需要开放服务器的UDP 443端口,一般服务器是默认开放的,可以检测一下自己的UDP 443端口是否开放?服务端检查443端口命令:

netstat -anp | grep "443"

如果udp 443端口没有开放给nginx,那么可以使用iptables开放443端口:

1
2
3
4
5
iptables -I INPUT -p udp --dport 443 -j ACCEPT

service iptables save

service iptables restart

或者,在本地电脑上,执行下面的命令:

nc -v -u 1.2.3.4 443

其中,1.2.3.4为您的服务器IP地址,若收到类似下面的回显,则说明进入服务器的UDP 443端口开放了。

Connection to 1.2.3.4 443 port [udp/*] succeeded!

然后,再测试一下出服务器的UDP 443端口。在服务器上执行下面的命令:

nc -v -u google.com 443

如果收到类似下面的回显,说明设置成功。

Connection to google.com 443 port [udp/*] succeeded!

网站测试

目前,有两个网站可以用来测试我们的网站是否支持QUIC-HTTP/3。

这两个网站分别是:

https://gf.dev/http3-test

https://http3check.net/

输入自己的域名即可测试网站是不是支持http/3

浏览器开启http3

Firefox开启http3

首先在火狐地址栏输入:about:config

然后搜索http3,找到network.http.http3.enabledfalse 改成 true,重启、就可以了。

Chrome canary开启http3

注意,只有金丝雀版chrome才支持http3,在地址栏输入 chrome://flags/

搜索quic,找到Experimental QUIC protocolDefault改成Enabled,重启浏览器。

然后,在Chrome canary的快捷方式,右键、属性,在目标栏尾处添加--enable-quic --quic-version=h3-29 即可。

最后,在浏览支持http3的网站时,按f12键可以查看网络、协议显示为HTTP/3或者h3-29.

注:本文说的HTTP/3指的是IETF QUIC,而非Google QUIC,这两个,现阶段是完全不同的分支。文中说的Cloudflare的quiche补丁只支持IETF QUIC,还没有支持Google QUIC,所以IETF QUIC在Google Chrome浏览器中并不被很好地支持,需要指定启动项,当然它自家的Google QUIC倒是支持的很好。最新版火狐是直接走IETF QUIC的HTTP3的,且支持得很好。

参考: