题目
TCP三次握手过程及异常处理
信息
- 类型:问答
- 难度:⭐⭐
考点
TCP连接建立过程,握手状态转换,异常场景分析
快速回答
TCP三次握手过程:
- 客户端发送SYN包(SYN=1, seq=x)进入SYN_SENT状态
- 服务端响应SYN-ACK包(SYN=1, ACK=1, seq=y, ack=x+1)进入SYN_RCVD状态
- 客户端发送ACK包(ACK=1, seq=x+1, ack=y+1)进入ESTABLISHED状态,服务端收到后也进入ESTABLISHED状态
常见异常处理:
- SYN超时:启用SYN Cookie防护
- 握手丢包:TCP重传机制自动处理
- 端口关闭:服务端直接返回RST
一、三次握手核心原理
TCP通过三次握手建立可靠的双向通信通道:
- 第一次握手(SYN):客户端随机生成初始序列号x,发送SYN=1的报文,不携带应用数据
- 第二次握手(SYN-ACK):服务端生成自己的初始序列号y,确认客户端的x(ack=x+1),同时发送SYN=1和ACK=1
- 第三次握手(ACK):客户端确认服务端的y(ack=y+1),连接建立完成
// 状态转换伪代码
Client: CLOSED → SYN_SENT → ESTABLISHED
Server: CLOSED → LISTEN → SYN_RCVD → ESTABLISHED二、异常场景与处理方案
1. SYN Flood攻击
现象:恶意客户端发送大量SYN后不回复ACK,耗尽服务端半连接队列
解决方案:
- 启用SYN Cookie(Linux内核参数:net.ipv4.tcp_syncookies=1)
- 调整半连接队列长度(net.ipv4.tcp_max_syn_backlog)
2. 握手丢包重传
重传规则:
- 首次重传超时(RT0):1秒
- 后续重传采用指数退避:2s, 4s, 8s...(最大超时时间通常60s)
// Linux内核参数示例
sysctl -w net.ipv4.tcp_syn_retries=6 # 客户端SYN重试次数
sysctl -w net.ipv4.tcp_synack_retries=5 # 服务端SYN-ACK重试次数3. 端口未监听
行为:服务端直接返回RST复位报文,客户端收到后进入CLOSED状态
三、抓包实例分析
Wireshark抓包示例:
No. Time Source Destination Protocol Info
1 0.000 192.168.1.2 → 10.0.0.3 TCP SYN Seq=0
2 0.025 10.0.0.3 → 192.168.1.2 TCP SYN, ACK Seq=0 Ack=1
3 0.050 192.168.1.2 → 10.0.0.3 TCP ACK Seq=1 Ack=1关键标志位:
- SYN包:Flags=0x002 (SYN)
- SYN-ACK包:Flags=0x012 (SYN, ACK)
- ACK包:Flags=0x010 (ACK)
四、最佳实践
- 队列优化:根据业务负载调整syn_backlog和accept_queue大小
- 超时设置:内网环境可减少重试次数降低延迟(tcp_syn_retries=3)
- 监控指标:关注半连接队列溢出计数(ListenOverflows/ListenDrops)
五、常见错误
- 误解为两次握手:无法防止历史连接初始化(RFC 793明确要求三次)
- 忽略队列限制:未设置合理的backlog导致连接被丢弃
- RST处理不当:应用层未处理连接被复位的情况
六、扩展知识
- TCP Fast Open(TFO):在SYN包携带应用数据,减少RTT(需客户端和服务端同时支持)
- SYN代理:防火墙在完成三次握手后才与后端建连,防御SYN Flood
- MTU发现:握手过程中通过DF标志位确定路径最大传输单元