前言
HTTP/3 .0
出来已经能有一段时间了,而且功能相对都已经比较完善了。早就听说 Nginx
要支持 HTTP/3.0
了,可是截止到目前 ,Nginx
最新的版本 1.19.0 也仍未能见 HTTP/3.0
的影子。 目前,NGINX-QUIC 官方预览版现已上线,传送测试页 。官方部署文档:传送 。顾名思义,HTTP/3.0
就是 HTTP/2.0
的下一代版本,由谷歌发出。目前主流仍是 HTTP/2.0
,而且目前支持 HTTP/3.0
的 Client 几乎没有,只有谷歌浏览器金丝雀 Chrome Canary 和火狐浏览器 Firefox Nightly 及Curl 7.66 以后的版本(默认不开启,需要自行编译开启)支持 HTTP/3.0
。欲了解更多HTTP/3.0
的,可以去 Cloudflare 的官方博客文章《HTTP / 3:从头到脚的介绍》 看看。而 QUIC
是由 Cloudflare 维护并开源的项目,而本文正是通过编译 QUIC
来为 Nginx
实现 HTTP/3.0
的。
由于国内运营商的原因,基于 UDP
协议的 QUIC
在国内效果并是特别的理想,因此暂时仅供尝鲜!
安装依赖相关
Copy Code
yum install libunwind-devel -y
cd /www/server /nginx
wget http ://nginx.org/download/nginx-1.19 .4 .tar.gz
git clone
yum remove go
wget https://dl.google.com/go /go1.15 .2 .linux-amd64.tar.gz
cmake
yum remove cmake
wget https://github.com/Kitware/CMake/releases/download/v3.11 .4 /cmake-3.11 .4 .tar.gz
tar zxf cmake-3.11 .4 .tar.gz && cd cmake-3.11 .4 && ./bootstrap && make && make install
ln -s /usr/local /bin /cmake /usr/bin /cmake
tar -C /usr/local -xzf go1.15 .2 .linux-amd64.tar.gz
curl https://sh.rustup.rs -sSf | sh
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
至此,准备工作已就绪。
编译安装
Copy Code
tar zxvf nginx-1.19 .4 .tar.gz
cd nginx-1.19 .4
curl https://raw.githubusercontent.com/kn007/patch/master/nginx_with_quic.patch | patch -p1
patch -p01 < ../quiche/extras/nginx/nginx-1.16 .patch
curl https://raw.githubusercontent.com/kn007/patch/master/Enable_
BoringSSL _OCSP.patch | patch -p1
--build="quiche-$(git --git-dir=../quiche/.git rev-parse --short HEAD)" --with -http_v3_module --with -openssl=../quiche/deps/boringssl --with -quiche=../quiche
./configure --user=www --group=www --prefix=/www/server/nginx --with -openssl=../quiche/deps/boringssl --with -quiche=../quiche --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/redis2-nginx-module --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/ngx-pagespeed --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/ngx_brotli --add-module=/www/server/nginx/src/nginx-http-concat --add-module=/www/server/nginx/src/nginx-sorted-querystring-module --add-module=/www/server/nginx/src/ngx_http_substitutions_filter_module --add-module=/www/server/nginx/src/headers-more-nginx-module --add-module=/www/server/nginx/src/nginx_cookie_flag_module --add-module=/www/server/nginx/src/ModSecurity-nginx --add-module=/www/server/nginx/src/ngx_webp --with -http_stub_status_module --with -pcre=/www/server/nginx/src/pcre-8.44 --with -zlib=/www/server/nginx/src/zlib --with -http_ssl_module --with -http_v2_module --with -http_image_filter_module --with -http_gzip_static_module --with -http_gunzip_module --with -stream --with -stream_ssl_module --with -ipv6 --with -http_sub_module --with -http_flv_module --with -http_addition_module --with -http_realip_module --with -http_mp4_module --with -http_v2_hpack_enc --with -google_perftools_module --with -http_geoip_module --with -http_v3_module --build="quiche-$(git --git-dir=../quiche/.git rev-parse --short HEAD)"
make -j$(nproc --all)
可能出现的错误
出错一
Copy Code
...
make -f objs/Makefile
make[1] : 进入目录“/www/server/nginx/nginx-1.19.4”
mkdir -p ../quiche/deps/boringssl/build ../quiche/deps/boringssl/.openssl/lib ../quiche/deps/boringssl/.openssl/include/openssl \
&& cd ../quiche/deps/boringssl/build \
&& cmake -DCMAKE_C_FLAGS="" -DCMAKE_CXX_FLAGS="" .. \
&& make VERBOSE=1 \
&& cd .. \
&& cp -r include/openssl/*.h .openssl/include/openssl \
&& cp build/ssl/libssl.a build/crypto/libcrypto.a .openssl/lib
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
CMake 3.0 or higher is required. You are running version 2.8.12.2
-- Configuring incomplete, errors occurred!
make[1] : *** [../quiche/deps/boringssl/.openssl/include/openssl/ssl.h] 错误 1
make[1] : 离开目录“/www/server/nginx/nginx-1.19.4”
make : *** [build] 错误 2
Copy Code
touch ../quiche/deps/boringssl/ .openssl/include/openssl/ssl.h
出错二
Copy Code
...
-- No package 'libunwind-generic' found
libunwind not found. Disabling unwind tests.
CMake Error at CMakeLists.txt:51 (message):
Could not find Go
...
Copy Code
yum install libunwind-devel
出错三
Copy Code
...
make -f objs/Makefile
make[1]: 进入目录“/www/server/nginx/nginx-1.19.4”
cd ../quiche && cargo build --release --no-default-features
/bin/sh: cargo: 未找到命令
make[1]: *** [../quiche/target/release/libquiche.a] 错误 127
make[1]: 离开目录“/www/server/nginx/nginx-1.19.4”
make: *** [build] 错误 2
Copy Code
出错四
Copy Code
...
/www/server/nginx/src/lua_nginx_module/src/ngx_http_lua_script.c: In function ‘ngx_http_lua_script_add_copy_code’:
/www/server/nginx/src/lua_nginx_module/src/ngx_http_lua_script.c:332 :18 : error: cast between incompatible function types from ‘size_t (*)(ngx_http_lua_script_engine_t *)’ {aka ‘long unsigned int (* )(struct <anonymous> * )’} to ‘void (* )(ngx_http_lua_script_engine_t * )’ {aka ‘void (*)(struct <anonymous> *)’} [-Werror=cast-function-type]
code->code = (ngx_http_lua_script_code_pt)
^
/www/server/nginx/src/lua_nginx_module/src/ngx_http_lua_script.c: In function ‘ngx_http_lua_script_add_capture_code’:
/www/server/nginx/src/lua_nginx_module/src/ngx_http_lua_script.c:402 :18 : error: cast between incompatible function types from ‘size_t (*)(ngx_http_lua_script_engine_t *)’ {aka ‘long unsigned int (* )(struct <anonymous> * )’} to ‘void (* )(ngx_http_lua_script_engine_t * )’ {aka ‘void (*)(struct <anonymous> *)’} [-Werror=cast-function-type]
code->code = (ngx_http_lua_script_code_pt)
^
cc1: all warnings being treated as errors
make[1 ]: *** [objs/Makefile:1912 : objs/addon/src/ngx_http_lua_script.o] Error 1
make[1 ]: *** Waiting for unfinished jobs....
make[1 ]: Leaving directory '/www/server/nginx/src'
make: *** [Makefile:8 : build] Error 2
Copy Code
...
CC = cc
CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -DNDK_SET_VAR -D_GLIBCXX_USE_CXX11_ABI=0 -Wno-deprecated-declarations
CPP = cc -E
LINK = $(CC)
...
touch ../quiche/deps/boringssl/.openssl/include /openssl/ssl.h
make -j$(nproc --all)
出错五
Copy Code
...
[ 84 %] Building CXX object ssl/CMakeFiles/ssl.dir/tls13_client.cc.o
cd /www/server/nginx/quiche/deps/boringssl/build/ssl &&
/usr/bin /c++ -DBORING SSL _DISPATCH_TEST -DBORING SSL _HAVE_LIBUNWIND -DBORING SSL _IMPLEMENTATION -I/www /server/nginx /quiche/deps /boringssl/third _party/googletest/
include -I/www/server/nginx/quiche/deps/boringssl/ssl/../
include -Werror -Wformat=
2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -Wvla -ggdb -Wall -fvisibility=hidden -fno-common -Wno-free-nonheap-object -Wmissing-declarations -std=c++
11 -fno-exceptions -fno-rtti -Wshadow -o CMakeFiles/ssl.dir/tls13_client.cc.o -c /www/server/nginx/quiche/deps/boringssl/ssl/tls13_client.cc
/www/server/nginx/quiche/deps/boringssl/crypto/trust_token/trust_token_test.cc: In constructor ‘bssl::{anonymous}: :TrustTokenProtocolTestBase : :TrustTokenProtocolTestBase (const TRUST_TOKEN_METHOD*)’:
/www/server /nginx/quiche /deps/boringssl /crypto/trust _token/trust_token_test.cc: 100 : 7 : error: declaration of ‘method’ shadows a member of 'this' [-Werror=shadow]
: method_ (method) {}
^
/www/server /nginx/quiche /deps/boringssl /crypto/trust _token/trust_token_test.cc: In member function ‘virtual void bssl::{anonymous}: :TrustTokenMetadataTest_TruncatedProof_Test : :TestBody ()’:
/www/server /nginx/quiche /deps/boringssl /crypto/trust _token/trust_token_test.cc: 589 : 12 : error: declaration of ‘public_metadata’ shadows a member of 'this' [-Werror=shadow]
uint32_t public_metadata;
^
/www/server /nginx/quiche /deps/boringssl /crypto/trust _token/trust_token_test.cc: In member function ‘virtual void bssl::{anonymous}: :TrustTokenMetadataTest_ExcessDataProof_Test : :TestBody ()’:
/www/server /nginx/quiche /deps/boringssl /crypto/trust _token/trust_token_test.cc: 657 : 12 : error: declaration of ‘public_metadata’ shadows a member of 'this' [-Werror=shadow]
uint32_t public_metadata;
...
解决方式同出错四 。
平滑升级
Copy Code
sudo objs/nginx -t
mv /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx.bak
cp /www/server/nginx/nginx-1.19 .4 /objs/nginx /www/server/nginx/sbin/nginx
make upgrade
nginx version:
QUIC /
1.1 .1 (--build=quiche-fd5e028)
built by gcc 4.8 .5 20150623 (Red Hat 4.8 .5 -39 ) (GCC)
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --with -openssl=../quiche/deps/boringssl --with -quiche=../quiche --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/redis2-nginx-module --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/ngx-pagespeed --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/ngx_brotli --add-module=/www/server/nginx/src/nginx-http-concat --add-module=/www/server/nginx/src/nginx-sorted-querystring-module --add-module=/www/server/nginx/src/ngx_http_substitutions_filter_module --add-module=/www/server/nginx/src/headers-more-nginx-module --add-module=/www/server/nginx/src/nginx_cookie_flag_module --add-module=/www/server/nginx/src/ModSecurity-nginx --add-module=/www/server/nginx/src/ngx_webp --with -http_stub_status_module --with -pcre=/www/server/nginx/src/pcre-8.44 --with -zlib=/www/server/nginx/src/zlib --with -http_ssl_module --with -http_v2_module --with -http_image_filter_module --with -http_gzip_static_module --with -http_gunzip_module --with -stream --with -stream_ssl_module --with -ipv6 --with -http_sub_module --with -http_flv_module --with -http_addition_module --with -http_realip_module --with -http_mp4_module --with -http_v2_hpack_enc --with -google_perftools_module --with -http_geoip_module --with -http_v3_module --build=--build=quiche-fd5e028
修改配置
Copy Code
listen 443 quic reuseport;
listen 443 ssl http2;
ssl_protocols TLSv1.2 TLSv1.3 ;
ssl_ciphers [TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA;
ssl_prefer_server_ciphers on ;
ssl_early_data on ;
ssl_ecdh_curve X25519:P-256 :P-384 ;
ssl_session_cache shared:
SSL :
10m ;
ssl_session_timeout 10m ;
error_page 497 https://$host $request_uri ;
ssl_stapling on ;
ssl_stapling_verify on ;
ssl_stapling_file /home/others/ocsp/nange.cn.ocsp.resp;
add_header alt-svc 'quic=":443"; ma=2592000; ' ;
注意: 有多个站点时 reuseport
参数只需要添加一次, 否则 NGINX 会报错!
测试
Mac
Copy Code
brew install --HEAD -s https://raw.githubusercontent.com/cloudflare/homebrew-cloudflare/master/curl.rb
curl -I --http3 https://www.nange.cn/
--- ~ » curl -I --http3 https://www.nange.cn
HTTP/3 200
server: NAN
date: Thu, 19 Mar 2020 09:58:04 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Thu, 19 Mar 2020 07:49:24 GMT
strict-transport-security: max-age=63072000; includeSubDomains; preload
access-control-allow-origin: *
alt-svc: quic=":443"; ma=2592000
Copy Code
git clone --recursive https://github.com/cloudflare/quiche
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
cd ../..
QUIC HE_B SSL _PATH =
$PWD/deps/boringssl cargo build --release --features pkg-config-meta
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
make
# 测试结果
[root@Her ~]# curl -I --http3 https://www.nange.cn
HTTP/3 200
server : NAN
date : Thu, 19 Mar 2020 10:01:06 GMT
content-type : text/html; charset=UTF-8
vary : Accept-Encoding
last-modified : Thu, 19 Mar 2020 07:49:24 GMT
strict-transport-security : max-age=63072000; includeSubDomains; preload
access-control-allow-origin : *
alt-svc : quic=":443"; ma=2592000
浏览器
需要先开启 QUIC
支持,浏览器地址栏输入:chrome://flags/
回车,依次搜 QUIC/TLS 1.3/TLS 1.3 Early Data
,分别选择 enable
后重启浏览器。然后关闭停用广告拦截应用或插件及网络代理程序,并在终端(Mac)输入:
Copy Code
/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --enable -quic --quic-version=h3-29
以再次打开浏览器。有 h3-29
字样说明支持。如图:
经自测,目前 Google Chrome Canary 最新版 v89.0.4327.0 只需要在配置里开启 QUIC 支持,无需额外添加启动参数即可直接支持 QUIC(最低h3-29)。
在浏览器地址栏输入 about:config
,搜 http3
,将 network.http.http3.enabled
改为 true
重启浏览器即可。如图
测试结果如图,显示HTTP/3
说明成功支持。
第三方网页在线检测
地址:h ttps://http3check.net/
我的测试结果
测试中踩到的坑
最初什么都编译部署好了,但是无论在哪个平台,运行 curl -I --http3 https://www.nange.cn/
始终不返回任何结果和信息。在第三方在线测试也提示 QUIC
连接失败!十分郁闷,后来在 Quiche
的 issues 中得知是 CentOS7.7
的防火墙没有开启 443
的 UDP
端口,默认只开启了 443
的 TCP
端口。导致连接直接被防火墙给屏蔽了。自己想想必须的这样啊,QUIC/HTTP3
的连接协议本来就是 UDP
而非 HTTP2
的 TCP
协议!得知此原因后,只需开放相应端口的 UDP
连接即可!
Copy Code
# 以 CentOS 7.7 为例
# 先查看下以开放的端口,如果有就不必开启了
firewall-cmd --zone=public --list-ports
# 没有的话,开启相应协议端口,其它端口亦是如此。
# 开启 80 udp端口
firewall-cmd --zone=public --add -port=80 /udp --permanent
# 开启 443 udp 端口
firewall-cmd --zone=public --add -port=443 /udp --permanent
# 重启防火墙服务
systemctl restart firewalld.service
使用愉快!
这个是什么情况啊
@Lucifer如果你补丁打的是
CloudFlare
的quiche
,把该参数去掉。如果不是,请打文中第一个补丁:您好,请问在
curl -I -http3
后面跟的这个域名可以是其他支持quic
的站点吗。我无论是跟您的nange.cn
还是其他支持quic
的站点都没反应,是我nginx
配置有问题吗?nginx
配置的ssl
证书和密钥那两行该怎么填写呢还是不用呀@chj这和
Nginx
没有关系,你可以更换其它任何一个域名。记得打开防火墙放行443/UDP
端口。@佩佩不好意思再麻烦下。。那这样为什么
curl
能运行但没反应呢 我就一直怀疑是nginx
配置文件中的ssl
证书问题@chj这不显示的
HTTP/3
么?说明是可以的,只不过我的站有防爬策略,所以禁止了curl
请求方式。@佩佩那您截图里怎么通过
curl
访问并得到响应的呢。。而且我这边不论nginx
启动与否都是显示这个,通过浏览器也没看到http3
协议。同时我通过curl
访问其他的支持quic
的网站(比如)基本是连接超时,比如https://quic.nginx.org/
,我觉得还是我没有启动quic
成功吧。(还有一个问题是访问
https://nange.cn
显示的更全)其中
alt-svc
并不是我在nginx
中设置的量。。。@chj我当时为了测试效果特意把防爬关了。
另外,从你这边访问我的站点。和你本地的
Nginx
没有任何关系,只和我这边的Nginx
有关。你只要在站点
https://http3check.net/
测试是通过的,那就没问题啦。至于浏览器,目前主流浏览器默认还不支持
HTTP3
,需要另外开启和启动时加参数才行。具体看本文浏览器部分,而且特别仔细阅读《支持 QUIC 的 NGINX 官方预览版部署体验》最后一段话。还有,你请求结果中的
alt-svc
参数只和目标服务器(我的服务器)的配置有关,跟你自己本地无关。@佩佩哦哦我明白了,就是用
nginx
部署quic
是和自己的服务器相关的对吧。 感谢感谢!@chj嗯,是的。😎
@佩佩博主您好!我通过
chrome
访问自己的部署站点时,没有在调试台的network
里看到quic
,看到的全是h2
.因为域名还在备案,是通过服务器ip
地址访问的,然后显示证书无效(阿里云的免费证书),是有可能因为这个吗?卡在这里,不动了。有人遇到过吗?
完全按照上述进行搭建的环境,唯一区别就是nginx我用的是1.16.1版本。
centos7.6.1810
@bruce
rustc --version
也会卡住。使用
curl https://sh.rustup.rs -sSf | sh
来安装的,装完也配置了环境变量@bruce不知道,没遇到。
问下,哪位遇到过
@菜鸟
cmake
的锅,我也常遇到。你可以谷歌下”-Werror=shadow
“,或BoringSSL
回滚到到上一个版本。@佩佩解决了吗??
@caiji
make -i
执行命令——-
@NGINX我也遇到了这个问题,这个问题你解决了吗?
@icanbibi😓 不用执行那条,
Nginx
编译配置里已经包含了。唉,我应该把它删了的。@icanbibi我放弃了对
curl
的对http3.0
的编译@nginx我就是单独编译
curl 7.70.0
+quiche
,quiche
可以编过,但是在编译curl
的时候,执行configure
就有这个错误,这个是避不开的吧@nginx这个编译问题我貌似解决了,报这个问题可能是机器没有安装
pkg-config
,你可以试下@icanbibiok,现在使用
https://http3check.net/
检测不出来HTTP3.0
,但是在火狐浏览器F12
又可以看到HTTP3.0
哇哦~٩(๑ᵒ̴̶̷͈᷄ᗨᵒ̴̶̷͈᷅)و 好腻害!
关于
curl
的编译我这边明白了,非常非常感谢您!针对浏览器上的测试我想问一下关于chrome canary
,我用的系统是Debian
,chrome canary
并不支持在debian
上安装,所以想问一下您是如何在chrome canary
中测试是否开启了http3
(协议为http2+quic
)?@zan
chrome canary
有点迷,一会儿可以,一会儿又不可以。而且我 Mac 端的很不稳定。@佩佩嗯嗯好吧!那您说的
firefox nightly
稳定吗?@zan都是夜更版的,差不多吧都。😂
@佩佩唉,我现在主要想获取到
quic
数据包,所以才打算在浏览器中开启quic
但这浏览器还不好使,您有什么其他方法吗?能够获得quic
协议的数据包@zan
firefox nightly
只要设置完就可以支持的。您好,在执行
curl -I --http3...
时出现curl:option --http3: is unknown
,您图中的内容执行不出来,麻烦您看到后帮忙回答一下,谢谢您!!@zan
curl
默认不开启“--http3
”参数,需要自行编译安装才可以。但是要注意自己编译安装后容易出现的问题,也就是今天最新发的那篇文章《解决 cURL 报错 “curl: undefined symbol: curl_mime_free”》。@佩佩您好,我刚刚又重新编译了
curl
(按照你上述步骤进行的安装编译),也参考了您新发的文章,我这里并没有出现curl
报错的问题。但还是出现curl:option --http3:is known
,还是不知道为什么?谢谢您@zan你需要单独对
curl
进行编译,编译后系统默认还是调用的旧版本curl
,需要手动指定curl
调用,或者直接将系统默认的替换为编译后的curl
。@佩佩我明白您的意思了,但还有一个疑问,
curl
如何在编译过程中告诉curl
支持http3
呢?比如curl
对http2
支持需要安装nghttp2
,对于http3
是否需要额外安装其他?非常感谢@zan编译好之后只需要添加参数“
--http3
”就可以了,不需要安装其他东西。