🙈 By 李崇民 2023-09-20
HTTP3 国密支持
通过修改,在QUIC协议支持的加密套件中增加了国密套件TLS_SM4_GCM_SM3,目前可以用支持QUIC协议及该加密套件的客户端访问。
1. QUIC协议
QUIC(Quick UDP Internet Connection)是谷歌推出的一套基于UDP的传输协议,它实现了TCP + HTTPS + HTTP/2的功能,目的是保证可靠性的同时降低网络延迟。因为UDP是一个简单传输协议,基于UDP可以摆脱TCP传输确认、重传慢启动等因素,建立安全连接只需要一的个往返时间,它还实现了HTTP/2多路复用、头部压缩等功能。
2. HTTP3协议:
HTTP3是HTTP协议的最新版本。HTTP/3是为了处理HTTP/2.0的传输相关问题而生的,可以在各种设备上更快地访问Web。它基于一个新的传输层协议,就是上面提到的QUIC协议。
现在,随着智能手机和便携式设备的数量超过台式机和笔记本电脑的数量,超过50%的互联网流量已经通过无线传输。这种趋势给整体的网络浏览体验带来了问题,其中最重要的是在无线覆盖率不足的情况下,TCP中的行头阻塞。Google的一些实验证明,QUIC作为Google部分热门服务的底层传输协议,极大地提高了速度和用户体验。部署QUIC作为YouTube视频的底层传输协议,导致YouTube视频流的缓冲率下降了30%,这直接影响了用户的视频观看体验。在显示谷歌搜索结果时,也有类似的改善。网络条件较差的情况下提升非常明显,这促使谷歌更加积极地完善该协议,并最终向IETF提出标准化。
3. TLSv1.3
TLSv1.3是TLS协议更新中变化非常大的一个版本,加入了许多新的特性和性能优化,并且不完全前向兼容,因此也有些人认为应该称为TLSv2.0,不过最后还是命名为TLSv1.3。
针对TLSv1.2中存在的安全和性能问题,TLSv1.3在设计的时候就放弃了前向兼容性,不再对之前的版本进行兼容,同时禁用了大量不安全的算法,使用了少量安全的算法来设计协议,这样的好处就是可以简化握手过程中的操作,使得握手过程从2-RTT变为1-RTT,同时有效提高安全性和性能。QUIC协议使用TLSv1.3来保证数据安全传输。
3. 国密算法
国密即国家密码局认定的国产密码算法。主要有 SM1、SM2、SM3、SM4。密钥长度和分组长度均为 128 位。SM1 为对称加密,SM2 为非对称加密,SM3 消息摘要,SM4 分组密码算法。
4. 相关的RFC
与本文相关的主要有:
- RFC8999:《商密算法在TLS 1.3中的应用》
- RFC8999:《QUIC版本通用属性(Version-Independent Properties of QUIC)》
- RFC9000:《QUIC,一种基于UDP的安全多路复用传输协议(QUIC: A UDP-Based Multiplexed and Secure Transport)》
- RFC9001:《使用TLS保护QUIC(Using TLS to Secure QUIC)》
- RFC9114:《HTTP/3》
5. 修改思路及效果
在RFC9001中规定了quic包传输时,除了数据包传输要用到加密算法外,还规定了头保护的加密算法,这个算法是与数据包加密算法对应的。RFC8998中给出了两种国密算法套件,TLS_SM4_GCM_SM3和TLS_SM4_CM_SM3。Tongsuo8.3.0中支持了这两种套件。因此可以在njet的quic协议初始化加密套件时,尝试增加对国密套件的支持。经过多次尝试后,可以成功支持TLS_SM4_GCM_SM3套件。同时通过对xquic的实现代码进行修改来支持在客户端使用TLS_SM4_GCM_SM3套件。
最终测试结果如下:查看body.txt可以看到具体内容为njet.org.cn的首页内容,说明传输成功。用wireshark抓包,可以看出quic协议在握手时指定的加密套件为TLS_SM4_GCM_SM3。本功能目前在http3分支上提交。
[root@cdn108 build]# ./test_client -G -a 192.168.40.108 -p 8443 -h njet.org.cn -u https://njet.org.cn/ -w body.txt
option get :on
option addr :192.168.40.108
option port :8443
option host & sni :njet.org.cn
option url :https://njet.org.cn/
option save body :body.txt
congestion control flags: 0
read token error No such file or directory
sessoin data read error or use_1rtt
conn type: 0
/root/xquic-main/tests/test_client.c:1771 (xqc_client_h3_conn_create_notify)
xqc_h3_conn_is_ready_to_send_early_data:0
[h3-dgram]|prepare_dgram_user_data|
xqc_h3_request_send_headers success size=20
save_tp_cb use server domain as the key. h3[0]
/root/xquic-main/tests/test_client.c:1855 (xqc_client_h3_conn_handshake_finished)
0rtt_flag:0
====>DCID:3302c7cfc71df12d7bc023299387f64186c8a312
====>SCID:cf2939ba1dbfd2b3
/root/xquic-main/tests/test_client.c:1900 (xqc_client_h3_conn_ping_acked_notify)
====>no ping_id
/root/xquic-main/tests/test_client.c:1900 (xqc_client_h3_conn_ping_acked_notify)
====>ping_id:1
:status = 200
server = njet/1.2.0
date = Mon, 18 Sep 2023 08:28:11 GMT
content-type = text/html
content-length = 17923
last-modified = Mon, 11 Sep 2023 02:38:08 GMT
etag = "64fe7d90-4603"
alt-svc = h3=":8443"; ma=86400
accept-ranges = bytes
>>>>>>>> request time cost:21642 us, speed:828 K/s
>>>>>>>> send_body_size:0, recv_body_size:17923
test_result_speed: 828 K/s. request_cnt: 1.
[rr_benchmark]|request_time:21642|request_size:0|response_size:17923|
***** on_ready_to_create_path
/root/xquic-main/tests/test_client.c:2909 (xqc_client_request_close_notify)
send_body_size:0, recv_body_size:17923, send_header_size:80, recv_header_size:205, recv_fin:1, err:0, mp_state:0, cellular_send_weight:0.00, cellular_recv_weight:0.00, stream_info:#0-1-17-51-0-18065-0-18065-0
xqc_client_timeout_callback | conn_close
/root/xquic-main/tests/test_client.c:1817 (xqc_client_h3_conn_close_notify)
conn errno:256
should_clear_0rtt_ticket, conn_err:256, clear_0rtt_ticket:0
send_count:11, lost_count:0, tlp_count:0, recv_count:26, srtt:5232 early_data_flag:0, conn_err:0, mp_state:0, ack_info:#21-0#0-0#0-0#v0429, conn_info:0,1,0,0,0,0,0,0-2,0-0,0-0,0-5232,0-3113,0-25566,0-11,0-26,0-0,0-0,0-0,0-0,0-0,0-0
[h3-dgram]|recv_dgram_bytes:0|sent_dgram_bytes:0|lost_dgram_bytes:0|lost_cnt:0|
[root@cdn108 build]# vi body.txt