IP协议详解:从IP协议头到网段划分、路由与NAT

IP协议详解:从IP协议头到网段划分、路由与NAT

一、IP协议

IP地址的核心作用:定位主机,具有将数据报从A主机跨网络发送到B主机的能力。

但是有这能力不代表一定能成功,就必须有上层TCP协议的支持,TCP负责处理出现问题的情况。但是IP有能力传输,体现在IP有很大概率成功传输。

IP具有跨主机的能力。在网络中,主机被称为主机,路由器也可以被称为主机。

在把数据从A主机发送到B主机时,实际上是把数据通过路径选择,选择一条路径,经过多个路由器,最后到达B主机。

通信时往往有很多路径可以选择,但是最终选择一条路径发送数据,选择路径的过程就是路由选择。

路径选择中,目标IP非常重要,决定了最终选择的路径。所以在路径上所有的路由器都需要知道目标IP的路由信息,来确定下一步的路由,最后就形成了一条路由路径。

IP = 目标网络 + 目标主机。比如IP有32位,前半部分是目标网络,后半部分是目标主机。所以在路径选择的时候只需要知道目标网络部分就可以了,而不需要知道目标主机部分,因为目标主机部分是在目标网络部分内的。

1. IP协议头

4位版本 4位首部长度 8位服务类型(TOS) 16位总长度(字节)
16位标识 3位标志 13位片偏移量(字节)
8位TTL 8位协议 16位校验和
32位源IP地址
32位目标IP地址
选项(可选)
数据(可变长度)

确定的报头大小为20字节。

1.1 如何将报头和有效数据分离

数据就是上层交付的含有TCP/UDP协议的数据。

4位首部长度单位是4字节,表示报头的字节数,所以最大报头长度为60字节,最小报头长度为20字节,最大计算过程为 1111 * 4 = 60 字节。

这个4位首部长度代表的是报头的字节数,并不是报文的字节数。报文数据的字节数是由 16位总长度(字节)- 报头的字节数 来确定的。

所以IP协议是通过16位总长度(字节)和4位首部长度来分离报头和有效数据的。

1.2 怎么向上交付数据

IP是怎么知道上层到底是TCP还是UDP协议的?答案是通过8位协议字段来判断的。

8位协议字段:1-4位是保留位,5-8位是协议类型。

1.3 16位校验和

用于检测数据报是否被修改过。IP校验不通过,则会丢弃数据报,因为发送方会超时重发,所以直接丢弃数据报即可。

因为TCP的滑动窗口机制,会使发送的数据在发送后不会立刻删除,所以IP协议不保证传输的可靠性,可靠性只能靠TCP协议来保证。

1.4 8位生存时间(TTL)

因为没有人能保证网络的稳定性,所以需要设置一个生存时间,来限制数据报在网络中的传输时间。

因为在数据从源主机发送到目标主机的过程中,会经过多个路由器,所以数据报在路由器之间传递时,每一个路由器都有丢弃报文的权力,本质就是一场接力。因为如果出现环路,则会导致数据报无限在路由器循环。

TTL就是在数据报中添加一个计数器,用于记录数据报在路由器中传递的次数。这个计数器的数字就是在网络中传递的次数,每个路由器会将TTL减1,直到TTL为0,则丢弃数据报(即便这个数据没有问题和没有到达目标主机,也会被丢弃,因为TTL为0)。

1.5 32位目标IP地址

用于指定数据报的接收主机。因为有了目标IP地址,所以数据报才能被正确地发送到目标主机。每一个路由器都需要根据目标IP地址来确定下一步的路由。

1.6 4位版本

用于指定IP协议的版本。当前只有版本4,也叫IPv4。未来可能会有版本5,也叫IPv6,IPv6会使用128位地址空间。因为IPv4和IPv6的地址是不兼容的,所以一般不会在意版本号。

1.7 8位服务类型(TOS)

