HTTP/3和QUIC及其实现方式

一.HTTP/3和QUIC的基本原理

1.什么是http3?

HTTP/3 是即将到来的第三个主要版本的HTTP协议,使用于万维网。与其前任HTTP/1.1和HTTP/2不同,在HTTP/3中,将弃用TCP协议,改为使用基于UDP协议的QUIC协议实现

 

2.解决什么问题?

此变化主要为了解决HTTP/2中存在的队头阻塞问题。由于HTTP/2在单个TCP连接上使用了多路复用,受到TCP拥塞控制的影响,少量的丢包就可能导致整个TCP连接上的所有流被阻塞。

3.发展历史:

QUIC(快速UDP网络连接,即Quick UDP Internet Connections)是一种实验性的网络传输协议,由Google开发,该协议旨在使网页传输更快。在2018年10月28日的邮件列表讨论中,互联网工程任务组(IETF) HTTP和QUIC工作组主席Mark Nottingham提出了将HTTP-over-QUIC更名为HTTP/3的正式请求,以“明确地将其标识为HTTP语义的另一个绑定……使人们理解它与QUIC的不同”,并在最终确定并发布草案后,将QUIC工作组继承到HTTP工作组。在随后的几天讨论中,Mark Nottingham的提议得到了IETF成员的接受,他们在2018年11月给出了官方批准,认可HTTP-over-QUIC成为HTTP/3。

 

 

关于quic的详细介绍,可以参考:https://blog.cloudflare.com/the-road-to-quic/

2019年9月,HTTP/3支持已添加到Cloudflare和Google Chrome(Canary build)。Firefox Nightly将在2019年秋季之后添加支持。

截至2021年1月,HTTP/3仍然是草案状态

参考:from:https://zh.wikipedia.org/wiki/HTTP/3

4.优势有哪些?

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

二.HTTP/3和QUIC的实现方式

1.方案选择

对于HTTP3.0,由于整个协议还是处于草案阶段,目前来说没有一个完整的标准,对于Nginx来说,支持HTTP3.0目前有两种方案可以选择:

  • 基于Cloudflare的分支版本Nginx:对于HTTP3.0/QUIC,Cloudflare始终走在了前列,借助于自家维护的开源项目quic,从Nginx中拉出了一个分支来开发,并编译出了对HTTP3.0支持的Nginx服务器。
  • Nginx官方Nginx-quic项目:去年6月10日,Nginx官博发布公告称已经在研发支持HTTP3.0/QUIC协议的工作,目前项目维护在nginx-quic,该项目和基于Cloudflare基于Nginx的分支并无关系,算是相对于正统的方案。

2.下面采用基于Cloudflare的分支版本Nginx的方式实现http/3

a.系统环境及相关依赖的软件安装和升级

[root@li1548-187 ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@li1548-187 ~]# uname -a
Linux li1548-187 3.10.0-957.12.2.el7.x86_64 #1 SMP Tue May 14 21:24:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

#TLS1.3 需要 OpenSSL 1.1.1 以上版本,系统自带版本一般较旧,我们需要重新安装(但是下文中的 quiche patch 中已经内置了 Boringssl,不需要再重新安装,我这里就不用系统的OpenSSL,而使用boringssl

#安装openssl1.1.1

yum install -y openssl-devel openssl11 openssl11-devel

编译主要需要注意的问题是设置编译FLAG,以便使用最新的openssl库
export CFLAGS=$(pkg-config --cflags openssl11)
export LDFLAGS=$(pkg-config --libs openssl11)

PS:关于什么是boringssl,请参考下面的链接:

1)https://boringssl.googlesource.com/boringssl/

2)https://imququ.com/post/optimize-ssl-ciphers-with-boringssl.html

3)系统的gcc的版本一定要至少大于4.9,否则在编译Nginx的时候会出错,升级gcc请参考:https://teddylu.xyz/blog/4149.html

#安装rust,为了支持 quiche,Rust 需要至少 1.39 版本

yum install clang go rust cargo -y

#下载 Brotli:

Brotli is a generic-purpose lossless compression algorithm (Brotli是一种通用无损压缩算法)that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling, with a compression ratio comparable to the best currently available general-purpose compression methods. It is similar in speed with deflate but offers more dense compression.

git clone https://github.com/google/ngx_brotli
cd ngx_brotli
git submodule update --init

#升级cmake的版本,否则编译的时候会出现错误:CMake 3.0 or higher is required. You are running version 2.8.12.2

wget https://cmake.org/files/v3.20/cmake-3.20.0-rc5.tar.gz
cd cmake-3.20.0-rc5/
./bootstrap
gmake
gmake install

如果本地使用了yum进行安装过,则需要卸载

[root@li1548-187 cmake-3.20.0-rc5]#yum remove cmake -y
[root@li1548-187 cmake-3.20.0-rc5]# ln -s /usr/local/bin/cmake /usr/bin/cmake
[root@li1548-187 cmake-3.20.0-rc5]# cmake --version
cmake version 3.20.0-rc5

CMake suite maintained and supported by Kitware (kitware.com/cmake).

#安装新版本的perl

wget https://www.cpan.org/src/5.0/perl-5.30.3.tar.gz

tar xf perl-5.30.3.tar.gz
cd perl-5.30.3

./Configure -des -Dprefix=/usr/mysf
make
make test
make install

# 建立新的软链接
mv /usr/bin/perl /usr/bin/perl.bak
ln -s /usr/mysf/bin/perl /usr/bin/perl

# 检查是否安装成功
perl -v

