ICMP
# ICMP
Internet Control Message Protocol 网络控制报文协议
关键字:控制
在网络层当中,一条数据包发送出去过后,我怎么知道这个数据是否发送成功还是发送失败?发送失败错误原因是什么呢?就像我们前端调用后端接口,前端调用后总有个返回信息说明请求成功或者错误原因吧。
# 功能
确认IP包是否成功发送到目的地址、报告发送过程中IP包被抛弃的原因和改善网络的设置等。
在ip通信过程中,如果某个ip包因为某种原因没有成功到达目的地,那么这个失败的原因就由ICMP来负责通知给发送方。
解析:
如上图例子,主机 A
向主机 B
发送了数据包,由于某种原因,途中的路由器 2
未能发现主机 B
的存在,这时,路由器 2
就会向主机 A
发送一个 ICMP
目标不可达数据包,说明发往主机 B
的包未能成功。
ICMP 的这种通知消息会使用 IP
进行发送 。
因此,从路由器 2
返回的 ICMP 包会按照往常的路由控制先经过路由器 1
再转发给主机 A
。收到该 ICMP 包的主机 A
则分解 ICMP 的首部和数据域以后得知具体发生问题的原因。
# ICMP 类型
- 一类是用于诊断的查询消息,也就是「查询报文类型」
- 另一类是通知出错原因的错误消息,也就是「差错报文类型」
# 报文结构
+-----------------------------------------------------------------------+
| ICMP报文头部(固定长度8字节) |
+-----------------------------------------------------------------------+
| 数据数据... |
+-----------------------------------------------------------------------+
2
3
4
5
ICMP报文头部(8字节)包含以下字段:
- 类型(Type)(1字节):指定ICMP消息的类型。
- 代码(Code)(1字节):提供与消息类型相关的更多详细信息。
- 校验和(Checksum)(2字节):用于校验ICMP报文的完整性。
- 标识符(Identifier)(2字节):通常用于标识与ICMP消息相关的进程或会话。
- 序列号(Sequence Number)(2字节):用于标识具体的ICMP消息。
数据部分是可选的,其内容和长度根据具体的ICMP消息类型和代码而定。不同的ICMP消息类型有不同的数据结构和格式。
# ping 实战[查询报文类型]
仅使用网络层
我们常用的指令ping就是使用ICMP的原理。
例如,我当前的ip地址为10.10.10.10,现在ping www.baidu.com,此时会先通过DNS解析将www.baiduc.om解析为相应的地址,然后再封装对应的ICMP包进行发送,ICMP中type为echo request;当百度的机器收到我们的数据包后,发现这是一个type 为echo request的包,所以会回给我们主机一个对应的echo reply包。
现在我们来抓包试一下。
首先查看我们的主机的转发表,看看默认的网关在哪?
route -n
默认网关在这个地址10.10.10.1
,同时其对应的网卡为 enpls0,所以我们需要再enpls0这个网卡上进行抓包。
输入抓包指令
tcpdump -i enp1s0: -w capture.pcap
开启另一个客户端:
ping www.baidu.com
将抓包的文件放到wireshark中进行分析,过滤条件为icmp
可以看到基本上都是成对的存在的。现在我们将 echo request 和 echo reply 打开看看内容
- echo request
- echo reply
从上面可以看出来,ping
的发送方用的type = echo request
进行发送,对应的注解收到对应的包后会回应 type = reply request
# tranceroute实战[差错报文协议]
原理
它的原理就是利用 IP 包的生存期限 从 1
开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的一种方法。
比如,将 TTL 设置 为 1
,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络包,类型是时间超时。
接下来将 TTL 设置为 2
,第一个路由器过了,遇到第二个路由器也牺牲了,也同时返回了 ICMP 差错报文数据包,如此往复,直到到达目的主机。
这样的过程,traceroute 就可以拿到了所有的路由器 IP。
当然有的路由器根本就不会返回这个 ICMP,所以对于有的公网地址,是看不到中间经过的路由的。
发送方如何知道发出的 UDP 包是否到达了目的主机呢?
traceroute 在发送 UDP
包时,会填入一个不可能的端口号值作为 UDP 目标端口号:33434。然后对于每个下一个探针,它都会增加一个,这些端口都是通常认为不会被使用,不过,没有人知道当某些应用程序监听此类端口时会发生什么。
当目的主机,收到 UDP 包后,会返回 ICMP 差错报文消息,但这个差错报文消息的类型是「端口不可达」。
所以,当差错报文类型是端口不可达时,说明发送方发出的 UDP 包到达了目的主机。
思考:我们使用traceRoute命令,一般情况是traceRoute 111.112.212.112 这种形式,既然我们也没有指定其他参数什么的,那么为什么traceRoute不能像ping一样直接使用ICMP协议【这里其实是可以的,因为ip头部有TTL,但是像UDP和TCP都是没有的,有区别的主要原因是不同的防火强有不同的过滤策略,导致单一的traceroute不可用,所以这里设置了3种策略】,而还需要外加一层UDP协议呢?
首先我们的ping的主要作用是关注一台主机是否可以直连,我们并不关系期间经历了什么,一条ping命令发送出去后,只需要关注传回的echo reply就可以了。但是traceRoute他的作用是不一样的,traceRoute还需要关注经过的每一台机器,怎么让每一台机器向主机发送回送信息是关键。考虑到ICMP中有差错报文,可以让在中间节点发生差错而返回ICMP报文,这个时候就可以涉及到传输层中的TTL了,当一个路由器上的报文TTL时长为0,则丢弃并返回ICMP type =11 超时报文,这样主机就可以拿到对应的路由信息。那么现在就需要思考我们使用tcp还是udp了。
惊讶的发现其实traceRoute有不同的实现。
https://zhuanlan.zhihu.com/p/101810847
http://129.226.226.195/post/33482.html
看traceroute的文档也可以看出有不同的方式:
可以看到有不同的方式。
先看看icmp方式是怎么样的?难道只有icmp方式?
# ICMP方式
tcpdump -i enp1s0: -w capture.pcap
traceroute www.baidu.com -I
root@k1:~# traceroute www.baidu.com -I
traceroute to www.baidu.com (36.155.132.55), 30 hops max, 60 byte packets
1 _gateway (10.10.10.1) 6.220 ms 6.365 ms 6.638 ms
2 10.10.10.11 (10.10.10.11) 1.776 ms 1.765 ms 1.756 ms
3 122.228.207.1 (122.228.207.1) 14.865 ms 14.738 ms 14.672 ms
4 172.30.50.16 (172.30.50.16) 39.874 ms 39.782 ms 39.696 ms
5 * * *
6 * * *
7 * * *
8 * * *
9 111.3.82.1 (111.3.82.1) 7.402 ms 5.605 ms 7.382 ms
10 221.183.81.133 (221.183.81.133) 11.589 ms 10.688 ms 11.115 ms
11 * * *
12 * * *
13 225.24.207.183.static.js.chinamobile.com (183.207.24.225) 21.651 ms 20.662 ms 21.076 ms
14 * * *
15 182.61.254.214 (182.61.254.214) 25.977 ms 25.605 ms 25.668 ms
16 182.61.255.167 (182.61.255.167) 18.392 ms 18.267 ms 18.133 ms
17 * * *
18 * * *
19 * * *
20 36.155.132.55 (36.155.132.55) 18.558 ms 18.627 ms 18.538 ms
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
发起方封装echo request 且ttl =1
# UDP方式
root@k1:~# traceroute www.baidu.com -U
traceroute to www.baidu.com (36.155.132.55), 30 hops max, 60 byte packets
1 _gateway (10.10.10.1) 4.799 ms 5.108 ms 4.893 ms
2 10.10.10.11 (10.10.10.11) 1.965 ms 1.801 ms 1.751 ms
3 122.228.207.1 (122.228.207.1) 67.181 ms 67.183 ms 67.101 ms
4 172.30.50.16 (172.30.50.16) 36.215 ms 36.071 ms 36.031 ms
5 172.16.247.41 (172.16.247.41) 13.737 ms 172.16.247.33 (172.16.247.33) 14.038 ms 172.16.247.37 (172.16.247.37) 14.152 ms
6 * * *
7 * 172.16.90.9 (172.16.90.9) 1.229 ms 172.16.90.17 (172.16.90.17) 1.408 ms
8 * * *
9 * * *
10 * * *
11 * 111.3.82.1 (111.3.82.1) 5.508 ms 5.823 ms
12 * 221.183.81.133 (221.183.81.133) 8.639 ms *
13 221.183.85.94 (221.183.85.94) 18.517 ms * 221.183.85.98 (221.183.85.98) 16.491 ms
14 * * 221.183.77.158 (221.183.77.158) 13.305 ms
15 182.61.255.165 (182.61.255.165) 30.274 ms * *
16 * 182.61.255.171 (182.61.255.171) 30.709 ms 31.321 ms
17 182.61.255.200 (182.61.255.200) 35.881 ms 182.61.255.169 (182.61.255.169) 22.693 ms *
18 * 182.61.255.165 (182.61.255.165) 26.647 ms *
19 * * *
20 * * *
21 * * *
22 * * *
23 * * *
24 * * *
25 * * *
26 * * *
27 * * *
28 * * *
29 * * *
30 * * *
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
发起方封装UDP 且ttl = 1
# TCP方式
root@k1:~# traceroute www.baidu.com -T
traceroute to www.baidu.com (36.155.132.31), 30 hops max, 60 byte packets
1 _gateway (10.10.10.1) 6.102 ms 5.815 ms 6.193 ms
2 10.10.10.11 (10.10.10.11) 1.964 ms 1.933 ms 1.903 ms
3 122.228.207.1 (122.228.207.1) 10.925 ms 10.827 ms 10.781 ms
4 172.30.50.16 (172.30.50.16) 37.286 ms 37.245 ms 36.651 ms
5 * * *
6 * * *
7 172.16.116.77 (172.16.116.77) 6.257 ms 172.16.90.1 (172.16.90.1) 1.307 ms *
8 * * 111.0.37.161 (111.0.37.161) 4.770 ms
9 * 111.0.37.161 (111.0.37.161) 5.175 ms 221.183.81.137 (221.183.81.137) 11.050 ms
10 * 221.183.81.137 (221.183.81.137) 8.471 ms *
11 221.183.81.137 (221.183.81.137) 8.385 ms 111.0.37.165 (111.0.37.165) 5.354 ms *
12 101.67.207.183.static.js.chinamobile.com (183.207.67.101) 25.823 ms 221.183.81.145 (221.183.81.145) 5.325 ms *
13 * * *
14 * 229.24.207.183.static.js.chinamobile.com (183.207.24.229) 19.897 ms *
15 129.22.207.183.static.js.chinamobile.com (183.207.22.129) 22.555 ms 182.61.254.218 (182.61.254.218) 18.213 ms 182.61.255.167 (182.61.255.167) 16.133 ms
16 * * *
17 182.61.254.222 (182.61.254.222) 23.094 ms 182.61.254.234 (182.61.254.234) 19.936 ms *
18 * 182.61.255.169 (182.61.255.169) 32.849 ms 21.493 ms
19 * * *
20 * * *
21 36.155.132.31 (36.155.132.31) 20.617 ms 26.234 ms 17.365 ms
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
客户端封装TCP且ttl = 1
既然两种都有相应的实现,我们就需要知道两者的优缺点:
traceroute(路由追踪)可以以三种不同的模式运行:UDP、TCP和ICMP。以下是这些模式之间的主要区别:
UDP模式:
- 在UDP模式下,traceroute发送带有递增的TTL(生存时间)值的UDP数据包。
- 它使用高编号的目标端口(通常在30000以上),以避免与运行在标准端口上的服务发生冲突。
- UDP路由追踪依赖于这样一个事实:当TTL为0的UDP数据包到达路由器时,路由器将使用ICMP的"Time Exceeded"消息作为响应,指示数据包已过期。
- 每一跳的往返时间(RTT)是根据发送UDP数据包和接收ICMP响应之间的时间计算的。
- 如果目标主机或中间路由器阻止或过滤UDP数据包,则UDP路由追踪可能无法工作。
TCP模式:
- 在TCP模式下,traceroute发送TCP SYN数据包到目标主机。
- 它使用众所周知的目标端口(例如80端口用于HTTP或443端口用于HTTPS),以模拟典型的客户端-服务器通信。
- TCP路由追踪依赖于这样一个事实:当TTL为0的TCP SYN数据包到达路由器时,路由器将使用ICMP的"Time Exceeded"消息作为响应。
- 每一跳的往返时间(RTT)是根据发送TCP SYN数据包和接收ICMP响应之间的时间计算的。
- TCP路由追踪可能在穿越有选择性地过滤ICMP或UDP数据包的防火墙和网络设备时更有效。
ICMP模式:
- 在ICMP模式下,traceroute发送ICMP Echo Request(ping)数据包到目标主机。
- 它依赖于这样一个事实:当TTL为0的ICMP Echo Request数据包到达路由器时,路由器将使用ICMP的"Time Exceeded"消息作为响应。
- 每一跳的往返时间(RTT)是根据发送ICMP Echo Request数据包和接收ICMP响应之间的时间计算的。
- ICMP路由追踪是最常用的模式,通常是许多traceroute实现的默认选项。
- 如果防火墙或网络设备阻止或过滤ICMP数据包,则ICMP路由追踪可能无法工作。
总之,在traceroute中,UDP、TCP和ICMP模式之间的主要区别在于发送的数据包类型以及它们如何引发路由器的响应。选择使用哪种模式取决于特定的网络环境和不同协议的可用性。