概述
这篇文章前面是翻译nginx对quic和http3实验介绍的一篇英文文章,原文地址是
Experimental QUIC support for nginx
另外一篇文章我会测试分享我使用quic的经验。
介绍
这是一个对nginx支持quic和http3特性的预览版。
这些代码是单独的“quic”分支,在
https://hg.nginx.org/nginx-quic
可以找到。这些代码是基于 1.19.x. 版本的nginx开发,我们现在打算在下一个nginx发布版本中将这个分支合并进去。
代码是和nginx一样的BSD许可协议。
我们正努力支持http3,以便于将它集成到主要的nginx代码库中。我们会经常的更新这些代码,不要出于任何目的依赖这些代码。
我们非常高兴你能反馈任何问题或者对功能作出贡献,但是我们也不会对这块代码产生的任何问题负责。
你能通过nginx-devel mailing list(nginx 开发者邮箱列表)在任何时候联系我们
现在的工作:
我们支持IETF-QUIC draft-27, draft-28,draft-29。
因为和早期的草案有不兼容情况,所以早期的草案我们没有支持。
你可以通过修改在
src/event/ngx_evejnt_quic.h
中的
NGX_QUIC_DRAFT_VERSION
宏的值来选择使用的版本。
nginx现在能响应简单的http3请求,并且能进行大文件的上传和下载。
- 握手完成
- 一端能更新密钥并且对端能正常响应
- 能正常收到0-RTT并且作出响应
- 能通过TLS Resume Ticket建立链接
- 在握手的时候有重试的包也能正常握手
- 流数据能正常的交互并且响应
- 一次http3成功交互
- 一端或者两端在dynamic table动态表中插入,接下来在头部中引用他们
- 当客户端不知道版本时会发送版本包
- 检测到丢失的数据包,并且重传
还没有完成的功能
- 指定ECN(拥塞控制)算法
- 带有旋转比特位链接在建立成功后bit位旋转
- 结构化日志
- NAT重绑定
- 地址移动
- http3分块传输编码
一些功直到放开实验还处于被开发中,很多功能还没有期望中起作用,例如:
- 简单的ACK处理:确认每一个收到的包,没有使用ack ranges
- 简单的流量控制:为了避免大量的cpu消耗,使交互更加简单
- 没有严格遵循草案:为了方便第一版本实现,一些检测没有严格遵循草案
安装
你需要BoringSSL库提供QUIC支持
$ hg clone -b quic https://hg.nginx.org/nginx-quic
$ cd nginx-quic
$ ./auto/configure --with-debug --with-http_v3_module \
--with-cc-opt="-I../boringssl/include" \
--with-ld-opt="-L../boringssl/build/ssl \
-L../boringssl/build/crypto"
$ make
当安装nginx时,你可以使用以下的配置开启http3和QUIC功能:
--with-http_v3_module - enable QUIC and HTTP/3
--with-http_quic_module - enable QUIC for older HTTP versions
--with-stream_quic_module - enable QUIC in Stream
配置
当使用HTTP的“listen”配置的时候,你可以在后面添加两个新的选项:“http3” 和 “quic”。
“http3”表示这个端口需要使用基于quic的http3来监听。
“quic”表示需要使用quic监听这个端口,不一定使用http3。
当使用Stream的“listen”配置的时候,你可以在后面加上“quic”,用于开启QUIC作为传输协议用于代替tcp和udp。
当你使用“http3”和“quic”配置时,你也可以启用“reuseport”选项,是他在多个workers上工作。
一些可以设定QUIC协议的参数:
quic_max_idle_timeout
quic_max_ack_delay
quic_max_packet_size
quic_initial_max_data
quic_initial_max_stream_data_bidi_local
quic_initial_max_stream_data_bidi_remote
quic_initial_max_stream_data_uni
quic_initial_max_streams_bidi
quic_initial_max_streams_uni
quic_ack_delay_exponent
quic_active_migration
quic_active_connection_id_limit
开启address validation特性
quic_retry on;
开启0-RTT特性
ssl+early_data on;
在使用QUIC时确保TLS是1.3版本
ssl_protocols TLSV1.3;
一些可以设定HTTP/3协议的参数
http3_max_field_size
http3_max_table_capacity
http3_max_blocked_streams
http3_max_concurrent_pushes
http3_push
http3_push_preload
两个变量被添加:
$quic
和
$http3
。
当QUIC 链接被使用时,
$quic
表示“quic”,别的情况是空字符串。
$http3
是一个字符串“h3-xx”,“xx”表示草案的版本。
例子:
http {
log_format quic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$quic" "$http3"';
access_log logs/access.log quic;
server {
# for better compatibility it's recommended
# to use the same port for quic and https
listen 8443 http3 reuseport;
listen 8443 ssl;
ssl_certificate certs/example.com.crt;
ssl_certificate_key certs/example.com.key;
ssl_protocols TLSv1.3;
location / {
# required for browsers to direct them into quic port
add_header Alt-Svc '$http3=":8443"; ma=86400';
}
}
}
客户端
浏览器
已知的:Firefox 75+ and Chrome 83+
防止奇怪的问题:一些浏览器会忽略QUIC。 缓存clearing/restart会有此帮助。检查access.log和error.log去确认使用的是http3而不是TCP https。
-
在Firefox开启QUIC,使用
network.http.http3.enabled = true
在
about:config
- 在chrome开启QUIC,并强制在你的网页中使用QUIC。
$ ./chrome --enable-quic --quic-version=h3-29 \
--origin-to-force-quic-on=example.com:8443
命令行
已知的:ngtcp2, firefox的neqo 和 chromium的命令行工具。
$ examples/client 127.0.0.1 8443 https://example.com:8443/index.html
$ ./neqo-client https://127.0.0.1:8443/
$ chromium-build/out/my_build/quic_client http://example.com:8443 \
--quic_version=h3-29 \
--allow_unknown_root_cert \
--disable_certificate_verification
如果你使用正确,你会在access日志中看到一些类似于下面的:
127.0.0.1 - - [24/Apr/2020:11:27:29 +0300] "GET / HTTP/3" 200 805 "-" "nghttp3/ngtcp2 client" "quic" "h3-29"
常见问题
这边有一些技巧用于你确认问题:
- 确认你使用的SSL library实现了29草案
-
确认你运行的时候使用了正确的SSL library(
nginx -V
可以显示你用了什么) -
确认你客户端使用了QUIC的请求(参考“客户端”关于浏览器和缓存问题)
我们比较建议你使用类似于ngtcp2命令行工具,以确保在你使用浏览器的时候之前你服务端配置正确 - 在构建nginx时候加上debug支持,它会在日志里面显示所有链接和失败的信息。所有相关包含“quic”前缀的信息可以快速被筛选出来
-
如果你想使用了解更清楚,你可以在
src/event/ngx_event_quic.h
中添加下列信息
#define NGX_QUIC_DEBUG_PACKETS
#define NGX_QUIC_DEBUG_FRAMES
#define NGX_QUIC_DEBUG_FRAMES_ALLOC
#define NGX_QUIC_DEBUG_CRYPTO
如何贡献力量
如果你想贡献力量,你可以看这个链接
http://nginx.org/en/docs/contributing_changes.html
链接
https://tools.ietf.org/html/draft-ietf-quic-transport-29
https://tools.ietf.org/html/draft-ietf-quic-http-29
https://mailman.nginx.org/mailman/listinfo/nginx-devel
https://boringssl.googlesource.com/boringssl/
https://tools.ietf.org/html/draft-ietf-quic-recovery-29
https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
https://nginx.org/en/docs/debugging_log.html