[root@li1548-187 teddylu]# perl -v

This is perl 5, version 30, subversion 3 (v5.30.3) built for x86_64-linux

b.目前,最新版本的 nginx (nginx-1.19.0) 仍然不能原生支持 HTTP3,好在 CloudFlare 提供了基于 Quiche 和 Boringssl 实现的一个 patch,使得我们可以在 nginx 上尝鲜一下。下载最新版本 nginx 并打上 quiche 的 patch

wget http://nginx.org/download/nginx-1.19.0.tar.gz

tar xf nginx-1.19.0.tar.gz

[root@li1548-187 ~]# git clone --recursive https://github.com/cloudflare/quiche
Cloning into 'quiche'...
remote: Enumerating objects: 252, done.
remote: Counting objects: 100% (252/252), done.
remote: Compressing objects: 100% (139/139), done.
remote: Total 13454 (delta 128), reused 184 (delta 98), pack-reused 13202
Receiving objects: 100% (13454/13454), 15.60 MiB | 13.11 MiB/s, done.
Resolving deltas: 100% (7253/7253), done.
Submodule 'boringssl' (https://github.com/google/boringssl.git) registered for path 'deps/boringssl'
Cloning into 'deps/boringssl'...
remote: Enumerating objects: 477, done.
remote: Counting objects: 100% (477/477), done.
remote: Compressing objects: 100% (304/304), done.
remote: Total 80174 (delta 279), reused 295 (delta 161), pack-reused 79697
Receiving objects: 100% (80174/80174), 165.46 MiB | 27.14 MiB/s, done.
Resolving deltas: 100% (56884/56884), done.
Submodule path 'deps/boringssl': checked out '067cfd92f4d7da0edfa073b096d090b98a83b860'

#打入quiche的path,官方说是支持nginx-1.16.1版,其实nginx-1.19.0版也是支持的
[root@li1548-187 ~]# tar xf nginx-1.19.0.tar.gz
[root@li1548-187 ~]# cd nginx-1.19.0
[root@li1548-187 nginx-1.18.0]# patch -p01 < ../quiche/extras/nginx/nginx-1.16.patch

c.安装 nginx(编译的时候一定要升级gcc,否则会报错,参考:https://teddylu.xyz/blog/4149.html)

./configure \
--prefix=/application/nginx-1.19.0 \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_geoip_module \
--with-threads \
--with-stream \
--with-quiche=/root/quiche \
--with-openssl=/root/quiche/deps/boringssl \
--with-http_stub_status_module
make && make install

d.配置nginx
listen 443 quic reuseport;
listen 443 ssl http2 fastopen=3 reuseport;
listen [2400:8002::f03c:91ff:fpe0:7653]:443 ssl http2;
listen [2400:8002::f03c:91ff:fpe0:7653]:443 quic;

PS:为啥要同时启用http2和http3的ipv4和ipv6呢?

a.一个是因为我机器上有2种类型的ip

b.如果只启用http/3的而不启用http2,那么所有使用不支持http/3的浏览器的用户将无法访问网站,所以这样做的目的是同时兼顾只能使用支持http/2的浏览器的用户!!!

#要支持quic必须要开启TLSv1.3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

#Alt-Svc响应头
add_header alt-svc ‘h3-27=”:443″; ma=86400,h3-29=”:443″; ma=86400’;

3.测试HTTP/3支持

UDP端口测试

QUIC-HTTP/3是基于UDP协议的,因此需要开放服务器的UDP 443端口

#ipv4
-A INPUT -p udp -m udp –dport 443 -j ACCEPT

#ipv6
-A INPUT -p udp -m state –state NEW -m udp –dport 443 -j ACCEPT

以上是针对既有ipv4也有ipv6的机器上,分别在其对应的防火墙上开启udp的443端口

在本地电脑上,执行下面的命令:

nc -v -u 1.2.3.4 443

其中,1.2.3.4为您的服务器IP地址,若收到类似下面的回显,则说明进入服务器的UDP 443端口开放了。

[root@docker02 ~]# nc -v -u 1.2.3.4 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 1.2.3.4:443.

[root@docker02 ~]# nc -v -u google.com 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 93.46.8.90:443.

网站测试

目前,有两个网站可以用来测试我们的网站是否支持QUIC-HTTP/3。

这两个网站分别是:

https://gf.dev/http3-test

https://http3check.net/

输入自己的域名即可测试网站是不是支持http/3

浏览器开启http3

Firefox开启http3

首先在火狐地址栏输入:about:config

然后搜索http3,找到network.http.http3.enabled 把 false 改成 true,重启、就可以了。

 

Chrome canary开启http3

注意,只有金丝雀版chrome才支持http3,在地址栏输入 chrome://flags/

搜索quic,找到Experimental QUIC protocolDefault改成Enabled,重启浏览器。

然后,在Chrome canary的快捷方式,右键、属性,在目标栏尾处添加--enable-quic --quic-version=h3-29 即可。

最后,在浏览支持http3的网站时,按f12键可以查看网络、协议显示为HTTP/3或者h3-29.

(ps.使用Google Chrome Canary没有看到页面显示为http/3,原因待查!!!)

修正:

下面是firefox浏览器的对源站和cloudflare站点的http/3的支持的具体的信息:

源站的http/3的相关信息
cloudflare的http/3的相关详细信息

参考:

https://starts.sh/posts/nginx_http3.html

 

HTTP/3和QUIC及其实现方式
0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Scroll to top
0
Would love your thoughts, please comment.x
()
x