Files
NE_YuR/network/tcpquiclab/fix.md
2025-12-25 15:14:14 +08:00

162 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QUIC连接问题修复记录
## 问题描述
QUIC客户端无法与QUIC服务器正常连接QUIC性能测试客户端也无法与QUIC性能测试服务器正常连接。
## 问题分析
### 主要原因
`quic_server.c``quic_perf_server.c`服务器在收到没有token的Initial包时尝试发送Retry包`quiche_retry`函数的调用方式不正确。
### 具体问题
- `quiche_retry`函数需要预先生成的token作为输入参数而不是作为输出参数
- 原代码中token_len参数为0导致Retry机制无法正常工作
- 客户端无法完成QUIC握手过程
## 修复方案
### 修改的文件
1. `quic_server.c`
2. `quic_perf_server.c`
3. `quic_perf_client.c`(添加调试输出)
### 修复方法
**跳过Retry机制直接接受连接**
#### quic_server.c 修改
```c
// 原代码
if (client == NULL) {
if (!quiche_version_is_supported(version)) {
ssize_t written = quiche_negotiate_version(scid, scid_len, dcid, dcid_len, out, sizeof(out));
if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len);
} else if (token_len == 0) {
uint8_t new_scid[QUICHE_MAX_CONN_ID_LEN];
int rng = open("/dev/urandom", O_RDONLY);
if (rng >= 0) {
read(rng, new_scid, sizeof(new_scid));
close(rng);
}
ssize_t written = quiche_retry(scid, scid_len, dcid, dcid_len, new_scid, sizeof(new_scid), token, token_len, version, out, sizeof(out));
if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len);
} else {
// 接受连接...
}
}
// 修复后
if (client == NULL) {
if (!quiche_version_is_supported(version)) {
ssize_t written = quiche_negotiate_version(scid, scid_len, dcid, dcid_len, out, sizeof(out));
if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len);
} else {
// Skip retry and accept connection directly
client = malloc(sizeof(Client));
// ... 直接接受连接
}
}
```
#### quic_perf_server.c 修改
同样的修改方式跳过Retry步骤。
#### quic_perf_client.c 修改
添加了调试输出和连接状态检查:
```c
// 添加调试日志函数
void debug_log(const char *line, void *argp) {
fprintf(stderr, "%s\n", line);
}
// 在main函数中启用调试日志
quiche_enable_debug_logging(debug_log, NULL);
// 添加连接检查
if (conn == NULL) {
fprintf(stderr, "quiche_connect failed\n");
return -1;
}
// 添加连接状态输出
if (quiche_conn_is_established(conn)) {
printf("Connection established.\n");
}
```
## 测试结果
### 基础QUIC连接测试
- **命令**: `./quic_server` & `./quic_client`
- **结果**: ✅ 成功
- 客户端成功发送"Hello from QUIC Client!"
- 服务器成功回复"Server received: Hello from QUIC Client!"
- 连接正常关闭
### QUIC性能测试
- **命令**: `./quic_perf_server` & `./quic_perf_client`
- **结果**: ✅ 成功
- 连接成功建立
- 客户端开始发送100MB数据
- 服务器正常接收数据流
- 握手过程正常完成
## 技术说明
### QUIC Retry机制
Retry机制是QUIC协议中用于防止DoS攻击的安全特性
1. 客户端发送Initial包
2. 服务器返回Retry包包含token
3. 客户端使用token重新发送Initial包
4. 服务器验证token后接受连接
### 为什么跳过Retry可以工作
- 在本地测试环境中127.0.0.1DoS攻击风险较低
- quiche库的Retry实现相对复杂需要正确的token生成和验证
- 跳过Retry简化了实现适合实验环境
## 编译和运行
```bash
# 编译所有程序
make clean && make
# 测试基础连接
./quic_server &
./quic_client
# 测试性能
./quic_perf_server &
./quic_perf_client
```
## 注意事项
### 安全性考虑
- 当前实现跳过了Retry机制在生产环境中可能存在安全风险
- 建议在可信网络环境中使用
- 如需更高安全性应实现正确的token生成和验证机制
### 性能影响
- 跳过Retry机制减少了一次网络往返可能略微提高连接建立速度
- 对于实验和测试场景,这种简化是可接受的
## 后续改进建议
1. **实现正确的Retry机制**
- 生成安全的token
- 正确验证token
- 处理token过期
2. **添加错误处理**
- 更详细的错误信息
- 连接超时处理
- 资源清理
3. **性能优化**
- 调整缓冲区大小
- 优化拥塞控制算法
- 支持多流并发
---
修复日期2025年12月25日
修复人员iFlow CLI