用于指定数据报的优先级。因为网络中有很多数据报,有的数据报需要优先传输,有的数据报需要后传输,所以需要一个字段来指定数据报的优先级,这个字段就是TOS字段。

8位服务类型包括:3位优先权字段(已经弃用),4位TOS字段,和1位保留字段(必须置为0)。4位TOS分别表示:最小延时,最大吞吐量,最高可靠性,最小成本。这四者相互冲突,只能选择一个。对于ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要。

1.8 16位总长度

IP数据报整体占多少个字节。

16位标识(id):唯一的标识主机发送的报文。如果IP报文在数据链路层被分片了,那么每一个片里面的这个id都是相同的。

3位标志字段:第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。第三位表示"更多分片",如果分片了的话,最后一个分片置为0,其他是1。类似于一个结束标记。

13位分片偏移(fragment offset):是分片相对于原始IP报文开始处的偏移。其实就是在表示当前分片在原报文中处在哪个位置。实际偏移的字节数是这个值 * 8 得到的。因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)。


二、网段划分(重要)

IP地址分为两个部分:目标网络部分、目标主机部分。

1. 形象例子

在学校中,学校可能有多个学院,每个学院可能有多个系,每个系可能有多个学生。所以需要学号来唯一标识每个学生,每一个学号可以由学院号+系号+学生号来组成。

  • 学院号:用于标识学院。
  • 系号:用于标识系。
  • 学生号:用于标识学生。

一个系间可能有多个学生,学生之间可能会维护一个大群,系里面的学生可以相互通信。但是实际中可能不同系的学生也会相互通信,所以需要院的群来让不同系的学生可以相互通信。但是实际上并不是所有的学生都能相互通信,往往需要一个代理人来帮助学生相互通信,通过这个代理人来实现学生之间的通信。发送数据给代理人,代理人会将数据发送到院的群,并指定给某系的代理人,让这个代理人将数据发送给目标学生。所以是一个系的就可以在自己系内相互通信,而不需要通过院的群来实现相互通信。但是不同系的学生就需要通过院的群来实现相互通信,不同系的学生不能直接相互通信,所以通过代理人来实现相互通信。

对应IP地址的网段划分:

  • 学生就是主机,代理人就是路由器。
  • 每一个学生都有唯一的学号,对应IP地址的主机部分。
  • 每一个同学都属于某一个学院的某一个系,对应IP地址的目标网络部分。

所以互联网中的每一个主机都要属于某一个子网,为了方便定位这个主机,因为这样效率高。因为在查找目标主机的时候,只需要知道目标网络就可以排除绝大部分的主机,这样排除效率非常高。所以要引入子网划分。

2. 如何子网划分

再举一个形象的例子。IP地址一共有32位。互联网身处于一个被设计过的世界,在我们国家,被设计过是被三大运营商设计的。实际上IP的划分是按照人口、网络设备接入到互联网的数量来划分的。但为了方便表述,后面的例子使用国家和国家里面的不同地区来划分IP地址。

假设使用8个位来表示国家,8个位来表示不同省份。所以一个国家中的所有主机的前8位都是相同的,一个省份中的所有主机的前16位都是相同的。

在国家之间会维护一个类似于前一个例子的大群(国际网),用于让不同国家的主机可以相互通信。每一个国家都会有一个属于自己的可以链接到这个大群国际网的代理人------国际路由器。所以国际路由器在国际网可以通过前8位来区分这个报文是属于哪个国家的,然后发送给对应的国家的国际路由器。

在每一个省份之间会维护一个类似于前一个例子的大群(国家网),用于让不同省份的主机可以相互通信。每一个省份都会有一个属于自己的可以链接到这个大群国家网的代理人------国家路由器。所以国家路由器在国家网可以通过前16位来区分这个报文是属于哪个省份的,然后发送给对应的省份的国家路由器。

每一个省份又有自己省里面的不同市,每一个市都有自己的省份路由器,用于让不同市的主机可以相互通信等等,一直这样划分,直到每个主机都有自己的IP地址。

