惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
腾讯CDC
G
Google Developers Blog
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
有赞技术团队
有赞技术团队
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
美团技术团队
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志

atpX

自建 S3 兼容对象存储服务 Garage 听风的歌 偶尔是深夜就好了 新玩具 AirPods Pro 3 公交车上的时间 从 WHOIS 到 RDAP 通过 WireGuard 访问 NFS 共享文件 自建音乐串流服务探索 我停止了探索 Fediverse 互联网背景噪音 我的数字生活降级 小城与确定性的墙 一只特立独行的猪 Fediverse 与社交 承认的勇气 mediaX - 轻量书影音记录管理工具 我的博客写作流程 网站新增 Misc 页面 擅长对线的鲍勃 在 Chroot 环境下使用 Rsync 同步 再见 JavaScript 当我玩博客时我在玩什么 为什么我的博客没有友链页面 小熊猫与大熊猫 (HDR 照片测试) 使用 AdGuard Home 搭建自用 DoH 服务 谈谈读书与消遣 2023 年终总结 西安两日游 从 AirPods「升级」到 EarPods Docker 搭建去中心化的微博客平台 Mastodon
是时候为网站开启 HTTP/3 支持了吗
ATP · 2024-02-01 · via atpX

关于 HTTP/3,很久以前了解过,被多数文章和网友的一句国内运营商 UDP QoS 劝退,只留下了个「鸡肋」的印象。前段时间看了 Robin Marx 关于 HTTP/3 的系列文章,深入浅出的介绍了 HTTP/3 协议的历史和由来,性能优势和存在的问题,读完后受益匪浅,让我开始重新看待 HTTP/3。

互联网工程任务组 (IETF) 于 2022 年 6 月正式发布了 HTTP/3 。根据 W3Techs 统计,截至 2024 年 1 月,互联网上已经有 28.8% 的网站使用了 HTTP/3,那么,是时候为自己的网站开启 HTTP/3 支持了吗?

HTTP/3 简单介绍

首先,HTTP/3 的出现是为了解决一些历史问题,HTTP/1.1HTTP/2 都是基于 TCP 协议,TCP 作为互联网上使用和部署最广泛的协议之一,最早标准化于 1981 年发布的 RFC 793,如今已经显示出了一些瓶颈,QUIC(Quick UDP Internet Connections,读作 “quick”)协议成为它的预期替代品。

QUIC 协议于 2012 年由 Google 设计,并由 IETF 于 2021 年公布了 RFC 9000 标准。QUIC 是一个基于用户数据报协议 (UDP) 的传输协议,与 TLS 1.3 深度集成,保留 TCP 大多数优点的同时,带来了更高的安全性、更低的延迟以及更好的拥塞控制等特性。QUIC 之所以基于 UDP 也不是出于性能考虑,理想情况下应该是一个全新的独立协议,只是为了方便在现有的网络上部署。

但大家最初发现在 HTTP/2 上运行 QUIC 效率很低,有些特性很难实现,在几个关键地方进行修改后,推出了 HTTP/2-over-QUIC,出于多种原因,后命名为了 HTTP/3。也就是说,是为了使用 QUIC,才有了所谓的 HTTP/3。

这里需要泼一点冷水,HTTP/3 本身是对 HTTP/2 的修改,可能会让你的网上冲浪体验更好,但还不至于起飞,如果你的网络本来就很快,感知可能并不明显。我们常看到的会话恢复和 0-RTT 也不是 QUIC 的特定功能,实际上是 TLS 的功能,可以从下图中看到,即使开启了 0-RTT,QUIC (f) 仍然只比 TCP + TLS 1.3 (e) 快一次往返,所谓的快三次是和 TCP + TLS 1.2 (a) 相比,同时开启 0-RTT 还需要考虑更多的安全问题。但对于网速较慢且不太稳定的用户来说提升仍是很大的。

不同协议握手流程对比
不同协议握手流程对比。

还有一个需要考虑的现实是,UDP 通常被用于 DoS 攻击,因此许多企业网络和防火墙会选择禁止 UDP,QUIC 自然也无法使用。虽然 Google, Cloudflare, Amazon, Netflix 等网站早已经全面支持 HTTP/3,环大陆互联网上风生水起,但国内不少地区的运营商还在研究怎么 QoS UDP,国内用户目前有可能会得到更慢的体验。

一句话总结就是 HTTP/3 比 HTTP/2 更快更强,但普及还需要相当的时间,目前 HTTP/2 基本够用,不支持 HTTP/3 也无伤大雅。但 QUIC 作为下一代传输协议的趋势是肯定的,就我自己以文字为主的博客来说,先开为敬。

网站开启 HTTP/3

配置 Nginx 开启 HTTP/3 支持

最简单开启 HTTP/3 的方式就是使用免费的 Cloudflare CDN,会默认开启。如果不使用 CDN,HTTP/3 的普及很大程度上取决于 Nginx,Caddy,Apache 等 Web 服务器的支持程度。这里主要介绍 Nginx 开启 HTTP/3 支持的方法。

