以前上大学的时候学习过网络协议,对于其中报头的格式,完全是不解其意,只是囫囵吞枣记住样子拿去考试。

后来工作后在前人的指点下开始学习《TCP/IP详解》,但是当时对网络编程一点经验都没有,只是造着例子填代码,所以虽然通读了一遍,但是和没看几乎没有什么两样——因为看不懂。

现在回过头来重新来读,发现很多东西都基本能看懂了,就算有不明白的,多看2遍也就明白了。结合抓包,更能解释自己以前对这些协议的困惑,的确是一本好书,难怪以前好多人推荐我去读。

以书为主,结合抓包,记录笔记。

链路层抓不到包,暂时只是了解基础知识,抄袭几句:

“最大传输单元MTU

以太网和802.3对数据帧的长度都有一个限制,其最大值分别是1500和1492字节。链路层的这个特性称作MTU,最大传输单元。不同类型的网络大多数都有一个上限。如果IP层有一个数据报要传,而且数据的长度比链路层的MTU还大,那么IP层就需要进行分片( fragmentation),把数据报分成若干片,这样每一片都小于MTU。

路径MTU

当在同一个网络上的两台主机互相进行通信时,该网络的MTU是非常重要的。但是如果两台主机之间的通信要通过多个网络,那么每个网络的链路层就可能有不同的MTU。重要的不是两台主机所在网络的MTU的值,而是两台通信主机路径中的最小MTU。它被称作路径MTU。

两台主机之间的路径MTU不一定是个常数。它取决于当时所选择的路由。而选路不一定是对称的(从A到B的路由可能与从B到A的路由不同),因此路径MTU在两个方向上不一定是一致的。

从第三章IP协议开始。

-------------------------------------------------------------------------------

IP数据包的传送是无序的,不管先后。是不可靠的,比如路由器缓冲区满,直接丢弃IP包,并发送ICMP差错报文。

IP的4位首部长度,与4位版本整合在一个字节中。

目前版本号均为4。

4位首部长度的数值不是表示首部有多长,而是指有多少个4字节。比如在IP没有选项的情况下,其值为5,那么首部长度就是5乘以4得20个字节。

因为只有4位,所以最大值为15,导致IP的首部最多只能有60个字节长度。

IP的TOS服务类型,对大多数协议是被忽略的。基本都是00 。

报文的总长度会被填充,比如ARP的包(长度42),无论是路由器发的还是其他PC发给我的,都会自动把它填充到60,但是自己发给自己本机的虚拟机,仍然是42 ,不清楚原因。所以需要总长度来确认有效值。

16位标志,是单个主机所有进程发送的IP包形成一个队列,每发送一个IP包就进行加1 。交互的2台计算机的标志是独立的。但是从抓包上来按,对方QQ发给我的IP包,这个值一直都是0 。

如果一个UDP报携带的内容长度超过了1472,那么它会被分片,被分割的IP包,他们的16位标志是相同的。3位标志用来确认是首包0X02,后续包0X00,后面的13位偏移显示本IP包携带数据的头位置为实际内容的第几位。比如:第一个包,IP包长度1500(IP报头20字节),3位标志0X02,13位偏移为0,携带数据长度1480(8字节的UDP报头,1472实际内容),第二个包,IP包长度48,3位标志0X00,13位偏移为1480,携带数据长度(28实际内容,没有UDP报头了)。

如果不需要分片,3位标志为0X04。

-------------------------------------------------------------------------------

第三章ARP

ARP的的请求包必然是广播地址。

PC机器会定期去ARP自己的网关地址。

抓包中发现,我的路由器会把42字节的ARP包填充成60字节,后面增加了“0000+16字节的请求报文头部”。(本机的虚拟机没有填充,仍然是42字节,其他PC为60字节)

又换了台路由器,发现返回的ARP包被追加了18字节的全0,估计也是根据路由器设置不同而变。

这是因为以太网数据帧长度有最小长度,通过以太网的数据都被填充到这个最小长度。

如果是本机ARP本机的虚拟机,只通过网卡,不通过以太网,那么还会为原先的长度。

对于ES5,删除一个ARP地址后,会仍然以incomplete存在,或者ping一个不存在的IP地址,也会出现incomplete。

但是对于XP,没有这样一个不完整缓存的记录。

免费ARP并不是为自己获取自己IP地址的报文,而是2个作用:

1、如果收到回复,说明IP地址冲突了。

2、自己修改IP地址,就会发送这个报文通知其他机器,更换缓存内容,这个报文没有任何回复的。

在实际抓包中,如果你修改了本机的IP地址,就肯定会抓到免费ARP的报文,目的、源IP、源MAC都是自己,目的MAC为空。

-------------------------------------------------------------------------------

第四章RARP

RARP并不是所有机器能应答这个请求报文,而是需要专门的RARP服务器来负责应答,如果有多个RARP服务器,则通过设置不同的响应延迟时间来分别。

-------------------------------------------------------------------------------

第五章ICMP

类型0,8为ping服务。

ICMP的标识符和序列号在应答中被原样返回,用于匹配。

UDP的规则之一:收到与本进程使用的端口不一致的请求,返回一个ICMP不可达的报文()后面traceroute就是利用这个实现的。)

UDP端口不可达报文中,ICMP报头后四个字节为全0 ,只有类型3代码4时才有值。

有个地方,抓包与原书不符合。ICMP不可达报文并不是仅仅返回了8字节的UDP首部,而是全部UDP报文,比如使用tftp来访问一个不存在的服务器,会把tftp的报文内容也一起返回。使用服务器是ES5 。

后来又换来台路由器,结果发现,返回的仅仅是8字节UDP首部,估计是在路由器上可以设置。

-------------------------------------------------------------------------------

第七章ping

ping使用ICMP的0,8实现。

标识号为04,序号每次请求则加1,不清零,下次重新ping操作时,继续往上加。

ping携带的数据为32个字符:a-z a-i

关于携带过路IP的操作,XP和ES5的命令不一样,携带信息也不一样。

XP:ping -r (1-9) host 可以调整携带多少个IP,XP在接受返回报文时没有填入自己的入口IP。XP的请求报文里请求ptr为4,不携带自己的出口IP。

ES5:ping -R host 不能调整,固定9个IP。发送返回报文时填入自己的入口IP。请求报文里请求ptr为8,携带了自己的出口IP。

一般而言,带R的ping连路由器都出不去,基本被全部限制了。

ping 在win和linux虽然都能设置包大小(但肯定限制在65535以下),如果包长度大于MTU,实际发送中icmp包会被分片。