571
社区成员
发帖
与我相关
我的任务
分享Quic 全称 quick udp internet connection,“快速 UDP 互联网连接”,(和英文 quick 谐音,简称“快”)是由 google 提出的使用 udp 进行多路并发传输的协议。
Quic 相比现在广泛应用的 http2+tcp+tls 协议有如下优势:

编译及测试环境:mac os + go@1.16
brew search go
brew install go@1.16
echo 'export PATH="/usr/local/opt/go@1.16/bin:$PATH"' >> ~/.zshrc
source .zshrc
git clone https://github.com/lucas-clemente/quic-go.git
cd quic-go/example
//server
go build main.go
./main -qlog -v -tcp
//client
cd client
go build main.go
about:config修改HTTP3值为TRUEcd quic-go/example
./main -qlog -v -tcp
https://localhost:6121/demo/tile,打开调试工具查看request详情,第一次访问网站使用TCP协议(HTTP1.1),同时在请求头带上Alt-Svc字段,通知浏览器该服务器支持HTTP3协议
HTTP3协议
cd quic-go/example/client
./main -v -insecure -keylog ssl.log https://quic.rocks:4433/

查看key.log文件
CLIENT_HANDSHAKE_TRAFFIC_SECRET e65a96f4182847c7b5bbaa3af2e209b96d9bf35aff8c772c395f90fadcd91bef 737a56ede644a2d584be8ae45acffed9e4582a8caecd5154d503264800c0a13d
SERVER_HANDSHAKE_TRAFFIC_SECRET e65a96f4182847c7b5bbaa3af2e209b96d9bf35aff8c772c395f90fadcd91bef 071d2846bde495ddc663cbcff856580b4fd1da2c537299af8ebc26c7bf697f81
CLIENT_TRAFFIC_SECRET_0 e65a96f4182847c7b5bbaa3af2e209b96d9bf35aff8c772c395f90fadcd91bef 4fd462c58beaaef3f838a3364bbd34d84eb622f471f82ce101188c152140f607
SERVER_TRAFFIC_SECRET_0 e65a96f4182847c7b5bbaa3af2e209b96d9bf35aff8c772c395f90fadcd91bef d0ab6cc075b5f95d50511c66c25d236332850aafda8ac7e032295bfa09b86d5d
根据QUIC Transport Draft可以知道quic协议使用的长短header格式如下:

查看源码
headers := []wire.Header{
{ // Initial without token
IsLongHeader: true,
SrcConnectionID: protocol.ConnectionID(getRandomData(3)),
DestConnectionID: protocol.ConnectionID(getRandomData(8)),
Type: protocol.PacketTypeInitial,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
},
{ // Initial without token, with zero-length src conn id
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID(getRandomData(8)),
Type: protocol.PacketTypeInitial,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
},
{ // Initial with Token
IsLongHeader: true,
SrcConnectionID: protocol.ConnectionID(getRandomData(10)),
DestConnectionID: protocol.ConnectionID(getRandomData(19)),
Type: protocol.PacketTypeInitial,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
Token: getRandomData(25),
},
{ // Handshake packet
IsLongHeader: true,
SrcConnectionID: protocol.ConnectionID(getRandomData(5)),
DestConnectionID: protocol.ConnectionID(getRandomData(10)),
Type: protocol.PacketTypeHandshake,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
},
{ // Handshake packet, with zero-length src conn id
IsLongHeader: true,
DestConnectionID: protocol.ConnectionID(getRandomData(12)),
Type: protocol.PacketTypeHandshake,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
},
{ // 0-RTT packet
IsLongHeader: true,
SrcConnectionID: protocol.ConnectionID(getRandomData(8)),
DestConnectionID: protocol.ConnectionID(getRandomData(9)),
Type: protocol.PacketType0RTT,
Length: protocol.ByteCount(rand.Intn(1000)),
Version: version,
},
{ // Retry Packet, with empty orig dest conn id
IsLongHeader: true,
SrcConnectionID: protocol.ConnectionID(getRandomData(8)),
DestConnectionID: protocol.ConnectionID(getRandomData(9)),
Type: protocol.PacketTypeRetry,
Token: getRandomData(1000),
Version: version,
},
{ // Short-Header
DestConnectionID: protocol.ConnectionID(getRandomData(8)),
},
}
QUIC协议中数据流建立的状态机如下图

查看crypto_stream.go可以见到
type cryptoStream interface {
// for receiving data
HandleCryptoFrame(*wire.CryptoFrame) error
GetCryptoData() []byte
Finish() error
// for sending data
io.Writer
HasData() bool
PopCryptoFrame(protocol.ByteCount) *wire.CryptoFrame
}
首先查看cryptoStreamManager
type cryptoStreamManager struct {
cryptoHandler cryptoDataHandler
initialStream cryptoStream
handshakeStream cryptoStream
oneRTTStream cryptoStream
}
分为三种数据流,初始化、握手和1RTT数据流。
QUIC协议请求流程如下图

客户端可以使用TCP和QUIC竞速
运营商针对UDP通道⽀持不⾜,表现为不稳定
NAT局域⽹路由、交换机、防⽕墙等会禁⽌UDP 443同⾏
调试复杂:测试环境需要预埋证书,只能看到前期明⽂握⼿,链路调试抓包可能性为零
Wireshark + ⽇志输出
高阶调试:中间人代理 + 证书
作者NP567