国际路由器既属于国际网,也属于国家网,因为国家里面的主机要和国际网的主机相互通信,所以国际路由器要属于国际网,也属于国家网。因为要通过国家网找到国际路由器,然后通过国际路由器发送数据给目标国家的国际路由器,再进行数据的转发。

但是实际上真实情况比这个复杂,需要考虑很多因素,比如路由器的配置、路由表的维护等等,但是思想是一致的。这个是一个理念版的子网划分,实际情况会更复杂。

3. 网络号和主机号

IP地址分为两个部分:网络号和主机号。

  • 网络号:保证相互连接的两个网段具有不同的标识。
  • 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。

不同的子网其实就是把网络号相同的主机放到一起。如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。

想要跨子网通信,需要通过路由器来实现。那么就注定了路由器要属于不同的子网,才能实现跨子网通信,所以路由器的IP地址要属于不同的子网。所以路由器有两个IP地址,一个属于当前子网,一个属于下一个路由的子网。一般来说路由器的IP是末尾的主机号为1的IP地址。

通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。

那么问题来了,手动管理子网内的IP,是一个相当麻烦的事情。有一种技术叫做DHCP,能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便。一般的路由器都带有DHCP功能。因此路由器也可以看做一个DHCP服务器。

4. 五类IP地址

过去曾经提出一种划分网络号和主机号的方案,把所有IP地址分为五类:

  • A类:0.0.0.0 到 127.255.255.255
  • B类:128.0.0.0 到 191.255.255.255
  • C类:192.0.0.0 到 223.255.255.255
  • D类:224.0.0.0 到 239.255.255.255
  • E类:240.0.0.0 到 247.255.255.255

随着Internet的飞速发展,这种划分方案的局限性很快显现出来,大多数组织都申请B类网络地址,导致B类地址很快就分配完了,而A类却浪费了大量地址。例如,申请了一个B类地址,理论上一个子网内能允许6万5千多个主机。A类地址的子网内的主机数更多。然而实际网络架设中,不会存在一个子网内有这么多的情况,因此大量的IP地址都被浪费掉了。

5. CIDR

针对这种情况提出了新的划分方案,称为CIDR(Classless Interdomain Routing):

  • 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号。
  • 子网掩码也是一个32位的正整数,通常用一串"0"来结尾。
  • 将IP地址和子网掩码进行"按位与"操作,得到的结果就是网络号。
  • 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关。

可见,IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围。

IP地址和子网掩码还有一种更简洁的表示方法,例如 140.252.20.68/24,表示IP地址为140.252.20.68,子网掩码的高24位是1,也就是255.255.255.0。

一般一个子网中,管理子网中IP的设备通常是路由器。目标网络和子网掩码、子网中的主机,都会被路由器管理。目标网络和子网掩码、子网中的主机,都会被路由器配置好。

6. 划分子网的例子

例子1:

  • IP地址:140.252.20.68(十六进制:8C FC 14 44)
  • 子网掩码:255.255.255.0(十六进制:FF FF FF 00)
  • 网络号:140.252.20.0(子网IP和掩码的按位与操作的结果)
  • 子网地址范围:140.252.20.0 到 140.252.20.255

一般来说每一个子网的主机号从1开始,因为0是代表网络号的,所以不能作为主机号使用,255一般也不作为主机号使用。所以实际可以容纳的主机数为 1-254。

例子2:

  • IP地址:140.252.20.68(十六进制:8C FC 14 44)
  • 子网掩码:255.255.255.240(十六进制:FF FF FF F0)
  • 网络号:140.252.20.64(子网IP和掩码的按位与操作的结果)
  • 子网地址范围:140.252.20.64 到 140.252.20.79

