Enjoy your life

AEnjoy’s Blog

为你的服务器Nginx支持最新的quic

使用最新的nginx主线版本1.25,给网站开启quic支持。

本文不探讨手动编译,而是使用主线安装直接启用quic特性

环境:Debian12+nginx1.25

HTTP 3/QUIC介绍

QUIC/HTTP3 (Quick UDP Internet Connections), 快速 UDP 互联网连接,由Google在2015年提出的SPDY v3演化而来的新协议,传统的HTTP协议是基于传输层TCP的协议,而QUIC是基于传输层UDP上的协议,可以定义成:HTTP3.0基于UDP的安全可靠的HTTP2.0协议。 QUIC是基于UDP协议的,与传统的HTTP1.1/HTTP2不兼容,当浏览器不支持quic/http3时,会自动尝试使用http2、http1.1连接。

HTTP/3 基于 QUIC 传输协议,该协议专门用于支持多路复用连接,并摆脱了对单个 TCP 连接的依赖。QUIC 使用 UDP 作为在客户端和服务器之间的数据包底层传输机制,并为HTTP 请求提供可靠连接。值得注意的是,从HTTP2起,包括HTTP3/QUIC ,都将 TLS作为必选项(即强制加密),如果站点不支持ssl/tls,那就只能回到http1.1了。

主要特性:

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

安装主线nginx1.25版本

由于各大发行版(截止2024年1月9日,我测试了archLinux,openSUSE,Fedora,Debian,ubuntu23.10)目前还没有将1.25合并进存储库,因此我们需要手动添加1.25版nginx源.

参考nginx: Linux packages

本机环境:Debian 12

其它发行版操作类似

安装先决依赖:

1
apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring

下载nginx官方签名

1
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

导入签名

1
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

输出的内容应包含“573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62

例如:

1
2
3
pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid nginx signing key <signing-key@nginx.com>

如果不是,那么你需要重新下载并重新导入。

导入主线分支版本库:

1
2
3
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

固定使用nginx官方的包:

1
2
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx

(如果你已经安装了系统源带的nginx,请先卸载(你应该手动备份配置))

卸载系统自带的nginx

1
sudo apt remove nginx

安装nginx官方的nginx

1
2
sudo apt update
sudo apt install nginx

配置nginx.conf

注意:如果你从nginx1.24或更早的版本升级到1.25,应该注意几个重要变更,否则可能会因为nginx版本升级,配置部分选项弃用导致的error。

NGINX1.25重要变更

1.不再支持“http2”标记,已经默认ssl站点全部启用http2(该参数已弃用,但继续使用不会报错,只会报warning,你应该将站点中所有的http2参数移除)

listen 443 ssl http2;会出现警告

2.“ssl”参数完全丢弃,如果你的站点参数中有ssl参数,则会报error

如果有ssl on;则会报错

配置项

启用SSL:

由于http2、http3/quic强制加密,如果你的站点没有SSL支持,将不支持启用http2、http3/quic。

什么?你还没有ssl证书?你可以了解下acme.sh。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ssl_protocols  TLSv1.3; #启用TLS1.3加密(如果你考虑支持老旧浏览器和系统,则可以增加TLSv1.2,TLSv1.1)
ssl_certificate /root/uhttpd.crt;#SSL证书
ssl_certificate_key /root/uhttpd.key;#SSL密钥
ssl_ecdh_curve secp384r1;#SSL加密算法
ssl_stapling on;
# Path of the file with Diffie-Hellman parameters for EDH ciphers.
# TIP: Generate with: `sudo openssl dhparam -out /etc/nginx/dh2048.pem 2048`
#ssl_dhparam /etc/ssl/nginx/dh2048.pem;
ssl_dhparam /etc/nginx/dh2048.pem;#使用ssl_dhparam扩展,可以根据以上命令创建
# Specifies that our cipher suits should be preferred over client ciphers.
# Default is 'off'.
ssl_prefer_server_ciphers on;
# Enables a shared SSL cache with size that can hold around 8000 sessions.
# Default is 'none'.
ssl_session_cache shared:SSL:2m;
# Specifies a time during which a client may reuse the session parameters.
# Default is '5m'.
ssl_session_timeout 1h;
# Disable TLS session tickets (they are insecure). Default is 'on'.
ssl_session_tickets off;
ssl_early_data on; #开启 0-RTT的支持 quic部分特性

在全局段启用http3/quic支持:

在http{}内增加

1
2
3
quic_retry on;
quic_gso on;
http3 on;

在server{}段中有关quic的配置

增加单独的quic标记

1
2
listen 443 quic;
listen [::]:443 quic;

当然,如果只有这样的配置,那么站点就是只支持quic访问。我们可以增加传统http2支持

1
2
listen 443 ssl;
listen [::]:443 ssl;

这两端代码合在一起是可以的,不会报错。毕竟,quic监听的是443udp,ssl侦听的是443tcp。

此外,我们还要增加标头,向浏览器报告我们支持quic

在location中增加如下内容:

1
add_header Alt-Svc 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"';

这段代码的意思是,在443端口启用http3的以下草案支持:h3,h3-29,h3-q050,h3-q046,h3-q043,quic。

一段完整的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server{
#listen 80; #站点不支持传统http(可以设置一个默认监听80端口跳转至443)
#listen [::]:80;

listen 443 quic; #在IPv4/IPv6的443端口监听udp连接(quic/http3)
listen [::]:443 quic;

listen 443 ssl; #在IPv4/IPv6的443端口监听传统httptcp连接(默认http2、如若客户端不支持则变为http1.1)
listen [::]:443 ssl;

server_name xxx.sample.com;
location /{
add_header Alt-Svc 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"';
proxy_pass http://192.168.31.1;
}
}

保存,退出,重启nginx服务器

浏览器测试

使用最新版edge/chrome 打开F12,在网络栏的协议可以看到,已经启用http3/quic

h3

手机浏览器访问:(Chrome)

quic

Quic站点的好处:

1.加速访问

2.过滤GFW的TCP-SNI阻断(GFW目前还没有识别http3站点的技术),可以在DNS配置正确的情况下直接打开诸如 www.v2ex.com 这类的,只被DNS污染和SNI打断但又支持QUIC的站点。