* ICMP:Internet控制报文协议
用于为IP或者更高层协议传递查询/请求/差错相关报文,封装在IP数据报内部。其规范见RFC 792。
* 发送网络广播不会引起ICMP差错报文。
* ICMP报文的主要格式:
类型(8位)--代码(8位)--校验和(16位)--报文内容
类型共15种,其值为0~18,但不包括1、2、6、7;
代码字段从0~15共16种。类型字段和代码字段共同组成定义了ICMP的报文类型。
检验和算法与IP首部相同,即全部取反,然后每16位累加。覆盖整个ICMP报文。
* ICMP掩码地址请求与应答报文(共12字节):
用于无盘系统在引导过程中获取自己的子网掩码。
格式:
类型(Req=17/Ack=18)--代码(0)--校验和--标识符(2 bytes)--序号(2 bytes)--Netmask(32 bits)
由IP往广播地址发送,应答主机把响应传回给请求主机。
* ICMP时间戳请求与应答报文(20字节):
用于一台主机向另一台主机查询当前时间。时间戳的建议值为UTC从0时开始计算的时间,单位为毫秒。
格式:
类型(Req=17/Ack=18)--代码(0)--校验和--
标识符(2 bytes)--序列号(2 bytes)--
发起时间戳(32 bits)--接收时间戳(32 bits)--传送时间戳(32 bits)
请求时只填写发起时间戳。大多数实现在响应时把接收和传送时间戳填写为相同的值。
与请求主机的时钟的差别的算法(单位: 毫秒):
(接收时间戳-发起时间戳)-(发请求的时间-收到响应的时间)/2
即先比较响应主机接收到请求报文时的时间与发起的差,再减去网络往返的时间。
* ICMP端口不可达差错报文:
一种常见的ICMP差错。
格式:
类型(3)--代码(0~15)--校验和--未用(32 bits,必须为0)--
IP首部--原始IP数据报中数据的前8个字节。
类型3为各种ICMP不可达报文,共16种。
IP首部用于为出错主机提供协议字段,从而分析往后的8个字节,而后8个字节包含了TCP或者UDP等协议的源端口和目的端口,从而使出错主机可以从端口号把差错报文与相关的进程关联起来。
注:ICMP规范允许IP数据报中的数据多于8个字节,但大多BSD的派生系统只返回8个字节。
================================================================================
* ping程序
* ping是ICMP最常见的应用,使用的是ICMP回显请求/应答报文,而不必经过TCP/UDP的传输层。
* ICMP回显请求/应答报文的格式:
类型(Req=8/Ack=0)--代码(0)--校验和(16 bits)--标识符(16 bits)--序号(16 bits)--选项数据
* ping局域网的另一台主机的输出:
root@mjxian-ubuntu ~
# ping 219.221.206.53
PING 219.221.206.53 (219.221.206.53) 56(84) bytes of data.
64 bytes from 219.221.206.53: icmp_seq=1 ttl=64 time=5.12 ms
64 bytes from 219.221.206.53: icmp_seq=2 ttl=64 time=0.727 ms
64 bytes from 219.221.206.53: icmp_seq=3 ttl=64 time=0.730 ms
64 bytes from 219.221.206.53: icmp_seq=4 ttl=64 time=0.756 ms
64 bytes from 219.221.206.53: icmp_seq=5 ttl=64 time=0.743 ms
--- 219.221.206.53 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4016ms
rtt min/avg/max/mdev = 0.727/1.615/5.120/1.752 ms
第一个往返时间比后面的要大,一般是由于包含了局域网上arp请求与应答的时间。如果arp -a看到目标主机已经在本机的arp高速缓存上,就不用再进行arp请求。
以下是tcpdump在局域网上抓包的结果,显然是每秒发送和接收一次ICMP回显:
11:27:12.587877 arp who-has 219.221.206.53 tell ubuntu
11:27:12.588589 arp reply 219.221.206.53 is-at 00:14:78:d4:f1:43 (oui Unknown)
11:27:12.588612 IP ubuntu > 219.221.206.53: ICMP echo request, id 17432, seq 1,length 64
11:27:12.589342 IP 219.221.206.53 > ubuntu: ICMP echo reply, id 17432, seq 1,length 64
11:27:13.587972 IP ubuntu > 219.221.206.53: ICMP echo request, id 17432, seq 2,length 64
11:27:13.588667 IP 219.221.206.53 > ubuntu: ICMP echo reply, id 17432, seq 2,length 64
11:27:14.592023 IP ubuntu > 219.221.206.53: ICMP echo request, id 17432, seq 3,length 64
11:27:14.592724 IP 219.221.206.53 > ubuntu: ICMP echo reply, id 17432, seq 3,length 64
11:27:15.596088 IP ubuntu > 219.221.206.53: ICMP echo request, id 17432, seq 4,length 64
11:27:15.596814 IP 219.221.206.53 > ubuntu: ICMP echo reply, id 17432, seq 4,length 64
11:27:16.600304 IP ubuntu > 219.221.206.53: ICMP echo request, id 17432, seq 5,length 64
11:27:16.601015 IP 219.221.206.53 > ubuntu: ICMP echo reply, id 17432, seq 5,length 64
* ping非本局域网上的一台主机的输出
例如校园网里面的,其结果如下。很显然这次第一次返回并没有很大的时间差,这是因为由于wjl.scu.edu.cn这台主机并不在局域网内,封装ICMP的IP数据报直接投递给路由,后面的事情由路由解决,看起来应该是这台机器的硬件地址已经在某台路由上的arp高速缓存里面了,省去了arp请求的一步。
root@mjxian-ubuntu ~
# ping
PING (202.115.32.129) 56(84) bytes of data.
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=1 ttl=62 time=0.368 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=2 ttl=62 time=0.395 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=3 ttl=62 time=0.261 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=4 ttl=62 time=0.345 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=5 ttl=62 time=0.324 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=6 ttl=62 time=0.382 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=7 ttl=62 time=0.423 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=8 ttl=62 time=0.250 ms
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=9 ttl=62 time=0.428 ms
--- ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 8034ms
rtt min/avg/max/mdev = 0.250/0.352/0.428/0.065 ms
这是tcpdump抓包的结果(略):
11:36:43.053719 IP ubuntu > wjl.scu.edu.cn: ICMP echo request, id 26713, seq 1,length 64
11:36:43.054048 IP wjl.scu.edu.cn > ubuntu: ICMP echo reply, id 26713, seq 1,length 64
11:36:44.059846 IP ubuntu > wjl.scu.edu.cn: ICMP echo request, id 26713, seq 2,length 64
11:36:44.060206 IP wjl.scu.edu.cn > ubuntu: ICMP echo reply, id 26713, seq 2,length 64
ping输出的ttl是62,是由于经过了2次路由,减了2,一个简单的路由查询可以使用ping -R选项。它显示了一次请求和应答整个往返过程经过的所有路由。
* ping -R 目标主机,显示往返所经路径。
-R选项要求返回的IP数据报的首部操作选项包含RR路由记录。这要求路由提供IP数据报的R操作R选项支持,下例中,经过的两个路由都没有显示出来,说明这些路由都不支持RR选项。
root@mjxian-ubuntu ~
# ping -R
PING (202.115.32.129) 56(124) bytes of data.
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=1 ttl=62 time=1.20 ms
RR: ubuntu (219.221.206.48)
wjl.scu.edu.cn (202.115.32.129)
wjl.scu.edu.cn (202.115.32.129)
ubuntu (219.221.206.48)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=2 ttl=62 time=1.20 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=3 ttl=62 time=1.14 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=4 ttl=62 time=2.49 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=5 ttl=62 time=1.09 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=6 ttl=62 time=1.12 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=7 ttl=62 time=1.10 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=8 ttl=62 time=1.10 ms (same route)
64 bytes from wjl.scu.edu.cn (202.115.32.129): icmp_seq=9 ttl=62 time=1.07 ms (same route)
--- ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 8068ms
rtt min/avg/max/mdev = 1.074/1.282/2.491/0.432 ms
使用ping -R,就是要求返回的IP数据报的首部操作选项包含RR路由记录,
* RR操作的IP选项主要格式为
code(RR=7,1 bytes)--len(1 bytes)--ptr(1 bytes)--addr1(4 bytes per addr#)
其中ptr为addr的指针,从4开始;
addr一共最多可以记录9个,因为一个IP选项字段最多可以存放40字节。
用tcpdump -v查看的输出如下:包含了IP首部和操作选项:
12:08:05.985310 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto: ICMP(1), length: 124, options ( NOP (1) len 1 )) ubuntu > mail.scu.edu.cn: ICMP echo request, id 42296, seq 1, length 64
12:08:05.986331 IP (tos 0x0, ttl 62, id 24203, offset 0, flags [none], proto: ICMP (1), length: 124, options ( RR (7) len 39ubuntu, mail.scu.edu.cn, mail.scu.edu.cn, 0.0.0.00.0.0.00.0.0.00.0.0.00.0.0.00.0.0.0EOL (0) len 1 ))mail.scu.edu.cn > ubuntu: ICMP echo reply, id 42296, seq 1, length 64
第一个为 ICMP echo request, IP首部不包含操作选项(NOP,无操作)
第二个为 ICMP echo reply,记录了路由上的主机地址,后面空的填充为0,EOL表示操作选项清单结束。
* IP时间戳选项: ping -T tsonly/tsandaddr/tsprespec host1 [host2 [host3[host4]]] 目标主机
tsonly 选项只显示时间戳(timestamp)
tsandaddr 包括每个路由上的主机名和时间戳
tsprespec 预指定要显示时间戳的路由,最多4个。
时间戳记录为UTC时间午夜00时至今的时间,单位毫秒。
================================================================================
* traceroute程序
* traceroute是使用ICMP报文的另一个重要应用程序。它还利用了这样一个事实,就是IP数据报里面的TTL字段每经过一个路由都将自动减1,如果在路由内停留超过1秒则减去这个秒数。事实上TTL在今天已经用来作为路由计数器,每一跳减1,到为0时该IP数据报即被丢弃,然后路由返回一个ICMP超时出错报文。
traceroute程序运行后每次往目标主机反复发送3次一个带UDP数据的IP数据报,其TTL初始值为1,收到ICMP超时报文后再发一个,然后再发3次一个TTL值为2的报文。直到抵达目的主机。而UDP数据里面的目的端口设置为不可能的UDP端口,Unix的实现一般用traceroute的 pid | 32768,这样traceroute通过查询返回的ICMP出错报文是超时还是端口不可达判断是下一跳路由 或者是目的主机。
* 下面是一个用traceroute命令查看到主机wjl.scu.edu.cn的例子。和上面ping -R wjl.scu.edu.cn 用ping来查看路由比较,会发现ping -R的输出并不包含219.221.206.62这台路由,可能是路由不支持IP操作选项的RR特性的缘故。而trceroute利用的是ICMP的出错报文,只要求路由支持ICMP和目的主机支持UDP就可以了。另外两个traceroute比ping -R更好用的原因是ping -R显示的是往返路由,且其长度受IP首部所限最多只能记录9个路由。而traceroute显示的是单向路由,显示的路由数能达到TTL规范的最大值。
root@mjxian-ubuntu ~
# traceroute wjl.scu.edu.cn
traceroute to wjl.scu.edu.cn (202.115.32.129), 30 hops max, 40 byte packets
1 219.221.206.62 (219.221.206.62) 0.992 ms 0.656 ms 0.539 ms
2 10.10.34.2 (10.10.34.2) 0.609 ms 0.596 ms 0.482 ms
3 wjl.scu.edu.cn (202.115.32.129) 0.548 ms 0.312 ms 0.314 ms
前面的序号,和所发送的TTL值一次,第一个值比较大,为0.992 ms,一般认为是arp交换或者向dns服务器查询域名等其它预处理的原因。可见到主机wjl.scu.edu.cn共经过了2个路由,这一点也可以从ping的时候看到TTL为62看得出来。
* 以下为traceroute执行时用tcpdump的抓包输出。可见主机ubuntu一直在向wjl.scu.edu.cn发送一个包括12字节数据的UDP包,每个经过的路由都发了三次,而路由也返回三次长度为36字节的ICMP超时报文,最后是主机wjl.scu.edu.cn发送三次端口不可达报文。UDP端口是每发一次自动加1,初始值由traceroute进程的pid和32768相或得到。该进程pid可以在程序运行时通过ps -A显示出来。
16:53:25.799438 IP ubuntu.40890 > wjl.scu.edu.cn.33435: UDP, length 12
16:53:25.800050 IP 219.221.206.62 > ubuntu: ICMP time exceeded in-transit,length 36
16:53:27.391779 IP ubuntu.40890 > wjl.scu.edu.cn.33436: UDP, length 12
16:53:27.392342 IP 219.221.206.62 > ubuntu: ICMP time exceeded in-transit,length 36
16:53:27.392808 IP ubuntu.40890 > wjl.scu.edu.cn.33437: UDP, length 12
16:53:27.393262 IP 219.221.206.62 > ubuntu: ICMP time exceeded in-transit,length 36
16:53:27.394112 IP ubuntu.40890 > wjl.scu.edu.cn.33438: UDP, length 12
16:53:27.394619 IP 10.10.34.2 > ubuntu: ICMP time exceeded in-transit, length 36
16:53:28.963890 IP ubuntu.40890 > wjl.scu.edu.cn.33439: UDP, length 12
16:53:28.964418 IP 10.10.34.2 > ubuntu: ICMP time exceeded in-transit, length 36
16:53:28.964837 IP ubuntu.40890 > wjl.scu.edu.cn.33440: UDP, length 12
16:53:28.965257 IP 10.10.34.2 > ubuntu: ICMP time exceeded in-transit, length 36
16:53:28.966022 IP ubuntu.40890 > wjl.scu.edu.cn.33441: UDP, length 12
16:53:28.966489 IP wjl.scu.edu.cn > ubuntu: ICMP wjl.scu.edu.cn udp port 33441 unreachable, length 48
16:53:28.967881 IP ubuntu.40890 > wjl.scu.edu.cn.33442: UDP, length 12
16:53:28.968127 IP wjl.scu.edu.cn > ubuntu: ICMP wjl.scu.edu.cn udp port 33442 unreachable, length 48
16:53:28.968541 IP ubuntu.40890 > wjl.scu.edu.cn.33443: UDP, length 12
16:53:28.968792 IP wjl.scu.edu.cn > ubuntu: ICMP wjl.scu.edu.cn udp port 33443 unreachable, length 48
* traceroute的-g -G选项
-g、-G选项为自定义源站选路的选项,traceroute命令必须经过该选项指定的路由,其中-G严格指定了要经过的全部路由顺序,-g只指定必须要经过的路由顺序。
我机器上的traceroute的版本为1.4a12,从源代码来看已经取消了-G选项。
-g选项一个有用的应用是可以查看到某主机往返的路由是否一致,只需把目的主机设为-g指定的主机,把发出主机设为tracert的最终主机。这时traceroute就先查找从发出主机srchost到dsthost的路由,再查找dsthost到srchost的路由。完成一次从localhost到dsthost的往返。
traceroute -g dsthost srchost
阅读(3324) | 评论(0) | 转发(0) |