先看IP地址140.252.20.68,子网掩码255.255.255.240,把两者做按位与运算:先把IP最后一段68转二进制是 01000100,掩码最后一段240转二进制是 11110000,二者按位与得到 01000000,也就是十进制64,所以网络号就是140.252.20.64;掩码255.255.255.240,二进制末尾有4位为主机位,主机位全部置1就是广播地址,主机位4位全1对应二进制 01001111,等于十进制79,因此这个子网的地址范围就是140.252.20.64到140.252.20.79,其中140.252.20.64是子网网络号,140.252.20.79是广播地址,可用主机IP是中间140.252.20.65至140.252.20.78。

所以主机号能动的就是在子网掩码中不为1的位数,掩码二进制为1的部分固定代表网络位,主机位只能在掩码为0的比特上变化;本例掩码255.255.255.240,二进制最后4位是0,这4位就是主机位,可以从 0000 变化到 1111,对应地址范围140.252.20.64~140.252.20.79,其中主机位全0是网络号,主机位全1是广播地址,这两个地址不能分配给主机使用。


三、特殊的IP地址

  • 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网。
  • 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包。
  • 127.* 的IP地址用于本机环回(loopback)测试,通常是127.0.0.1。

四、IP地址的数量限制

IP地址(IPv4)是一个4字节32位的正整数。那么一共只有 2 的 32 次方个IP地址,大概是43亿左右。而TCP/IP协议规定,每个主机都需要有一个IP地址。

这意味着,一共只有43亿台主机能接入网络么?

实际上,由于一些特殊的IP地址的存在,数量远不足43亿;另外IP地址并非是按照主机台数来配置的,而是每一个网卡都需要配置一个或多个IP地址。

CIDR在一定程度上缓解了IP地址不够用的问题(提高了利用率,减少了浪费,但是IP地址的绝对上限并没有增加),仍然不是很够用。这时候有三种方式来解决:

  • 动态分配IP地址:只给接入网络的设备分配IP地址。因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的。
  • NAT技术(后面会重点介绍)。
  • IPv6:IPv6并不是IPv4的简单升级版。这是互不相干的两个协议,彼此并不兼容;IPv6用16字节128位来表示一个IP地址;但是目前IPv6还没有普及。

五、私有IP地址和公网IP地址

如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址:

  • 10.*,前8位是网络号,共16,777,216个地址。
  • 172.16. 到 172.31.,前12位是网络号,共1,048,576个地址。
  • 192.168.*,前16位是网络号,共65,536个地址。

包含在这个范围中的,都成为私有IP,其余的则称为全局IP(或公网IP)。

一个路由器可以配置两个IP地址,一个是WAN口IP,一个是LAN口IP(子网IP)。因为一个路由器会级联很多个子网,所以注定了路由器肯定会存在在多个子网内,作为子网的一部分。

路由器LAN口连接的主机,都从属于当前这个路由器的子网中。WAN口IP则用于连接到外网。也就是说LAN对内WAN对外。

不同的路由器,子网IP其实都是一样的(通常都是192.168.1.1)。子网内的主机IP地址不能重复。但是子网之间的IP地址就可以重复了。

每一个家用路由器,其实又作为运营商路由器的子网中的一个节点。这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP了。

子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN口IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP。这种技术称为NAT(Network Address Translation,网络地址转换)。

如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上。这样的服务器可以在阿里云/腾讯云上进行购买。

假设我的IP为192.168.1.100,我需要访问外网IP 122.77.241.3。一开始时我准备好了一个报文,准备往外发送,我们之前说过想要访问外网一定要通过路由器,所以我需要把报文发送给路由器。路由器收到报文后,会先判断报文的IP地址是否在自己的子网内,如果不在,就会把报文发送给自己的WAN口IP,就交给了运营商路由器。运营商的路由器收到报文后,会判断报文的IP地址是否在自己的子网内,如果不在,就会把报文发送给自己的WAN口IP,这个WAN口IP就是公网IP了。也就是广域网通信了。因为在公网IP是唯一的,所以在广域网内可以被访问到。

