3. 协议详细说明 (Protocol Details)
本章详细说明 TCP Fast Open 的技术实现细节,包括选项格式、状态机转换和数据处理规则。
3.1. TCP Fast Open Cookie 请求 (Cookie Request)
TCP 选项格式
+-------------+-------------+
| Kind=34 | Length=2 |
+-------------+-------------+
字段说明:
- Kind: 8 位,值为 34(TCP Fast Open 实验性选项编号)
- Length: 8 位,值为 2(表示无 Cookie 数据,这是请求)
客户端行为规范
客户端请求 Cookie 时 MUST 遵循:
-
初始连接:
- 在 SYN 包的 TCP 选项中包含 Kind=34, Length=2
- 不携带任何应用数据
- 正常完成三次握手
-
选项放置:
- TFO 选项应放在其他 TCP 选项之后
- 确保不超过 TCP 选项最大长度(40 字节)
-
重传处理:
- 如果 SYN 包需要重传,MUST 保留 TFO 选项
- 重传计数应与标准 TCP 一致
服务器响应规范
服务器收到 Cookie 请求时 SHOULD:
-
Cookie 生成:
Input: ClientIP, ServerSecret, Timestamp
Output: Cookie = Encrypt(ServerSecret, ClientIP || Timestamp) -
响应构造:
- 在 SYN-ACK 中包含 TFO Cookie 选项
- Cookie 长度通常为 4 到 16 字节
- 继续标准 TCP 握手流程
-
安全考虑:
- 定期轮换 ServerSecret(建议每几小时一次)
- 实现 Cookie 过期机制
- 监控异常请求模式
3.2. TCP Fast Open Cookie 授予 (Cookie Grant)
TCP 选项格式
+-------------+-------------+-------------------+
| Kind=34 | Length | Cookie (4-16字节) |
+-------------+-------------+-------------------+
字段说明:
- Kind: 8 位,值为 34
- Length: 8 位,值为 6 到 18(2 + Cookie 长度)
- Cookie: 4 到 16 字节的加密 Token
Cookie 结构建议
推荐的 Cookie 内部结构:
Cookie = AES-128(ServerSecret, ClientIP || Timestamp || Counter)
组成部分:
- ClientIP: 客户端 IP 地址 (4 或 16 字节)
- Timestamp: Unix 时间戳 (4 字节)
- Counter: 防重放计数器 (可选,4 字节)
服务器实现要点
MUST 实现:
- Cookie 必须绑定到客户端 IP 地址
- Cookie 必须可验证(使用 MAC 或加密)
- Cookie 必须有过期时间
SHOULD 实现:
- 使用加密强度高的算法(如 AES-128)
- 实现密钥轮换机制
- 记录 Cookie 使用统计
MAY 实现:
- Cookie 版本号(支持算法升级)
- 额外的客户端信息(如端口号)
- 速率限制信息
3.3. TCP Fast Open 连接 (Fast Open)
TCP 选项格式与数据
SYN 包结构:
+-------------+-------------+-------------------+
| Kind=34 | Length | Cookie (4-16字节) |
+-------------+-------------+-------------------+
TCP 段:
+------------------------+
| TCP Header |
+------------------------+
| TCP Options | (包含 TFO Cookie)
+------------------------+
| Application Data | (可选,最多 MSS)
+------------------------+
客户端发送规范
客户端使用 Fast Open 时 MUST:
-
Cookie 包含:
- 在 SYN 包的 TCP 选项中包含缓存的 Cookie
- Cookie 必须是从目标服务器接收的有效 Cookie
-
数据携带:
- 可以 在 SYN 包中携带应用数据
- 数据长度 MUST NOT 超过 MSS
- 数据 MUST 是幂等的(可安全重传)
-
序列号:
- SYN 数据使用 ISN(初始序列号)
- 数据序列号范围:[ISN+1, ISN+1+DataLen)
-
重传策略:
首次 SYN:包含 Cookie + Data
↓ (超时)
重传 SYN:
- 选项 1:重传 Cookie + Data(推荐)
- 选项 2:仅重传 SYN,不带数据(保守)
服务器接收规范
服务器收到 Fast Open SYN 时的处理流程:
收到 SYN + TFO Cookie + Data
↓
1. 验证 Cookie
├─ Cookie 格式检查
├─ IP 地址匹配检查
├─ 时间戳验证(是否过期)
└─ MAC/签名验证
↓
2. Cookie 验证结果
├─ 有效 → 继续步骤 3
└─ 无效 → 丢弃数据,发送标准 SYN-ACK(不带数据响应)
↓
3. 接受 SYN 数据
├─ 创建 TCB (Transmission Control Block)
├─ 状态:SYN-RECEIVED
├─ 将数据放入接收缓冲区
└─ 通知应用层有数据可读
↓
4. 发送 SYN-ACK
├─ 确认 SYN 和数据(ACK = ISN + 1 + DataLen)
├─ 可选:在 SYN-ACK 中携带响应数据
└─ 可选:刷新 Cookie(返回新 Cookie)
↓
5. 收到 ACK
└─ 连接进入 ESTABLISHED 状态
数据处理规则
SYN 数据的特殊性:
-
幂等性要求:
- 客户端 MUST 确保 SYN 数据可以安全重传
- 适合:HTTP GET 请求
- 不适合:有副作用的操作(如 POST、DELETE)
-
应用层交付:
- 服务器 MAY 在 SYN-RECEIVED 状态交付数据给应用
- 应用 SHOULD 在连接完全建立前谨慎处理数据
- 服务器 SHOULD 限制 SYN-RECEIVED 状态的资源分配
-
数据重传:
场景:SYN 包丢失
客户端:
SYN + Cookie + Data (1st)
↓ (超时)
SYN + Cookie + Data (2nd)
服务器:可能收到重复数据
→ MUST 实现去重机制(通过序列号)
3.4. Cookie 处理 (Cookie Handling)
Cookie 生命周期管理
服务器端:
# Cookie 生成伪代码
def generate_cookie(client_ip, server_secret, timestamp):
data = client_ip + timestamp
cookie = aes_encrypt(server_secret, data)
return cookie
def validate_cookie(cookie, client_ip, server_secret, max_age):
try:
data = aes_decrypt(server_secret, cookie)
stored_ip, timestamp = parse(data)
# 检查 IP 地址
if stored_ip != client_ip:
return False
# 检查过期时间
if current_time() - timestamp > max_age:
return False
return True
except:
return False
客户端端:
# Cookie 缓存伪代码
class TFOCookieCache:
def __init__(self):
self.cookies = {} # {(server_ip, server_port): (cookie, timestamp)}
def store(self, server_ip, server_port, cookie):
key = (server_ip, server_port)
self.cookies[key] = (cookie, current_time())
def get(self, server_ip, server_port, max_age):
key = (server_ip, server_port)
if key in self.cookies:
cookie, timestamp = self.cookies[key]
if current_time() - timestamp < max_age:
return cookie
else:
del self.cookies[key] # 过期,删除
return None
Cookie 更新策略
主动更新:
- 服务器可以在任何 SYN-ACK 中返回新 Cookie
- 客户端 SHOULD 使用最新收到的 Cookie
被动更新:
- Cookie 过期后,客户端重新请求
- Cookie 验证失败后,客户端回退并请求新 Cookie
安全强化措施
防重放攻击:
Cookie 中包含时间戳
→ 服务器拒绝过期 Cookie
→ 限制 Cookie 有效期(如 24 小时)
防 IP 欺骗:
Cookie 绑定客户端 IP
→ 不同 IP 的客户端无法使用相同 Cookie
→ 移动网络场景需要考虑 IP 漂移
密钥管理:
服务器密钥轮换
├─ 保持多个密钥活跃(当前 + 前一个)
├─ 定期生成新密钥(如每 8 小时)
└─ 旧密钥仅用于验证,不用于生成
故障处理
Cookie 验证失败处理:
-
服务器行为:
- 发送标准 SYN-ACK(不确认 SYN 数据)
- 可选:包含新的 Cookie 供后续使用
- 继续标准 TCP 握手
-
客户端行为:
- 检测到 Fast Open 失败(数据未被确认)
- 在 ACK 后重新发送应用数据
- 清除失效的 Cookie
- 可选:立即请求新 Cookie
网络中间设备干扰:
某些防火墙或 NAT 可能:
- 剥离未知 TCP 选项
- 阻止带数据的 SYN 包
- 修改序列号
客户端应对策略:
- 实现回退机制
- 记录失败的服务器(避免重复尝试)
- 提供禁用 TFO 的选项
3.5. 状态机扩展 (State Machine Extensions)
客户端状态机
CLOSED
↓ (应用请求连接 + 有 Cookie)
SYN-SENT (发送 SYN + Cookie + Data)
↓ (收到 SYN-ACK,ACK 包括数据)
ESTABLISHED
↓
[Fast Open 成功!]
OR
CLOSED
↓ (应用请求连接 + 无 Cookie)
SYN-SENT (发送 SYN,请求 Cookie)
↓ (收到 SYN-ACK + Cookie)
ESTABLISHED
↓ (缓存 Cookie)
[为下次连接准备]
服务器状态机
LISTEN
↓ (收到 SYN + 有效 Cookie + Data)
SYN-RECEIVED (接受数据,通知应用)
↓ (发送 SYN-ACK,确认数据)
↓ (收到 ACK)
ESTABLISHED
↓
[Fast Open 成功!]
OR
LISTEN
↓ (收到 SYN + 无效/无 Cookie)
SYN-RECEIVED
↓ (发送 SYN-ACK,可能包含 Cookie)
↓ (收到 ACK)
ESTABLISHED
↓
[标准 TCP 握手]
关键状态转换
SYN-RECEIVED 状态的特殊处理:
- 服务器 MAY 在此状态向应用层交付 SYN 数据
- 应用 SHOULD 意识到连接尚未完全建立
- 服务器 MUST 限制此状态的资源使用(防 DoS)
下一章节: 4. 安全考量 (Security Considerations) 将详细分析 TFO 的安全威胁和防护措施。