如何通过原始套接字修改 IP 数据包头

马谦马谦马谦 编程语言评论1,344字数 537阅读 1 分 47 秒阅读模式

背景:我们的设备上有个链路探测的功能,会定时请求公网的某个 IP 地址,以探测网络是不是连通的。具体的做法是会使用 icmp 或 dns 探测远端服务器,看请求能否正常响应,如果有响应,则认为链路正常,否则则认为不正常,需要采取对应的措施。但是问题的现象是每隔一段时间后,探测包就收不到回复了,导致我们认为线路异常。而实际上网络还是通的,使用系统自带的 ping 和 nslookup 工具也是没问题的。

最后抓包分析,怀疑是 IP 数据包中的 identify 字段为 0 导致的,因为不回复的都是为 0 的 id:

如何通过原始套接字修改IP数据包头

因此,我们就打算先把这 id 改掉试试。本身的实现上,我们使用的是原始套接字来构造 icmp 和 dns 请求,没办法控制 ip.id 。要想修改 ip.id,必须让内核放弃自动填充 ip 头的操作。要想做到这一点,需要用到 socket 选项中的 IP_HDRINCL 选项,它的作用就是告诉内核不要填充头部:

注意事项:

  1. IP 报文中,如果校验和设置为 0,内核会帮我们自动填充。但在 ICMP 报文中,内核不会自动填充。
  2. 如果不填写源地址,内核也会自动帮我们填充。

以下是一个自己修改的 PING 包示例代码:

 

 
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2020 年 6 月 5 日 02:19:56
  • 转载请务必保留本文链接:https://www.dyxmq.cn/program/code/how-to-modify-ip-header-by-raw-socket-in-c-on-linux.html
给socket分配随机端口 C/C++

给 socket 分配随机端口

客户端的 socket 不需要手动执行 bind 绑定地址,但这不意味着客户端 socket 真的不需要绑定端口,实际上是内核它帮我们做了这个操作,在执行 connect 时,内核发现没有绑定端口,就会自动选择一个合...
I/O模型 编程语言

I/O 模型

一、 I/O 模型分类 unix 环境下有 5 中 IO 模型: 阻塞式 I/O 非阻塞式 I/O I/O 多路复用 信号驱动 I/O 异步 I/O(POSIX 中的 aio_系列函数) 常用的是前三种方式,特别是多路 I/O 复用...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证