在服务器拿到报文后,会判断报文的IP地址是否是自己的IP地址,如果是,就会把报文发送给自己的进程,然后进程会处理报文,构造报文返回。那么就出现了服务器的报文的目的IP填的就不可能是我们的IP了,因为我的IP是私有IP,所以不能被访问到。

所以就出现了NAT技术。在开始时我传给路由器的报文,会把当前请求的源IP替换为WAN口IP,假设家庭路由器的WAN口IP为10.1.1.2,那么这个时候报文的源IP就是10.1.1.2了,目的IP是122.77.241.3。然后在向上传递到运营商路由器,路由器会识别到报文的源IP就是你的路由器的WAN口IP,所以会做相似的工作,把报文的源IP替换为运营商路由器的WAN口IP,122.77.241.4了。这个时候源IP和目的IP都变成了一个子网内的IP地址,所以就能实现通信了。这种不断替换源IP为WAN口IP的技术,就称为NAT技术。

在服务器处理好报文,给我响应时,会收到报文的源IP也就是122.77.241.4运营商路由器的WAN口IP作为目的IP,返回到运营商路由器的入口了。这个返回的过程后面再说,因为还有路由和一些转发的问题还没有解决。

NAPT:如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的IP都是相同的。那么NAT路由器如何判定将这个数据包转发给哪个局域网的主机?这时候NAPT来解决这个问题了,使用IP+port来建立这个关联关系。这种关联关系也是由NAT路由器自动维护的。例如在TCP的情况下,建立连接时,就会生成这个表项;在断开连接后,就会删除这个表项。

NAT技术的缺陷:由于NAT依赖这个转换表,所以有诸多限制:无法从NAT外部向内部服务器建立连接;转换表的生成和销毁都需要额外开销;通信过程中一旦NAT设备异常,即使存在热备,所有的TCP连接也都会断开。

NAT和代理服务器的区别:

  • 从应用上讲,NAT设备是网络基础设备之一,解决的是IP不足的问题。代理服务器则是更贴近具体应用,比如通过代理服务器进行翻墙,另外像迅游这样的加速器,也是使用代理服务器。
  • 从底层实现上讲,NAT是工作在网络层,直接对IP地址进行替换。代理服务器往往工作在应用层。
  • 从使用范围上讲,NAT一般在局域网的出口部署,代理服务器可以在局域网做,也可以在广域网做,也可以跨网。
  • 从部署位置上看,NAT一般集成在防火墙、路由器等硬件设备上,代理服务器则是一个软件程序,需要部署在服务器上。

六、路由

数据包在路由的时候一定要告诉路由目标的IP地址,在IP报头就有一个字段就是目的IP地址。又知道IP可以分为两个部分,一个是网络部分,一个是主机部分。所以路由的过程就是根据网络部分去查找目标主机的子网。

所以一定会有一张路由表,来存储所有的路由信息。

数据包里面就含有一个目的IP地址,在进行路由的过程中会遇到非常多的路由器,每个路由器都有自己的路由表,来存储所有的路由信息。路由器选择下一跳路由器的过程就是查找路由表的过程。

这个就类似于你去问路,你就是主机,你去问问路的人就是路由器。问的结果就会有几种情况:

  1. 我不知道。
  2. 虽然我不知道但是我知道有人知道。
  3. 你先到某个地方再问。
  4. 已经到了。

我在去问路的过程中,就类似于在路由的过程中不断查找路由表,然后根据路由表中的信息来选择下一跳路由器的过程。

  1. 我不知道的情况,在路由的过程中其实是不存在的。
  2. 虽然我不知道但是我知道有人知道的情况,就对应了路由表中一定会有默认路由,我虽然不知道但是我会告诉你默认路由的IP地址,你去默认路由找。
  3. 你先到某个地方再问,在路由的过程中会根据路由表中的信息来选择下一跳路由器,直接转发到下一跳路由器的IP地址。
  4. 已经到了的情况,直接返回目的IP地址,作为路由目标。

