TCP/IP详解--IP首部的选项字段

[摘要]一般教科书都介绍四种IP选项:路由记录选项、时间戳选项、松散源路由选项和严格源路由选项
但对IP选项的介绍都比较简洁,而且多是抄袭steven的Unix环境,对于使用Windows的学习比较有困难
这里我用《科来》说明一下IP选项的情况

[关键词] IP选项 IP包分析 网络分析 科来网络分析软件

一、带IP选项的数据包的产生
首先要说明的是,并非任何IP包都带有IP选项的,事实上,正好相反,正常的IP包都不带IP选项
也就是说,正常IP包的包头长度标志位(第0x000E字节)的值都是0x45,其中高位“4”表示该IP包的版本号为4(IP v4),低位“5”表示包头长5个32位组(即20字节)。下图是一个正常的IP包:

这20个字节的IP包头通常称为“IP包固定头”,任何一个IP包都有符合这个格式的20字节包头
带有IP选项的IP包的包头除了20字节的固定头之外,还带有若干不定长度的选项字节,所以包头长一定大于5个32位组,也就是:包头长是否大于5是IP包是否带有IP选项的一个标志。
下图是一个带有路由记录选项的IP包:

图上可以看到:包头长度标志位(第0x000E字节)的值为0x4F,低位“F”表示包头长0x0F个32位组,即15x4=60字节,60字节是IP包头的最大长度了!
由于并非任何IP包都带有IP选项,按照steven的办法,我们采用带有参数的Ping命令来产生带有IP选项的IP包(谁还有其它的办法?别忘了告诉我一下!)
由于Ping命令是利用了ICMP来检查网路的连通情况,并且默认是连续检查四次,因此,发出一个Ping命令可以用《科来》捕捉到四个请求包。同时,如果能连通的话,宿端也会回发四个应答包(不能连通?那当然没有应答包了!连通不好也会丢失应答包的!)
有关Ping命令的参数介绍如下(可以放心在Windows命令方式下使用的!):
Ping -r 9 网址    //参数-r表示产生路由记录选项包,9表示最多记录9个路由IP,网址是宿端的IP地址
Ping -s 4 网址    //参数-s表示产生时间戳选项包,4表示最多记录4个路由IP及时间戳,网址是宿端的IP地址
Ping -j 网址组    //参数-j表示产生松散源路由选项包,网址组是到达宿端的所经过的路由器IP地址,要按顺序经过,但允许其中经过其它路由器
Ping -k 网址组    //参数-k表示产生严格源路由记录选项包,网址组是到达宿端的所经过的路由器IP地址,要按顺序经过,且不允许其中经过其它路由器


二、选项码
选项码位于数据包的第0x0022字节,值为0x07表示路由记录选项,值为0x44表示时间戳选项,值为0x83表示松散源路由选项,值为0x89表示严格源路由选项
 
三、带有路由记录选项的IP包分析
1、请求包
请求包是源端发出的,所以它的源IP地址(位于数据包的第0x001A、0x001B、0x001C、0x001D四个字节)应该就是本机的IP地址。IP记录表的长度是Ping -r Count命令设定的,9表示IP记录表的长度为9个32位组(即36个字节),最多可记录9个路由IP。IP记录表长度加上一个选项码字节(第0x0022字节)、一个选项长度字节(第0x0023字节)、一个选项指针字节(第0x0024字节),所以选项长度字节的值应为39(即0x27)。由于发出请求包的时候,尚未经过任何路由器,所以IP记录表的值应该全部为0,而选项指针(位于数据包的第0x0024字节)的值应为0x04,表示遇到第一个路由器时,路由器IP地址应存入选项的第0x04个字节(数据包的第0x0024字节)开始的四个字节中。
下图是发出带有路由记录选项的IP包Ping -r命令:

下图是对这个Ping -r命令捕捉到的请求包(利用《科来》的“按协议浏览”-“Ethernet II”-“IP”-“ICMP”-“ Echo Req”来查看):

