自定义Raw Socket发送TCP SYN包后DUT无ACK响应问题求助
问题原因分析及排查方向
一、Linux自动发送RST包的原因
当你用raw socket手动发送SYN包后,内核的TCP协议栈并没有记录这个半连接请求。所以当DUT返回SYN-ACK时,内核发现没有对应的连接条目,就会自动发送RST包终止这个“未知”连接。
解决思路:
- 用
iptables规则拦截内核发出的RST包(替换<DUT_IP>和<目标端口>为实际值):iptables -A OUTPUT -p tcp --tcp-flags RST RST -d <DUT_IP> --dport <目标端口> -j DROP - 创建raw socket时设置
IP_HDRINCL选项,同时用libpcap等工具捕获DUT返回的SYN-ACK,不让内核处理该包;后续ACK包也手动构造发送,全程绕过内核TCP栈。
二、自定义代码发送SYN后无响应的可能原因
1. TCP/IP校验和错误
虽然Wireshark显示包结构与参考包一致,但如果校验和计算错误,DUT会直接丢弃该包,不会返回任何响应。需要注意:
- 手动构造IP和TCP头时,必须自行计算正确的校验和(IP头校验和、TCP校验和,TCP校验和需包含伪头部)。
- 部分情况下Linux内核会自动为raw socket包计算校验和,但如果代码中手动填充了校验和字段,可能覆盖内核计算结果导致错误。可通过
setsockopt关闭内核自动校验,或确认相关选项(如IP_CHECKSUM)设置正确。
2. IP头参数异常
- TTL值:如果设置的TTL过小,SYN包可能在传输途中被路由设备丢弃,Wireshark在本地能抓到,但DUT实际未收到。建议设置TTL为常见值(如64)。
- 源IP地址:如果自定义代码中填写的源IP不是本机实际绑定的IP,或DUT侧有ACL/防火墙规则限制该源IP,会导致包被拒绝。
3. TCP选项或字段细节问题
- MSS值:SYN包中的MSS选项如果设置过大(超过DUT的MTU值),DUT可能忽略该包。建议将MSS设置为DUT侧MTU减40(IP头+TCP头长度)。
- 窗口大小:如果SYN包的窗口大小设置为0,DUT可能不会响应,参考Buchan的代码设置合理窗口值。
- TCP选项格式错误:比如选项的长度字段不正确、选项顺序不符合规范,虽然Wireshark能解析,但DUT可能不识别。
4. 链路层帧错误
由于代码基于802.1X的raw包改写,可能保留了原有链路层处理逻辑:
- 以太网帧的目的MAC地址错误,导致包未正确发送到DUT。需确认目的MAC是DUT的实际MAC地址,或网关MAC地址(跨网段场景)。
- 帧类型字段错误,比如误设置为802.1X的类型,而非IPv4对应的
0x0800。
5. 权限或发送逻辑问题
- Ubuntu 18中发送raw socket需要root权限,如果代码未以root用户运行,包可能并未真正发送出去(Wireshark抓到的可能是本地生成但未出网卡的包)。
- 代码中可能存在发送逻辑错误,比如未正确绑定网卡,导致包从错误的网卡发出,无法到达DUT。
内容的提问来源于stack exchange,提问作者SpacemanScott
相关产品推荐
相关产品推荐

