当我们判断网络是否可用的时候
感谢baidu.com
ping 命令是使用ICMP报文
ICMP 报文具体是什么呢?
from 互联网控制消息协议:
https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E6%8E%A7%E5%88%B6%E6%B6%88%E6%81%AF%E5%8D%8F%E8%AE%AE
Type - ICMP的类型,标识生成的错误报文;
Code - 进一步划分ICMP的类型,该字段用来查找产生错误的原因.;例如,ICMP的目标不可达类型可以把这个位设为1至15等来表示不同的意思。
Checksum - Internet校验和(RFC 1071),用于进行错误检查,该校验和是从ICMP头和以该字段替换为0的数据计算得出的。
Rest of Header - 报头的其余部分,四字节字段,内容根据ICMP类型和代码而有所不同。
- Identification: 标识符:linux-进程PID,windows-固定值1
- Sequence number: 序列号
!! 注意:这里多了Timestamp 8字节,这里测试时用的MacOS(参考:
hping
)ICMP数据 - 48字节
总共是:src-mac(6字节) + dst-mac(6字节) + 类型(2字节) + IP报文(20字节) + ICMP报文(8字节) + ICMP数据(48字节) + Timestamp(8字节)
ICMP 作用
概念
- ICMP: Internet Control Message Protocol 控制报文协议
- ICMP 和 IP 处于同一层,但是ICMP是配合IP协议一起使用的,补充IP协议的差错控制和辅助机制
- 分为差错报告和查询两种报文类型
- 差错:目的主机或者网络路由处理IP数据报文的时候出问题了就报告
- 查询:最常见的应用就是ping、traceroute这样的使用了,发送请求,并要求回执
差错报文
- 那些情况会有差错报告:
- 目的站不可达,很多可能都会造成这种情况:没有网络,主机找不到,协议,端口找不到,路由失败
- 源站抑制,机器本身或者网络上的其他设备网络拥塞导致数据丢了
- 超时:假设一个数据报被分片发送了,一定时间内没有收到全部的分片,已经收到的就会被丢弃掉,并且产生一个这样的报文告知
- 参数问题:协议数据校验发现错误了,就会丢掉这个数据报,并且报告
- 改变路由:A点到B点需要经过很多的路由设备,如果其中一个路由设备不可用或者发现了更优路径了,需要切换路由设备了,会产生这样一个报文,让上一层知道下一次路由用已经切换过的节点吧
- 那些情况及时出问题也不会报告差错:
- 本身ICMP就是差错报告的包出错了,不会报告,不然就是递归了
- 分片的数据报,不会报告(IP分片的第一片会报,其他片不会)
- 多播的数据报,不会报告
- localhost地址,不会报告
- 上面这些差错报告,是可能由路由层发出的,而路由层解包的是IP层的协议,ICMP可以看做是IP协议的子类
ICMP 报文类型
ICMP 工具
1. ping
- 最常用的工具了,上面介绍ICMP也用的这个
2. why dose ping need setuid permission
https://unix.stackexchange.com/questions/382771/why-does-ping-need-setuid-permission; 这个问题包含的知识挺多的
suid
: https://www.cnblogs.com/sparkdev/p/9651622.htmlraw network socket
: https://stackoverflow.com/questions/14774668/what-is-raw-socket-in-socket-programmingraw network socket
wiki: https://en.wikipedia.org/wiki/Network_socketgetcap
: https://www.man7.org/linux/man-pages/man8/getcap.8.html- traceroute -T 需要
root
也是因为socket_raw
的关系 windows
的tracert
没有tcp
的选项,但是可以自己写程序模拟,但是自己的程序需要administrator
权限windows
的ping
没有特别的要求administrator
权限,是win有个特殊的icmp.dll
不需要管理员权限就可以用,而ping
是基于这个实现的 (https://www.thoughtco.com/implementing-ping-without-using-raw-sockets-4068869)- 有时候icmp的路径探测是不准确的,(不同协议路由的路径很可能不同); 这时候我们需要个tcp的路径探测包在自己的程序里,(TTL递增)代码很简单,只是需要记得需要
管理员权限
- ttl(Time To Live):代表是报文的存活时间,存活时间以秒为单位,但小于一秒的时间均向上取整到一秒。在现实中,这实际上成了一个跳数计数器:报文经过的每个路由器都将此字段减1,当此字段等于0时,报文不再向下一跳传送并被丢弃,最大值是255(8bit)
图片来源:https://www.cloudflare.com/zh-cn/learning/cdn/glossary/time-to-live-ttl/
3. traceroute 路径探测
wiki
: (https://en.wikipedia.org/wiki/Traceroute)man page
: (https://linux.die.net/man/8/traceroute)
默认是UDP探测,利用IP协议TTL字段,第一次TTL=1探测一个路由节点,收到ICMP Type=11, Code=0的Time Exceeded
做下一次,TTL递增,直到探测到目标节点,到达目标接地那会收到ICMP Type=3 Code=3
之前的路径太长了,这次探测换了路径中一个近的路由点
traceroute 可以选择ICMP、UDP、TCP模式,并可以选择最多探测多少(也就是TTL最大多少)
指定–mtu也可以探测路径上的mtu,但是下一次发消息不一定是探测的路径,所以这个值只能用作参考
行程中的一些附加注释:这些都对应了ICMP的Type&Code,具体抓包可以看到
- !H 主机不可达
- !N 网络不可达
- !P 协议不可访问
- !S 源路由失败
- !F 需要分段
- !X(管理性通信)禁止
- !V 违反主机优先级
- !C 有效优先级截止
- !(num)(ICMP无法访问代码(num))
如果几乎所有的探测导致某种无法到达的情况,traceroute将放弃并退出。
traceroute
* * *
Qos/ACL根据差错报文的规则,我们用
TCP+TTL
访问一个不存在的端口,就可以探测出TCP的路由路径
,TTL超时(type=11 code=0)
表示没有到达目标点,RST(type=3 code=3 也有可能是其他)
、connected
表示到达了目标点
ECMP 等价多路径
wiki
: (https://en.wikipedia.org/wiki/Equal-cost_multi-path_routing)
- 消息报从A点发送到B点,链路上会有很多路由节点,但是有一些路由节点是是核心的路由节点,图示的线路
- 如果traceroute遇到ECMP(等价路径点A&B),也就是这次经过等价路径的A,但是下次很可能经过的B
说明
- 由于现在网络环境大都有NAT、防火墙等设备、策略,ICMP的检测只能作为参考,甚至ICMP拿不到结果
- 指定目标IP:Port,指定协议,这样检测出来的结果相对价值更大
- ICMP的差错报文可以帮助我们考虑网络问题可能出现在哪个方面
- 日常多抓包,多看