以上记录中, IP 数据包的:
0x000E 字节第 3 位到第 0 位值为 0x0F ,表示这个 IP 数据包的 包头长 60 字节,超过了 IP 数据包固定包头的 20 字节长度,说明这个 IP 数据包带有 IP 选项;
0x001A 字节到第 0x001D 字节值为 0xC0A801D4 是源 IP 地址,与本机的 IP 地址 192.168.1.212 比较,可知这是本机发出的请求包;
0x0022 字节称为 选项码 ,值为 0x07 (0 00 00111) ,说明这个 IP 数据包带有记录路由选项,其中第 7 位为复制标志位,值为 0 表示 IP 包需要分片时只需将该选项复制到第一个分片中 ,第 6 位到第 5 位为选项类,值为 00 表示 IP 选项是数据包和网络控制选项 ,第 4 位到第 0 位为选项号,值为 00111 表示 IP 选项是路由记录选项
0x0023 字节为长度,值为 0x27 ,说明这个记录路由选项需要记录的路由器 (IP 地址 ) 个数为 9 个,这个值是由 包的源端 设定的;
0x0024 字节为指针,值为 0x04 ,说明这个记录路由选项 尚未记录 路由器 IP 地址;
记录路由选项中已经记录的 IP 地址均为 0.0.0.0 ,进一步印证了这个 IP 数据包是请求包,理由是 发出请求包的时候,尚未经过任何路由器

2
、应答包
应答包是宿端接收到请求包之后,由宿端转发回源端的。 这在一般教科书中都没讲清楚,因为 steven 本身就没讲清楚,抄书的人当然也就讲不清楚了,呵呵 。由于宿端必须接收到请求包才会回发应答包,所以我们只能在 Ping 通宿端之后才可能捕捉到应答包。与请求包相比,应答包的包头总长 ( 0x000E 字节低 4 ) 、选项码 ( 0x0022 字节 ) 和选项长度 ( 0x0023 字节 ) 应该不变,而宿 IP 地址 ( 位于数据包的第 0x001E 0x001F 0x0020 0x0021 四个字节 ) 是本机的 IP 地址,且选项指针 ( 0x0024 字节 ) 应大于 0x04
下图是对上面的 Ping -r 命令接收到的应答包 ( 利用《科来》的 按协议浏览 ”-“Ethernet II”-“IP”-“ICMP”-“ Echo Reply 来查看 )

以上记录中,IP数据包的:
0x000E字节第3位到第0位值为0x0F,表示这个IP数据包的包头长60字节,超过了IP数据包固定包头的20字节长度,说明这个IP数据包带有IP选项;
0x001E字节到第0x0021字节值为0xC0A801D4是宿IP地址,与本机的IP地址192.168.1.212比较,可知这是本机收到的应答包;
0x0022字节称为选项码,值为0x07(0 00 00111),说明这个IP数据包带有记录路由选项,其中第7位为复制标志位,值为0表示IP包需要分片时只需将该选项复制到第一个分片中,第6位到第5位为选项类,值为00表示IP选项是数据包和网络控制选项,第4位到第0位为选项号,值为00111表示IP选项是路由记录选项
0x0023字节为长度,值为0x27,说明这个记录路由选项需要记录的路由器(IP地址)个数9个,这个值是由包的宿设定的;
0x0024字节为指针,值为0x28,说明这个记录路由选项已经记录了9路由器(IP地址),其中第一个IP地址为0xDA13C10B,第二个IP地址0x3B2980FD,最后一个(9)IP地址为0x3D900641

需要说明的一点是,为了使应答包的IP记录表不再象请求包那样全为0必须Ping外网IP地址而不能Ping内网IP地址(192.168.x.x)因为Ping内网地址发出的请求包在内网未经过任何路由器就到达宿端了,当然IP记录表依然会全为0

