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

马谦马谦马谦 2020年6月5日02:19:56 发表评论
文章最后编辑于:2020-6-5 02:21:50

背景:我们的设备上有个链路探测的功能,会定时请求公网的某个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包示例代码:

 

本文共执行62次查询,耗时0.743秒!
马谦马谦马谦

发表评论

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