* 写本文时,Nginx 最新的稳定版本为 1.24.0,主线版本为 1.25.3。

Nginx 从 1.25.0 版本开始支持 QUIC 和 HTTP/3 协议 ,但目前还不能开启 early data(即 0-RTT,允许客户端在 TLS 握手完成之前发送应用程序数据),可能至少要等到明年 OpenSSL 发布支持 QUIC 的版本后才行,具体说明可以见文章:QUIC+HTTP/3 Support for OpenSSL with NGINX

安装 Nginx

如果你不需要开启 0-RTT,可以通过 Ngxin 官方库安装主线版本,这里以 Debian 系统 root 用户举例,其他 Linux 系统可以参考官方文档

# Install the prerequisites
apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring

# Import the official nginx signing key
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

# Set up the apt repository for mainline nginx packages
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
    | tee /etc/apt/sources.list.d/nginx.list

# Install nginx
apt update
apt install nginx=1.25.3

如果要想开启 0-RTT 可以选择自行编译,Nginx 建议使用一个支持 QUIC 的 SSL 库,例如 BoringSSLLibreSSL 或者 QuicTLS,三者最初都是 fork 自 OpenSSL,目前分别由 Google、OpenBSD、Akamai & Microsoft 维护。

我测试了使用 BoringSSL和 LibreSSL 构建都可以成功开启 0-RTT。需要注意的是 BoringSSL 虽然综合性能最好,但目前不支持 ssl_stapling,也就是 OCSP Stapling,需要曲线救国实现。同时还有个神奇的事,使用同样的 Nginx 配置文件和系统在三台服务器上测试脚本,编译 LibreSSL 后发现在其中两台服务器上能正常运行和访问,在另一台服务器上能正常运行 Nginx,但一访问就会报无限进程退出错误 worker process xxxxxxx exited on signal 11,排查通宵未果… 第二天又花了一下午排查才发现是权限问题,Nginx 配置中使用 user www-data 就会报错,使用 root 才能正常访问网站。然而三台服务器环境都一样,且所有 Nginx 目录包括证书文件和网站文件的权限也都是一样的,另两台服务器编译 BoringSSL 版本也不需要指定 Nginx 用户为 root,能正常运行和访问,就很迷惑,但已不想再深究。

这里不再详细介绍如何进行编译,如有需要可以前往 Github 参考我的 Nginx 编译安装脚本(不建议直接运行)。

配置 Nginx

一个简单的配置示例如下:

server {
    listen 80;
    listen [::]:80;
    server_name atpx.com;
    location / {
        add_header alt-svc 'h3=":443"; ma=86400';
        return 301 https://atpx.com$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;
    http2 on;

    server_name atpx.com;

    root /var/www/atpx.com;
    index index.html;

    ssl_certificate /path/to/ssl/atpx.com.pem;
    ssl_certificate_key /path/to/ssl/atpx.com.key;

    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;
    
    # Enabling 0-RTT.
    # ssl_early_data on;
    ssl_session_timeout 1h;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
  
    # Informs the client that HTTP/3 is available.
    add_header alt-svc 'h3=":443"; ma=86400';
}

更多具体配置你可以使用 Mozilla 的 SSL 配置生成工具。然后 Nginx 日志格式也可以在 http 段中修改:

# Log http3 requests
log_format  quic  '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent" "$http3"';
access_log /var/log/nginx/access.log quic;

需要注意的是:

  • 从 Nginx 1.25.0 开始,不再支持在 listen 中使用 http3 参数,需要修改为 quic
  • 从 Nginx 1.25.1 开始,不再支持在 listen 中使用 http2 参数,需要单独一行 http2 on
  • listen 中不能同时使用 sslquic 参数,须分为两行;
  • listen 段中的 reuseport 复用端口参数在所有 server 块里只允许出现一次;
  • 开启 0-RTT 可能会遭受重放攻击。

* 你可能会在配置文件中发现华点,Alt-Svc 标头要建立连接后才能获取,那首次连接呢?目前浏览器为了安全起见,首次连接仍会通过 HTTP2 或 HTTP/1.1 进行,发现 Alt-Svc 标头后才会尝试在后面的连接中使用 HTTP/3,这也是为什么你测试时会发现需要刷新一次网页后才能使用 HTTP3。解决办法是 DNS 中添加 SVCB/HTTPS 记录。

完成配置后需要重启 Nginx 并记得在防火墙放行 443 UDP。

最后,你可以通过 https://quic.nginx.org/ 检查你的浏览器是否支持 HTTP/3 连接(主流浏览器 Chrome 91+,Firefox 89+,Edge 90+ 等都已经默认开启 );通过 https://http3check.net/ 检查你的网站是否成功开启 HTTP/3 支持。