四、带有时间戳选项的IP包分析
1、请求包
与路由记录选项相似,时间戳选项请求包也是预定一个IP记录表,发送出去之后,每经过一个路由器就记录一个IP地址,直到宿端后被转发回源端,这样源端就可以了解数据包传输的路径。与路由记录选项不同的是,时间戳选项不但可以记录经过的路由器IP地址,还可以记录经过路由器的时刻。通过分析经过各路由器的时间间隔,就可以了解数据包传输路径中,哪段路径比较拥挤、哪段路径比较畅顺、应以多大的包进行传输比较合适。这样就为源端构造最优化的数据包提供了可能。为了提高灵活性,时间戳选项还提供了一个4位的标志字段(位于数据包第0x0025字节低4位),可以让带有时间戳选项的IP包经过路由器时仅记录路过时刻而不记录路由器的IP地址,这种情形下标志字段值为0x00,或者既记录路过时刻又记录路由器的IP地址,这种情形下标志字段值为0x01,甚至可以预先构建一个将要路经的路由器IP地址表,每经过表中指定的路由器就记录路过时刻,这种情形下标志字段值为0x03,且溢出字段和指针字段失效。

Ping -s命令是产生带有时间戳选项的IP包的途径,但它只能产生第 种情形即既记录路过时刻又记录路由器的IP地址的IP包
下图是发出带有路由记录选项的IP包Ping -s命令:

下图是对这个Ping -s命令捕捉到的请求包(利用《科来》的“按协议浏览”-“Ethernet II”-“IP”-“ICMP”-“ Echo Req”来查看):

以上记录中, IP 数据包的:
0x000E 字节第 3 位到第 0 位值为 0x0E ,表示这个 IP数据包 包头长 56 字节,超过了 IP数据包 固定包头的 20 字节长度,说明这个 IP数据包 带有 IP选项
0x001A 字节到第 0x001D 字节值为 0xC0A801D4 源IP地址 ,与本机的 IP地址 192.168.1.212 比较,可知这是本机发出的请求包;
0x0022 字节称为 选项码 ,值为 0x44 (0 10 00100) ,说明这个 IP数据包 带有时间戳选项,其中第 7 位为复制标志位,值为 0 表示 IP 包需要分片时只需将该选项复制到第一个分片中 ,第 6 位到第 5 位为选项类,值为 10 表示 IP 选项是调试和测量选项 ,第 4 位到第 0 位为选项号,值为 00100 表示 IP 选项是时间戳选项
0x0025字节第 3位到第 0位为 标志,值为 0x01,表示 该IP选项既记录路过时刻又记录路由器
0x0025字节第 7位到第 4位为 溢出,值为 0x00,表示 该IP选项未发生因IP记录表已满而不能记录的路由器IP
0x0023字节为 长度,值为 0x24,说明这个 时间戳选项需要记录的 路由器(IP地址) 个数4个,这个值是由 发出请求包的源端设定的;
0x0024字节为 指针,值为 0x05,说明这个 记录路由选项 尚未记录任何 路由器IP地址和时间戳;
记录路由选项中已经记录的IP地址均为0.0.0.0、时间戳均为0,进一步印证了这个 IP 数据包是请求包,理由是 请求包发出时IP记录表全置为0

2、应答包
与路由记录应答包一样,时间戳选项应答包也必须在Ping得通宿端之后才会由宿端转发回来。由于请求包经过每个路由器都要作记录,因而时间戳选项的溢出字段(位于数据包第0x0025字节高4位)、指针字段(位于数据包第0x0024字节)和IP记录表(位于数据包第0x0026字节之后)都应有所变化。特别要指出的是溢出字段,它用于计算因IP记录表已满而无法记录的路由器IP个数,因为受到IP包头最大只能60字节的限制,时间戳选项的IP记录表最多只能记录4个路由器IP,所以一旦传输路径上要经过的路由器个数大于4个,那只能用溢出字段来计数了,这也是Ping -s命令的参数最大不可超过4的原因。
下图是对上面的 Ping -s 命令接收到的应答包 ( 利用《科来》的 按协议浏览 ”-“Ethernet II”-“IP”-“ICMP”-“ Echo Reply 来查看 )

