如何在Nginx中启用HTTP 3.0/QUIC支持

系统 Linux
本文主要讲解一下如何在 Nginx 中开启 HTTP3.0 的支持。一起来看看吧。

 [[377426]]

在 Nginx 中支持 HTTP3.0 / QUIC

HTTP 3.0,也称作 HTTP over QUIC。核心是 QUIC (读音quick)协议,由 Google 在 2015 年提出的 SPDY v3 演化而来的新协议,传统的 HTTP 协议是基于传输层 TCP 的协议,而 QUIC 是基于传输层 UDP 上的协议,可以定义成:HTTP3.0 基于 UDP 的安全可靠的 HTTP2.0 协议,主要有以下特性:

图片来自Nginx官博

  •  基于 UDP 减少了 TCP 三次握手及 TLS 握手时间
  •  解决多路复用丢包时的线头阻塞问题
  •  优化重传策略
  •  流量控制
  •  连接迁移

本文主要讲解一下如何在 Nginx 中开启 HTTP3.0 的支持。

方案选择

对于 HTTP3.0,由于整个协议还是处于草案阶段,目前来说没有一个完整的标准,所以各大浏览器厂商还只是在开发者版本中才会支持,例如 Chrome的金丝雀版本 Chrome Canary[1],并且各个服务器厂商也是在持续跟进中,对于 Nginx 来说,支持 HTTP3.0 目前有两种方案可以选择:

  •  基于 Cloudflare 的分支版本 Nginx:对于 HTTP3.0/QUIC,Cloudflare 始终走在了前列,借助于自家维护的开源项目 quic[2],从 Nginx 中拉出了一个分支来开发,并编译出了对 HTTP 3.0 支持的 Nginx 服务器。
  •  Nginx 官方 Nginx-quic 项目:今年 6 月1 0 日,Nginx 官博[3]发布公告称已经在研发支持 HTTP3.0/QUIC 协议的工作,目前项目维护在 nginx-quic[4],该项目和基于 Cloudflare 基于 Nginx 的分支并无关系,算是相对于正统的方案。

基于此,本文将会以部署 nginx-quic 的方式来让 Nginx 支持 HTTP3.0/QUIC。

改造过程

我们最终的目的是得到 nginx-quic 版本的 nginx 可执行文件,需要经过一系列的安装和编译,期间可能会遇到很多问题,如果各位读者不想实际操作,可以直接用我编译好的版本 nginx-quic.linux-x86_64.zip 传送门[5]。

准备工作:

以 centos7 为例,下载 nginx-quic 源码传送门[6],下载完成之后,需要进行编译安装,由于 nginx-quic 依赖 boringSSL,所以还需下载 boringSSL 源码传送门[7],然后同样需要编译安装 boringSSL,执行这些操作之前,需要在 linux 上安装一些前置模块,通过 yum 来安装,执行以下命令: 

  1. sudo yum install build-essential mercurial psmisc lsb-release cmake golang libunwind-dev git libpcre3-dev zlib1g-dev 

什么是 boringSSL:

对于 Nginx 来说,在编译时需要配置对于的 SSL 库,不管是 HTTP3.0 还是 HTTP2.0,始终都要基于 HTTPS,而加密算法这块主要有 OpenSSL来提供,而 BoringSSL 是谷歌创建的 OpenSSL 分支,用于支持 TLS1.3的 UDP 协议 0-RTT 数据传输的加密算法(可以理解成 TLS 1.3 是标准协议,BoringSSL 是实现工具),BoringSSL 的一些特性会在合适的时机同步给 OpenSSl。

编译安装 boringSSL: 

  1. cd boringssl-master/  
  2. mkdir build  
  3. cd build  
  4. cmake ../  
  5. make 

执行之后,可以在 build/crypto,和 build/ssl下获得对应的文件,如下图:

注意编译安装 boringSSL 需要使用 cmake3 以上的版本。

编译安装 nginx-quic: 

  1. cd nginx-quic/  
  2. ./auto/configure --prefix=/root/nginx --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-cc-opt="-I../boringssl-master/include" --with-ld-opt="-L../boringssl-master/build/ssl -L../boringssl-master/build/crypto" 
  3. make   
  4. make install 

执行命令之后,会在/root/nginx目录下生成对应的 nginx 可执行文件,如下图:

 

其中,配置文件在conf/下,nginx命令在sbin/目录下。

修改配置文件,启动 nginx: 

  1. vi /root/nginx/conf/nginx.conf 