但是实际上我们去一个地方的时候往往是一个具体的地方而不是一个区域,所以实际上找到目标子网后还没有结束,还要根据主机部分来确定具体的目标主机(问入口路由器)。

路由的过程,就是这样一跳一跳(Hop by Hop)"问路"的过程。所谓"一跳"就是数据链路层中的一个区间。具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间。

IP数据包的传输过程也和问路一样。当IP数据包到达路由器时,路由器会先查看目的IP;路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器;依次反复,一直到达目标IP地址。

那么如何判定当前这个数据包该发送到哪里呢?这个就依靠每个节点内部维护一个路由表。路由表可以使用 route 命令查看。如果目的IP命中了路由表,就直接转发即可。

路由表中的最后一行,主要由下一跳地址和发送接口两部分组成,当目的地址与路由表中其它行都不匹配时,就按缺省路由条目规定的接口发送到下一跳地址。

假设某主机上的网络接口配置和路由表如下:

Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.10.0 * 255.255.255.0 U 0 0 0 eth0
192.168.56.0 * 255.255.255.0 U 0 0 0 eth1
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default 192.168.10.1 0.0.0.0 UG 0 0 0 eth0

这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到192.168.56.0/24网络。

路由表的Destination是目的网络地址,Genmask是子网掩码,Gateway是下一跳地址,Iface是发送接口,Flags中的U标志表示此条目有效(可以禁用某些条目),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发。

转发过程例1:如果要发送的数据包的目的地址是192.168.56.3,跟第一行的子网掩码做与运算(与计算的过程就是查找路由表的过程)得到192.168.56.0,与第一行的目的网络地址不符,再跟第二行的子网掩码做与运算得到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送出去;由于192.168.56.0/24正是与eth1接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发。

转发过程例2:如果要发送的数据包的目的地址是202.10.1.2,依次和路由表前几项进行对比,发现都不匹配;按缺省路由条目,从eth0接口发出去,发往192.168.10.1路由器;由192.168.10.1路由器根据它的路由表决定下一跳路由器。

所以实际上在路由的过程是越来越具体的过程,子网掩码会越来越变成全1,从而确定具体的目标主机地址。所以在路由的过程实际上目的IP地址是会变的,网络号是会变的,但是最终IP是不会改变的。

路由表生成算法(选学):路由表可以由网络管理员手动维护(静态路由),也可以通过一些算法自动生成(动态路由)。例如距离向量算法、LS算法、Dijkstra算法等。


七、IP分片与组装

在路由器之间传输的是IP报文,但是实际上在网线之间传输的是MAC帧。所以IP的下一层数据链路层的协议就是MAC帧协议。

MAC帧协议规定自己的有效载荷的最大长度是1500字节(MTU,Maximum Transmission Unit)。这个1500字节包括了IP的报头和有效载荷,但是不包括MAC帧的报头。

所以就会要求IP报文的总长度不能超过1500字节,但是IP协议不能决定单个IP报文的长度,但是TCP协议可以决定单个IP报文的长度。

但是会有不正常的情况出现,例如TCP报文的长度超过了1500字节。所以IP就要有临时处理机制,例如分片组装机制(注意分片和组装不是常规的处理机制)。

分片机制就是将一个IP报文分成多个IP报文,每个IP报文的长度都不超过1500字节。组装机制就是将多个IP报文合并成一个IP报文。

分片和组装是IP协议处理的,不是MAC协议处理的,MAC协议不关心是否分片和组装,只关注是否符合MAC帧协议的长度要求。TCP的发送方和接收方都不关心是否分片和组装,所以分片和组装是IP自己独立处理的,所以要和TCP协议、MAC帧协议进行解耦。

注意在进行分片后的IP报文,也是含有IP报文的报头的,只不过在组装的时候会丢弃这个报头,只保留有效载荷。

