nginx对quic和http3的支持

  • Post author:
  • Post category:其他




概述

这篇文章前面是翻译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