November 17, 2019

NGINX 的 HTTP/3 尝试

前言

2019 年 9 月 26 日, Cloudflare 正式启用了 HTTP/3, 详情见 HTTP/3: the past, the present, and the future, 随后 10 月 17 日 Cloudflare 放出了基于 quiche 项目 的 NGINX patch, 详情见 Experiment with HTTP/3 using NGINX and quiche, 也正是这个 Patch 才会有这篇水文, 而关于 HTTP/3 的介绍不再赘述, 有兴趣的可以去 HTTP / 3:从头到脚的介绍 看看.

安装

参照 给 NGINX 添加 TLSv1.3 支持 准备除 OpenSSL 相关的依赖 (OpenSSL 本体和三个 patch).
注意: 同时打 HTTP/3 patch 和 hakasenyang 的 HPACK patch 需要手动解决冲突 (auto/options 文件)

另外虽然 Cloudflare 的文章里说该 patch 只在 NGINX 1.16.x 可用, 但实测 1.17.x 也没什么问题.

Note that the HTTP/3 and QUIC patch only works with the 1.16.x release branch (the latest stable release being 1.16.1).

quiche

git clone --recursive https://github.com/cloudflare/quiche
cd nginx-1.17.6
patch -p1 < ../quiche/extras/nginx/nginx-1.16.patch

P.s. 指定 commit 的原因是最近 Cloudflare 的几个提交添加了 h3-24 草案的支持, 但会导致浏览器端的 h3-23 无法正常使用以及 http3check.net 的测试结果不正常. 最新 commit 修好了.

编译

configure 配置参照 给 NGINX 添加 TLSv1.3 支持 去除 --with-cc-opt, --with-ld-opt 以及 --with-openssl-opt 部分, 然后添加以下参数, 最后照常编译, 测试, 安装到系统.

    --build="quiche-$(git --git-dir=../quiche/.git rev-parse --short HEAD)" \
   	--with-http_v3_module \
   	--with-openssl=../quiche/deps/boringssl \
   	--with-quiche=../quiche

配置 NGINX

确保 ssl_protocols 包含 TLSv1.3, 然后将 quicreuseport 选项添加到单独的 listen 配置里, 并添加对应的 alt-svc 头.
注意: 有多个站点时 reuseport 参数只需要添加一次, 否则 NGINX 会报错.

events {
    worker_connections  1024;
}

http {
    server {
        # Enable QUIC and HTTP/3.
        listen 443 quic reuseport;

        # Enable HTTP/2 (optional).
        listen 443 ssl http2;

        ssl_certificate      cert.crt;
        ssl_certificate_key  cert.key;

        # Enable all TLS versions (TLSv1.3 is required for QUIC).
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        # Add Alt-Svc header to negotiate HTTP/3.
        add_header alt-svc 'h3-23=":443"; ma=86400';
    }
}

客户端测试

浏览器

查看 HTTP/3 支持表: Can I use…

由此表可知 Firefox 需要 72+ 并在 about:config 内 打开 network.http.http3.enabled 而 Chrome 需要 79+ 并自行添加 --enable-quic (这个参数如果已经使用 flags 开启了则可忽略) 和 --quic-version=h3-23 启动命令, 我这里使用 Microsoft Edge 稳定版演示.

edge-command

添加完参数后, 打开支持 HTTP/3 (h3-23) 的站点, 使用开发者工具的网络功能可以看到如果 HTTP/3 成功连接, 协议会显示为 http/2+quic/99 (暂时)

edge-developer-tools-network

curl

拉取 quiche 和 BoringSSL

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

编译 BoringSSL

cd quiche/deps/boringssl
mkdir build
cd build
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=on ..
make
cd ..
mkdir -p .openssl/lib
cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib
ln -s $PWD/include .openssl

编译 quiche

cd ../..
QUICHE_BSSL_PATH=$PWD/deps/boringssl cargo build --release --features pkg-config-meta

拉取并编译 curl

cd ..
git clone https://github.com/curl/curl
cd curl
./buildconf
./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-ssl=$PWD/../quiche/deps/boringssl/.openssl --with-quiche=$PWD/../quiche/target/release --with-libssh2 --enable-alt-svc --with-librtmp --enable-tls-srp --with-gssapi --enable-doh
make
sudo make install

测试

 π curl master ❯ /usr/local/bin/curl -I --http3 https://love4taylor.me
HTTP/3 200
server: nginx/1.17.6
date: Wed, 04 Dec 2019 03:08:01 GMT
content-type: text/html
content-length: 10740
vary: Accept-Encoding
etag: "5de3d7e3-29f4"
strict-transport-security: max-age=31536000; includeSubDomains; preload
alt-svc: h3-23=":443"; ma=86400
accept-ranges: bytes
curl-http3

2019 © Love4Taylor · CC BY-NC-SA 4.0 · 友链