如何分片和组装?

  1. 你怎么知道这个报文是被分片了?
  2. 同一个IP报文的分片要能够识别出来。
  3. 哪一个是第一个分片,哪一个是最后一个分片,有没有收全或者丢失分片。
  4. 区分哪个在前哪个在后,如何正确的进行组装。
  5. 怎么保证合起来的报文是正确的。
  • 16位标识(id):唯一的标识主机发送的报文。如果IP报文在数据链路层被分片了,那么每一个片里面的这个id都是相同的。
  • 3位标志字段:第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。第三位表示"更多分片",如果分片了的话,最后一个分片置为0,其他是1。类似于一个结束标记。没有分片默认为0,如果后面还有分片则为1,反之为0。
  • 13位分片偏移(fragment offset):是分片相对于原始IP报文开始处的偏移。其实就是在表示当前分片在原报文中处在哪个位置。实际偏移的字节数是这个值 * 8 得到的。因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)。

对应回答:

  1. 怎么知道这个报文是被分片了?根据标志字段的值为1,但是标志字段的值为0并且分片偏移量大于0,说明是分片。

  2. 同一个IP报文的分片要能够识别出来:16位标识(id)是同一个。

  3. 哪一个是第一个分片,哪一个是最后一个分片,有没有收全或者丢失分片:根据标志字段的值为0和1。第一个分片的标志字段的值为1,且分片偏移量为0;最后一个分片的标志字段的值为0,且分片偏移量大于0。我们不能保证一定收全了,但是我们把偏移量排序一下,就依次进行计算,就可以保证正确的组装。当前分片起始位置 + 当前分片的长度 = 下一个分片的偏移量*8,如果不是,说明有丢失的分片。

  4. 区分哪个在前哪个在后,如何正确的进行组装:根据分片偏移量的值。

  5. 怎么保证合起来的报文是正确的:根据IP的报头中的16位首部校验和来判断,TCP的16位校验和来判断。

思考:

  1. 分片好吗?
  2. 对TCP和UDP协议包括IP本身有什么影响吗?

回答:

  1. 特别不好,原因是是否分片对于TCP和UDP协议和MAC帧协议都不在意。
  2. 所以假设一个报文被分片了,那么就有可能在传输过程中丢失分片,就会导致拼接失败,就会要求重新发送。但是补发不是只补发丢失的分片,而是会补发所有的分片。丢失的分片补发不是问题,问题是分片后丢失的机率会增加。

例子:

当传输层产生3000字节数据,加上20字节IP头部变成3020字节时,由于链路层MTU限制为1500字节,网络层必须将其拆分;为了满足MTU,每个分片都需携带20字节头部,因此单次最大承载数据为1480字节,原始数据被分为三个分片,即两个1480字节数据的分片和一个40字节数据的分片。图底部引出的三个数字正是分片控制的关键字段:第一个数字"1111"是16位标识符,用于标记这些分片属于同一个原始数据包;第二个数字"1"是3位标志中的MF位,表示"后面还有分片";第三个数字"0"是13位片偏移,表示该分片在原始数据中的位置(此处为首个分片,偏移量为0)。接收端在收到所有标识符为1111的分片后,会根据片偏移量(0、185、370)将它们排序并拼接数据,最终在收到MF位为0的最后一个分片时完成组装,还原出完整的3000字节数据。

MTU对IP协议的影响:由于数据链路层MTU的限制,对于较大的IP数据包要进行分包。将较大的IP包分成多个小包,并给每个小包打上标签;每个小包IP协议头的16位标识(id)都是相同的;每个小包的IP协议头的3位标志字段中,第2位置为0,表示允许分片,第3位来表示结束标记(当前是否是最后一个小包,是的话置为1,否则置为0);到达对端时再将这些小包,会按顺序重组,拼装到一起返回给传输层;一旦这些小包中任意一个小包丢失,接收端的重组就会失败。但是IP层不会负责重新传输数据。

MTU对UDP协议的影响:一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)),那么就会在网络层分成多个IP数据报。这多个IP数据报有任意一个丢失,都会引起接收端网络层重组失败。那么这就意味着,如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了。