以上记录中, IP 数据包的:
0x000E 字节第 3 位到第 0 位值为 0x0E ,表示这个 IP数据包 包头长 56 字节,超过了 IP数据包 固定包头的 20 字节长度,说明这个 IP数据包 带有 IP选项
0x001E 字节到第 0x0021 字节值为 0xC0A801D4 宿IP地址 ,与本机的 IP地址 192.168.1.212 比较,可知这是本机收到的应答包
0x0022 字节称为 选项码 ,值为 0x44 (0 10 00100) ,说明这个 IP数据包 带有时间戳选项,其中第 7 位为复制标志位,值为 0 表示 IP 包需要分片时只需将该选项复制到第一个分片中 ,第 6 位到第 5 位为选项类,值为 10 表示 IP 选项是调试和测量选项 ,第 4 位到第 0 位为选项号,值为 00100 表示 IP 选项是时间戳选项
0x0025字节第 3位到第 0位为 标志,值为 0x01,表示 该IP选项既记录路过时刻又记录路由器
0x0025字节第 7位到第 4位为 溢出,值为 0x07,表示 该IP选项传输路径上经过的路由器中有7个因IP记录表已满而未记录
0x0023字节为 长度,值为 0x24,说明这个 时间戳选项 需要记录的 路由器(IP地址) 个数4个,这个值是由 发出应答包的宿端设定的;
0x0024字节为 指针,值为 0x25,说明这个 记录路由选项 已经记录了 4 路由器IP地址和时间戳),其中第一个IP地址为 0x00000000,经过这个IP地址的时间戳为 0x04AC03B0,第二个IP地址为 0x3B2980FD,经过这个IP地址的时间戳为 0x04B5 EE4F,最后一个(第 4个)IP地址为 0xD39B1C09,经过这个IP地址的时间戳为 0x04AC062A

需要说明的一点是,《科来》6.2对这个选项的解码是错误的,无论是请求包还是应答包。一方面,《科来》把数据包第0x0025字节当作了“溢出字段/标志字段”字节来解码(这是正确的),另一方面,它又把这个字节当作了IP地址表的第1个字节,并由此把整个IP地址表都向前挪了一个字节(这是错的),这就是《科来》的错误所在。对比上面时间戳应答包与Ping -s命令的两张图,可以明显看到《科来》的解码结果与Ping -s的结果不同。期待《科来》6.3会对这个Bug有所修正吧
再有,我怎样也还未能解释清楚为什么这个应答包记录的第一个路由器的IP地址居然会为0x00000000(位于数据包的第0x0026~0x0029字节)。因为这意味着经过第一个路由器的时候,这个路由器仅仅在数据包中记录了路过时刻,没有按规定同时记录IP地址,而对照前面Ping -r命令捕捉到的应答包,这个IP地址应该为0xDA13C10B。对照Ping -s命令的图还可以看到,这个路由器不但对第一个请求包没有按规定同时记录IP地址,而且对后面两个Ping通了的请求包都作了同样的处理(还有一个请求包中途丢失了,为什么会丢失我们无从知晓,但估计如果可以观察的话,相信第一个IP恐怕也是同样处理的),说明这不是孤立的现象,而是这个路由器的标准处理手法。兴许这个路由器有故障?天知道
此外,对4字节的时间戳字段如何解码为可读的“年月日 时分秒”格式,我到现在还查不到相关资料。而无论是微软的Ping(它是从Unix移植过来的)还是《科来》,也都未对它进行解码,所以我们才看到“时间戳为0x04AC03B0”这种羞涩难懂的表达。不过这个问题我觉得不能怪微软或科来。微软不过是把一个Unix的程序移植了过来,Unix上没有的,微软当然可以理直气壮地也没有。至于科来,则不便评论了罢(我是科来的铁杆Fans啊!)。我觉得,要怪就只能怪我和steven两个人。怪我是因为我太Out,太孤陋寡闻。而怪steven的原因,则是他在他的经典上没有对此做出解释,以致后来的抄书人想抄都没处可抄,至于那些连想都没想过的,不予评论也罢


比较以上两种数据包,记录路由IP数据包时间戳IP数据包相似之处是___________,不同之处是___________
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值