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

马谦马谦马谦
马谦马谦马谦
马谦马谦马谦
606
文章
12
评论
2020年6月5日02:19:56 评论

背景:我们的设备上有个链路探测的功能,会定时请求公网的某个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复用...
epoll中的边缘触发ET和水平触发LT模式 C/C++

epoll中的边缘触发ET和水平触发LT模式

epoll中的触发模式有两种,边缘触发和水平触发,默认情况下使用的是水平触发。 边缘触发(ET)的意思是当电平出现变化的时候才触发事件,如果设置了边缘触发,执行epoll_wait时,内核检测到数据到...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: