安装 nginx-quic,启用 HTTP/3
本文最后更新于:2022年3月19日 早上
计算机网络技术日新月异,智能手机已成为人类生活必需品,全球网络用户爆发式增长,人们对网络的需求越发的强烈。老旧的互联网协议无法满足现阶段人们的需求,特别是超文本传输协议(HyperText Transfer Protocol,缩写:HTTP)这种用户使用最多应用层协议,其发展改变了人们浏览网页、观看视频、收听音乐的方式。
在 2018 年 10 月 28 日的邮件列表讨论中,互联网工程任务组(Internet Engineering Task Force,缩写 IETF)HTTP 和 QUIC 工作组主席 Mark Nottingham 提出了将 HTTP-over-QUIC 更名为 HTTP/3 的正式请求,这是 Web 的新标准,可实现更快、更可靠、更安全的 Web 终端(如网站和 API)连接[1]。
Nginx 是一个非常优秀的开源网页服务器(Web Server),2020 年 F5, Inc 创建了 nginx-quic 分支来支持 QUIC+HTTP/3[2]。我们可以在 Mercurial 代码库中下载最新的 nginx-quic 源码,通过编译安装 nginx-quic 来给网站提供 HTTP/3 的支持。
一、什么是 HTTP/3
HTTP/3 是自 2015 年 HTTP/2 标准获得批准以来对超文本传输协议的首次重大升级。与其前任 HTTP/1.1 和 HTTP/2 不同,HTTP/3 将弃用 TCP 协议,改用基于 UDP 的 QUIC 协议。此变化主要为了解决 HTTP/2 中存在的队头阻塞问题。由于 HTTP/2 在单个 TCP 连接上使用了多路复用,受到 TCP 拥塞控制的影响,少量的丢包就可能导致整个 TCP 连接上的所有流被阻塞[3]。
图1 对HTTP传输协议堆栈的概述[4]
基于 UDP 的 QUIC 协议能够改善 HTTP/2 的显著缺点[5],包括:
- 解决智能手机从 WiFi 切换到蜂窝数据时(例如离开家或办公室时)网络连接卡顿或者重连的问题
- 减少数据包丢失的影响。当一个数据包无法到达目的地时,它将不再阻塞所有信息流(这个问题称为”队头阻塞”)
其优势包括:
- 更快地建立连接:QUIC 允许 TLS 版本协商与加密以及传输握手同时进行
- 零往返时间(0-RTT):对于已经连接到的服务器,客户端可以跳过握手要求(相互确认和验证以确定它们将如何通信的过程)
- 更全面的加密:QUIC 的新握手方法将默认提供加密。这是对 HTTP/2 的一次重要升级,有助于降低攻击风险。
目前,服务端上,Nginx、Windows Server 2022 和 Windows 11 中的 IIS 均已支持 QUIC,Cloudflare 也在其 CDN 服务中开启 QUIC。客户端上,Google Chrome 和 Microsoft Edge 87 及以上版本、Firefox 88 及以上版本都已默认开启了对 HTTP/3 的支持。macOS Big Sur 11 和 iOS 14 中的 Safari 开始实验性的支持 HTTP/3,但是默认没有启用。
图2 Windows Server 2022和Windows 11的IIS默认启用QUIC
这篇文章主要介绍如何在 ubuntu 20.02 LTS 上安装 nginx-quic 来搭建 Web 服务器,并启用网站对 HTTP/3 的支持。
二、编译安装 nginx-quic
我们在 Mercurial 代码库中下载最新的 nginx-quic 源码,进行编译安装。
1. 搭建编译环境
编译程序需要先搭建编译环境,安装依赖库以及编译所需要的工具。在终端输入以下指令:
1 |
|
详细说明
build-essential
和libtool
是编译所必需的软件,包括gcc
、g++
、make
等。必需!git
和mercurial
用于从 Github 和 Mercurial 上下载源码。必需!libpcre2-dev
是 nginx 支持 perl 兼容的正则表达式的依赖库。必需!zlib1g-dev
是 nginx 启用 gzip 压缩的依赖库。推荐!
2. 下载 nginx-quic 源码文件
1 |
|
定义 NGINX_VERSION
和 NGINX_COMMIT
变量,主要是为了方便大家在 hg.nginx.org 上检索最新的 nginx-quic 提交版本。由于 nginx-quic 仍属于实验性版本,请确保你所安装的 nginx-quic 永远是最新的。
3. 下载和编译 quictls
QuicTLS 是 OpenSSL 的一个分支,其中添加了可供 QUIC 实现 TLS 握手的 API,用于启用 nginx 的 http_v3_module。
1 |
|
4. 下载 nginx brotli 压缩模块(推荐)
Brotli 是一款通用的无损压缩算法,它使用 LZ77 算法的一种现代变体(a modern variant of the LZ77 algorithm)、霍夫曼编码(Huffman coding)和二阶上下文建模(2nd order context modeling)的组合来压缩数据,其压缩率可与当前最佳的通用压缩方法相媲美。它在压缩速度上与 deflate 相似,但提供更高的压缩率,开启 Brotli 压缩可以优化网站访问速度[6]。
我们需要从 Github 下载 ngx_brotli 源码,并在编译 nginx 时加入这个模块:
1 |
|
5. 下载 ngx_security_headers 模块 (推荐)
这个模块可以给 nginx 自动添加安全响应头或者移除一些不安全的响应头,非常推荐编译进 nginx 中。
1 |
|
6. 编译安装 nginx
和 Windows 系统中安装程序类似,我们需要自定义程序的安装路径,并设置程序所需启用的功能和模块。
1 |
|
定义 $CONFIG
变量是为了方便选择想启用的功能[7]。
详细说明
--with-http_ssl_module
为 HTTPS 提供必要的支持。必需!--with-http_realip_module
用于透过代理(反代服务器或 CDN)获取客户端的真实 IP 地址。推荐!--with-http_gzip_static_module
允许发送以 .gz 结尾的预压缩文件替代普通文件。推荐!--with-http_gunzip_module
是一个过滤器,用于对不支持 gzip 编码方法的客户端解压缩。需要存储压缩数据以节省空间并降低 I/O 成本时,且配置了gzip_static always;
时,该模块将非常有用。推荐!--with-http_secure_link_module
用于开启防盗链功能,检查请求链接的真实性,保护资源免受未经授权的访问,并限制链接有效时长。可选--with-http_stub_status_module
提供对基本状态信息的访问的支持。可选--with-http_auth_request_module
基于子请求结果实现客户端授权。如果子请求返回一个 2xx 响应代码,则允许访问。如果返回 401 或 403,则拒绝访问并抛出相应的错误代码。子请求返回的任何其他响应代码被认为是一个错误。可选--with-http_slice_module
模块用在 proxy_cache 大文件的场景,将大文件切片缓存。通常用在 CDN 的 Range 缓存上。可选--with-stream
等模块用来实现四层协议的转发、代理或者负载均衡。可选--with-threads
和--with-file-aio
启用线程池和异步 I/O,可以加快 nginx 运行速度。推荐!--with-compat
可以让 nginx 在不重新编译的情况下动态加载模块。推荐!--with-http_v2_module
和--with-http_v3_module
用于开启 HTTP/2 和 HTTP/3 的支持。必需!--add-module=/usr/src/ngx_brotli
将 brotli 压缩模块编译到 nginx,使 nginx 支持 brotli 压缩。推荐!--add-module=/usr/src/ngx_security_headers
将 ngx_security_headers 模块编译到 nginx。推荐!
Nginx 编译时不是功能加的越多越好,应该尽可能少编译模块,不用的最好不要加入,直接在 $CONFIG
中删掉对应的行即可。定义好 $CONFIG
变量后进行配置:
1 |
|
配置结束后,注意查看屏幕上显示的结果,被添加的模块其依赖库应该都被找到,如下面所示:
1 |
|
特别注意屏幕上 OpenSSL QUIC support
是否显示为 found
。OpenSSL QUIC support
是启用 HTTP/3 的关键,如果是 not found
,则需要检查上一步 configure 时填写的 quictls 的 include
和 lib64
目录路径是否正确。
配置无误后,便可以进行编译安装了,终端中输入以下指令:
1 |
|
7. 检查 nginx
至此,nginx 就已经安装好了,你可以通过在终端中输入 nginx -V
,查看 nginx 的版本和编译选项:
1 |
|
8. 添加 nginx.service 使其开机自启
(1) 添加 nginx 服务
首先在 /usr/lib/systemd/system
目录下新建 nginx.service
,在终端中输入以下指令:
1 |
|
(2) 重新加载 systemd
1 |
|
(3) 设置 nginx 开机自启动
1 |
|
(4) nginx 服务常用操作
1 |
|
三、配置 nginx.conf 启用 HTTP/3
HTTP/3 使用 QUIC 协议,并且使用 TLS 1.3 进行加密。若要开启网页对 HTTP/3 的支持,必须开启 QUIC 端口(为了更好的兼容性,通常将 quic 和 https 设置为相同的端口),并使用 TLS 1.3 协议加密。你需要在 /etc/nginx/nginx.conf
中进行设置:
1 |
|
在正确设置 nginx.conf
后,网站依然没有启用 HTTP/3,极有可能是你没有在防火墙中打开 QUIC 对应的 UDP 端口,因为 QUIC 协议基于 UDP 协议进行传输。
图3 防火墙中开启UDP端口
若需开启 0-RTT,可以在 server 块或 location 块中添加 ssl_early_data on;
四、测试网站是否支持 HTTP/3
测试网站是否支持 HTTP/3 的最简单方法就是在 http3check.net 上输入域名进行测试。
图4 http3check.net测试结果
当然也可以通过浏览器的开发人员工具来查看是否开启 HTTP/3 访问。
图5 浏览器开发人员工具中查看网站是否开启http3
同样也可以在手机上查看,是否使用 QUIC 连接访问网站。
图6 手机浏览器中查看是否使用QUIC进行连接
由于最新版本的 nginx-quic 弃用了 QUIC 的互联网候选版本(Internet drafts),仅支持 IETF QUIC 第一版。所以目前支持最新版本的 nginx-quic 的客户端只有 Firefox 90+ 和 Chrome 92+ (QUIC version 1)[8]。
五、总结
HTTP/3 是未来趋势,越来越多的网站开始启用 HTTP/3,它的潜力将在不久的未来被开发到极致。我们现在就可以开始部署,让你的网站有更完美的浏览体验。
参考资料
- Nottingham, Mark. Identifying our deliverables. IETF Mail Archive. October 28, 2018 ↩
- Liam Crilly. Our Roadmap for QUIC and HTTP/3 Support in NGINX. July 12, 2021 ↩
- HTTP/3 - 维基百科,自由的百科全书. (https://zh.wikipedia.org/wiki/多重要素驗證) ↩
- Liam Crilly. Introducing a Technology Preview of NGINX Support for QUIC and HTTP/3. June 10, 2020 ↩
- What is HTTP/3? (https://www.cloudflare.com/zh-cn/learning/performance/what-is-http3/) ↩
- Github - google/ngx_brotli: NGINX module for Brotli compression. (https://github.com/google/ngx_brotli) ↩
- NGINX中文文档. (https://docshome.gitbook.io/nginx-docs/he-xin-gong-neng/http) ↩
- README: Experimental QUIC support for nginx. (https://quic.nginx.org/readme.html) ↩