MTU对TCP协议的影响:TCP的一个数据报也不能无限大,还是受制于MTU。TCP的单个数据报的最大消息长度,称为MSS(Max Segment Size)。TCP在建立连接的过程中,通信双方会进行MSS协商。最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU)。双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值。然后双方得知对方的MSS值之后,选择较小的作为最终MSS。MSS的值就是在TCP首部的40字节变长选项中(kind=2)。

MSS和MTU的关系:MTU = MSS + TCP首部 + IP首部。


八、ICMP协议

ICMP协议是一个网络层协议。一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否畅通;但是IP协议并不提供可靠传输。如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。

ICMP正是提供这种功能的协议。ICMP主要功能包括:

  • 确认IP包是否成功到达目标地址。
  • 通知在发送过程中IP包被丢弃的原因。

ICMP也是基于IP协议工作的。但是它并不是传输层的功能,因此人们仍然把它归结为网络层协议。ICMP只能搭配IPv4使用。如果是IPv6的情况下,需要是用ICMPv6。

ICMP的报文格式:

ICMP大概分为两类报文:

  • 一类是通知出错原因。
  • 一类是用于诊断查询。

常见类型:

  • 0:回送应答(Echo Reply)
  • 3:目标不可达(Destination Unreachable)
  • 4:原点抑制(Source Quench)
  • 5:重定向或改变路由(Redirect)
  • 8:回送请求(Echo Request)
  • 9:路由器公告(Router Advertisement)
  • 10:路由器请求(Router Solicitation)
  • 11:超时(Time Exceeded)
  • 17:地址子网请求(Address Mask Request)
  • 18:地址子网应答(Address Mask Reply)

ping命令:

ping命令基于ICMP,是在网络层。而端口号,是传输层的内容。在ICMP中根本就不关注端口号这样的信息。

ping命令不光能验证网络的连通性,同时也会统计响应时间和TTL(IP包中的Time To Live,生存周期)。ping命令会先发送一个ICMP Echo Request给对端;对端接收到之后,会返回一个ICMP Echo Reply。

注意,此处ping的是域名,而不是URL!一个域名可以通过DNS解析成IP地址。

traceroute命令:

也是基于ICMP协议实现,能够打印出可执行程序主机,一直到目标主机之前经历多少路由器。


九、总结

网络层:

  • 网络层的作用:在复杂的网络环境中确定一个合适的路径。
  • 理解IP地址,理解IP地址和MAC地址的区别。
  • 理解IP协议格式。
  • 了解网段划分方法。
  • 理解如何解决IP数目不足的问题,掌握网段划分的两种方案。理解私有IP和公网IP。
  • 理解网络层的IP地址路由过程。理解一个数据包如何跨越网段到达最终目的地。
  • 理解IP数据包分包的原因。
  • 了解ICMP协议。
  • 了解NAT设备的工作原理。
相关推荐
辻弋2011 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
硅基手札2 小时前
【Linux内核专栏 14】网络协议栈
linux·运维·网络协议
可乐鸡翅yeah_2 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
沫璃染墨3 小时前
《Linux工程实践篇(一):认识设计模式——从日志系统看策略模式》
linux·c++·安全·设计模式·策略模式
工作10年+,存储芯片行业3 小时前
Linux NVMe 中断排查与性能优化:CPU 亲和性
linux·运维·服务器·windows·性能优化·ssd·pcie
酣大智4 小时前
H3C MSR3600 交换机配置 SSH
网络·ssh·智能路由器
wuminyu4 小时前
ForkJoinPool内部WorkQueue的Lock-Free数组操作以及并发任务窃取原理剖析
java·linux·c语言·jvm·c++
沐浴露z4 小时前
Agent 响应延迟过高?从工具治理角度提供两条思路
前端·网络
她说彩礼65万4 小时前
C语言 堆区和栈区
java·linux·c语言