You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sendto函数无法发送自定义IPv4/TCP头的原始数据包问题排查

自定义IPv4/TCP原始数据包发送失败的问题修复

尝试用C语言的sendto发送自定义IPv4和TCP头的原始数据包,但代码无法正常工作:

  • 怀疑IP_HDRINCL的setsockopt配置有问题,注释掉这段代码后会发送带两个IPv4头的数据包(自定义的+系统自动添加的)
  • 无论是否注释该代码段,sendto都返回40,但实际要么发送了超过40字节的包,要么根本没发送
  • 已尝试绑定socket、修改协议配置、调整头参数等方法,使用Cygwin编译,运行在Windows 11系统

核心问题与修复步骤

1. 结构体字节对齐问题

Windows默认的结构体字节对齐规则会导致IPV4_HDR和TCP_HDR的实际大小与标准IP/TCP头不一致(标准IP头20字节、TCP头20字节),必须强制1字节对齐以匹配网络协议的字节布局:

#pragma pack(1)
// 所有结构体定义放在这里
typedef struct ip_hdr { ... } IPV4_HDR;
typedef struct tcp_header { ... } TCP_HDR;
struct pseudo_header { ... };
struct pseudoTcpHeader { ... };
#pragma pack()

2. IP校验和计算错误

当前代码错误地使用sizeof(struct pseudo_header)计算IP校验和,IP校验和仅需覆盖IP头部本身,修改为:

v4hdr->ip_checksum = csum( (unsigned short*)v4hdr, sizeof(IPV4_HDR) );

3. TCP校验和计算错误

TCP校验和必须结合伪头部(包含IP层的源/目的地址、协议类型等信息)计算,不能直接对TCP头单独计算:

// 构造TCP伪头部
struct pseudoTcpHeader p_tcp_hdr;
p_tcp_hdr.ip_src = v4hdr->ip_srcaddr;
p_tcp_hdr.ip_dst = v4hdr->ip_destaddr;
p_tcp_hdr.zero = 0;
p_tcp_hdr.protocol = IPPROTO_TCP;
p_tcp_hdr.tcp_len = htons(sizeof(TCP_HDR) + payload);
memcpy(&p_tcp_hdr.tcph, tcphdr, sizeof(TCP_HDR));

// 计算校验和
tcphdr->checksum = csum( (unsigned short*)&p_tcp_hdr, sizeof(struct pseudoTcpHeader) );

4. 套接字与IP_HDRINCL配置问题

  • Windows下使用SOCK_RAW+IPPROTO_RAW时,IP_HDRINCL设置生效后,系统不会自动处理IP头,需确保IP头的所有字段(如总长度、分片标记)完全正确
  • 无需绑定socket到源IP,绑定操作可能干扰原始包的发送逻辑,建议删除bind相关代码

5. 运行权限问题

Windows下发送原始数据包必须以管理员身份运行程序,否则即使代码正确,也会因权限不足无法发送数据包。

6. 其他细节修复

  • 避免使用inet_ntoa的临时指针直接赋值,改用dest.sin_addr.s_addr直接设置目的IP:
    v4hdr->ip_destaddr = dest.sin_addr.s_addr;
    
  • 显式初始化TCP头未赋值的字段:
    tcphdr->acknowledge = 0;
    tcphdr->window = htons(65535);
    tcphdr->urgent_pointer = 0;
    

内容的提问来源于stack exchange,提问作者Guy Dror

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:37:07