添加 http3 配置: 

  1. server {  
  2.     listen 443 ssl http2;              # TCP listener for HTTP/2  
  3.     listen 443 http3 reuseport;  # UDP listener for QUIC+HTTP/3  
  4.     ssl_protocols       TLSv1.3; # QUIC requires TLS 1.3  
  5.     ssl_certificate     ssl/www.example.com.crt;  
  6.     ssl_certificate_key ssl/www.example.com.key;  
  7.     add_header Alt-Svc 'quic=":443"h3-27=":443";h3-25=":443"h3-T050=":443"h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"h3-Q046=":443"h3-Q043=":443"'; # Advertise that QUIC is available 
  8.  

其中,要求使用 TLSv1.3 版本,并且当浏览器不支持 http3 时,可以选择 http2。另外,add_header Alt-Svc添加这个返回头不可缺少。

  •  Alt-Svc 全称为 “Alternative-Service”,直译为“备选服务”。该头部列举了当前站点备选的访问方式列表,让服务器可以告诉客户端 “看,我在这个主机的这个端口用这个协议提供相同的服务”。一般用于在提供 “QUIC” 等新兴协议支持的同时,实现向下兼容。参考 MDN[8]。

验证 HTTP3 生效:

由于目前浏览器对HTTP3.0/QUIC的支持性有限,可以通过 http3check.net/[9] 来验证站点启用HTTP3是否成功,以我的站点为例:

坑点总结

整个过程看似很简单,但是真正配置过程中遇到了不少坑,前前后后加上搜索问题花了一天半的时间才真正解决,把这些问题记录下来,分享给大家。

开启 UDP 的 443 端口:

由于 quic 协议使用的是 UDP 的 443 端口,这个端口对于 centos7 来说是默认关闭的,可以采用下面命令开启: 

  1. firewall-cmd --zone=public --add-port=443/udp --permanent 

如果项目托管在阿里云上,需要更新 ECS 的安全组策略来对外开启对应的协议和端口,如下图:

TLS 版本向下兼容:

由于使用了 TLS 1.3,所以会修改对应加密算法,但是对于一些浏览器而言还不支持这么高的版本,尤其是对于苹果的 Safari,所以,在配置 nginx 配置文件时,要多配置几个版本向下兼容,代码如下:

  1. ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; 

-Werror 错误问题:

在编译 nginx-quic 时,有时会遇到如下错误: 

  1. cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ 
  2.  -o objs/src/os/unix/ngx_linux_sendfile_chain.o \  
  3.  src/os/unix/ngx_linux_sendfile_chain.c  
  4. cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ 
  5.  -o objs/src/event/ngx_event_openssl.o \  
  6.  src/event/ngx_event_openssl.c  
  7. cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ 
  8.  -o objs/src/event/ngx_event_openssl_stapling.o \  
  9.  src/event/ngx_event_openssl_stapling.c  
  10. cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ 
  11.   -o objs/src/event/ngx_event_quic.o \  
  12.  src/event/ngx_event_quic.c  
  13. cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ 
  14.   -o objs/src/event/ngx_event_quic_transport.o \  
  15.  src/event/ngx_event_quic_transport.c  
  16. src/event/ngx_event_quic_transport.c: In function ‘ngx_quic_create_stream’:  
  17. src/event/ngx_event_quic_transport.c:54:9: error: comparison is always true due to limited range of data type [-Werror=type-limits]  
  18.       : ((uint32_t) value) <= 16383 ? 2                                       \  
  19.          ^  
  20. src/event/ngx_event_quic_transport.c:1299:15: note: in expansion of macro ‘ngx_quic_varint_len’  
  21.          len = ngx_quic_varint_len(sf->type);  
  22.                ^  
  23. cc1: all warnings being treated as errors  
  24. make[1]: *** [objs/src/event/ngx_event_quic_transport.o] Error 1  
  25. make[1]: Leaving directory `/root/nginx-quic'  
  26. make: *** [build] Error 2  
  27. [root@iz2zehmi1ztqtx8tg6ca7gz nginx-quic]# 

解决办法是: 

  1. cd nginx-quic\objs  
  2. vi Makefile 

找到 CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include将 -Werror 参数去掉。

reuseport 只需配置一次:

假如有多个域名需要开启 http3,则 reuseport 建议只在根域名上配置,如果一个配置文件中出现多个 reuseport,会报错,配置如下: 

  1. server {          
  2.       listen 443 ssl http2;              # TCP listener for HTTP/2  
  3.       listen 443 http3 reuseport;  # UDP listener for QUIC+HTTP/3  
  4.       server_name  www.nihaoshijie.com.cn default_server;  
  5.   }  
  6.   server {  
  7.       listen 443 ssl http2;        # TCP listener for HTTP/2  
  8.       listen 443 http3;  # UDP listener for QUIC+HTTP/3  
  9.       server_name  app.nihaoshijie.com.cn; 
  10.   } 

编译安装时的性能问题:

如果编译安装时报类似下面的错误,可能是主机的内容不足,需要关闭一些运行的程序来往下进行。 

  1. ...  
  2. c++: internal compiler error: Killed (program cc1plus) 

快开启你的 HTTP3 之旅吧! 

 

责任编辑:庞桂玉 来源: 奇妙的Linux世界
相关推荐

2021-04-19 10:05:37

MozillaHTTPWeb服务器

2017-03-02 09:40:28

UbuntuCentOSNginx

2022-10-21 10:31:36

Arch LinuxSnap

2021-12-15 11:46:46

HTTP2Nginx

2019-04-22 11:50:38

LinuxFlatpak

2018-04-09 09:45:09

Windows 10休眠

2020-12-07 13:23:07

LibreOffice开源

2022-06-17 16:38:07

MozillaFirefoxcookie

2019-07-19 09:12:50

Windows 10平板电脑模式Windows

2022-11-25 10:19:48

2022-09-16 07:33:52

浏览器深色模式Firefox

2018-11-27 15:00:05

AnboxGoogle PlayARM

2019-07-31 10:36:38

FirefoxDNS-over-HT浏览器

2019-12-11 10:20:13

Windows 10鼠标指针Windows

2022-10-17 06:34:28

FedoraLinuxRPM Fusion

2022-11-08 11:39:34

Web浏览器深色模式

2016-08-29 21:36:55

nginxWeb缓存

2016-12-16 09:23:29

LinuxShell脚本

2022-05-20 13:46:36

Linux激活Linux水印

2011-08-01 17:30:06

ActiveDirec组策略磁盘配额
点赞
收藏

51CTO技术栈公众号