IP 协议简述

501 阅读14分钟

这篇文章会对 IP 的知识点做一个简单的讲解,旨在让读者对 IP 有一些整体框架认知,若需要进行更深层次的学习,还需找专业的书籍深度阅读,比如《TCP/IP 详解》。

简介

网际协议(Internet Protocol)是 TCP/IP 协议族中最核心的协议,所有 TCP、UDP、ICMP 及 IGMP 数据都已 IP 数据报格式传输。

IP 仅提供最好的传输服务,不保证数据报能成功到达目的地(不可靠),若发生某种错误,IP 会丢弃该数据报,并发送 ICMP 消息报给源端。

IP 不维护任何关于后续数据报的状态信息(无连接),每个数据报的处理是相互独立的,没有所谓的顺序,选路也是独立的。

首部

同样,对一个协议的了解可以从首部的了解开始,IP 协议首部的传输是以大端(big endian)字节序传输的,即每4 字节的 32 bit 值以 07、815、1623、2431 的次序传输。由于 TCP/IP 首部中所有二进制整数在网络中传输时都要求以这种次序,故又称为网络字节序。以 little endian 格式存储二进制整数的机器,在传输数据前必须将首部转换成网络字节序。

image.png

版本

目前 IP 协议的主要版本为第四版(IPv4)和第六版(IPv6),以上的首部为第四版的首部。

自 IPv4 问世以来,随着 Internet 的快速增长,IPv4 的问题也逐渐显露出来:

  • 32 bit 的 IP 地址从 Internet 增长的角度来看,肯定是不够用的。
  • 当前的 IP 路由属于平面型结构,没有层次结构,每个网络都需要一个路由表目,随着网络数目增长,具有多网络的网站就必须分配多个 C 类地址,路由表的规模会不断增长。
  • IPv4 不能对某些有数据加密和鉴别要求的应用提供支持。
  • IPv4 没有提供对实时音频和视频传输这种要求传输最小时延的策略和预留资源支持。

所以,IPv6 被提了出来,其地址格式、分组格式和分组长度都改变了,IPv6 地址以冒号分隔 8 个 16 进制数,形成一个 128 位的地址。不过在此处先不对 IPv6 做更多讲解。

首部长度

首部长度是指首部占 32 bit 的数目,是一个 4 bit 字段,故首部最长为 60 字节。其中固定首部占 20 字节,可选首部最多占 40 字节。

服务类型

服务类型(TOS)包含 3 bit 优先权子字段(已忽略),4 bit TOS 子字段和 1 bit 未用位(必为 0)。4 bit 的 TOS 分别代表:最小时延、最大吞吐量、最高可靠性和最小费用。只能设置其中 1 bit,全为 0 表示一般服务。

RFC 1340 描述了所有标准应用如何设置 TOS,RFC 1349 对 1340 进行了修正,更详细的描述了 TOS 特性。

总长度

总长度字段指整个 IP 数据报占用字节数。占 16 bit,故 IP 数据报最长为 65535 字节。IP 数据报被分片时,每片的总长度值也会改为该片的长度值。

总长度字段是必要的,一些链路需要填充数据以达到最小长度(如以太网最小帧长 46 字节),总长度字段能让 IP 层知道哪些是数据报内容。

标识 + 标志 + 片偏移

标识字段唯一的标识每一份数据报,通常每发一份报文,IP 层都会将内核变量的值加 1,不管数据来自上层哪个协议。内核变量的初始值根据系统引导时的时间来设置。

在 IP 数据报分片时,该字段会被复制到每个片中。

标志字段的其中一个 bit 用于表示「更多的片」,除了最后一片外,该 bit 在其余每片都被设置为 1。

片偏移字段指该片偏移原始数据报开始处的位置。

标志字段中有一个 bit 表示「不分片」位,若该 bit 被设置为 1,IP 将不对数据报进行分片,若此时 IP 数据报过长,会被丢弃,并发送一个 ICMP 差错报文。

生存时间

生存时间(TTL,time-to-live)字段设置了数据报可以经过的最多路由器数。

初始值由源主机设置(通常 32 或 64),每个处理数据报的路由器,都会将 TTL 的值减 1 或减去数据报在路由器中停留的秒数,由于大多数时延都小于 1s,因此 TTL 最终成为一个跳站的计数器,即每经过一个路由器都将其值减 1。值为 0 时,数据报被丢弃,并发送 ICMP 「超时」 报文通知源主机。

协议

协议字段可让 IP 层识别上层是哪个协议。

当主机收到一个以太网的数据帧时,数据就开始从协议栈中由底向上升,同时去掉各层协议加上的报文首部。每层协议都要去检查报文首部的协议字段,以确定接收数据的上层协议,该过程称为分用。

image.png

首部检验和

首部检验和字段是根据 IP 首部计算的检验和码。

要算首部检验和,先将检验和设为 0,然后对首部中每 16 bit 进行二进制反码求和(先求和,再取反),将结果存入检验和字段。

在接收端 IP 层收到数据报后,同样对首部每 16 bit 进行二进制求和,由于接收方的计算值包含了发送方存在首部中的检验和,若首部在传输过程中未发生任何差错,接收方计算的结果应全为 1。若非全为 1,即检验和错误,丢弃数据报,且不发送差错报文,由上层发现丢失和重传。

假如发送前 IP 首部的 20 字节如下:

12 34  56 78  9A BC  DE F0  12 34  00 00  9A BC  DE F0  12 34  56 78

计算前检验和字段被设置为 0,即上面带下划线部分。

将首部每 16 bit 进行二进制求和:

0x1234 + 0x5678 + 0x9ABC + 0xDEF0 + 0x1234 + 0x9ABC + 0xDEF0 + 0x1234 + 0x5678 = 0x3D6E4
// 由于校验和字段为 16 bit,将结果的高位加回到低 16 位
0x0003 + 0xD6E4 = 0xD6E7

再将结果按 16 bit 无符号数按位取反:

~0xDE67 = 0x2918

再将结果存入检验和字段,得到最终 IP 首部:

12 34  56 78  9A BC  DE F0  12 34  29 18  9A BC  DE F0  12 34  56 78

接收方收到首部后,同样按每 16 bit 进行二进制求和:

0x1234 + 0x5678 + 0x9ABC + 0xDEF0 + 0x1234 + 0x2918 + 0x9ABC + 0xDEF0 + 0x1234 + 0x5678 = 0x3FFFC
// 由于校验和字段为 16 bit,将结果的高位加回到低 16 位
0x0003 + 0xFFFC = 0xFFFF

由于路由器经常只修改 TTL 字段(减 1),因此当路由器转发一份报文时,可以增加它的检验和,而不需要重新计算,RFC 1141 给出了一个很有效的办法,但标准的 BSD 实现在转发报文时并非采用这种增加的办法。

源 IP 地址 + 目的 IP 地址

互联网上的每个接口必须有一个唯一的 Internet 地址,也称作 IP 地址。多接口主机具有多个 IP 地址,每个接口对应一个。

IPv4 的地址长 32 bit,并不采用平面形式的地址空间,而是具有一定的结构,五类不同的互联网地址格式如下:

image.png

点分十进制表示法:这些 32 bit 的地址通常写成 4 个十进制的数,每个整数对应一个字节,通过点分隔。

子网相关概念会在下面做介绍。

可选项

可选项是数据报中的一个可变长的可选信息,每个可选项字段以 32 bit 作为界限,必要时会插入值为 0 的填充字节,以确保 IP 首部始终是 32 bit 的整数倍。

选项定义如下:

  • 安全和处理限制:用于军事领域,详细内容参见 RFC 1108
  • 记录路径:
    • 让每个处理该数据报的路由器都把它的 IP 地址放入选项字段中,数据报到达目的端时,IP 地址清单被复制到 ICMP 回显应答中。
    • 由于 IP 首部长最多为 60 字节,除去固定长度和记录路径选项占用的字节数,只能存放 9 个 IP 地址,是非常有限的。
  • 时间戳:根据时间戳选项的标志位可分为如下模式
    • 0:只记录时间戳,与记录路径一样,只能存放 9 个时间戳。
    • 1:每台路由器都记录它的 IP 地址和时间戳,只能存放 4 对地址和时间戳。
    • 3:发送端对选项列表进行初始化,存放了 4 个 IP 地址和 4 个取值为 0 的时间戳,当 IP 地址与当前路由器地址相匹配时,才记录时间戳。
  • 宽松的源站选路:发送端指定了一个数据报必须经过的 IP 地址清单,但数据报在清单上任意两个地址之间还可以通过其他路由器。
  • 严格的源站选路:发送端指明数据报必须采用的确切路由,若路由器发现源站所指定的下一个路由器不在其直接连接的网络上,则返回一个「源站路由失败」的 ICMP 差错报文。

IP 选路

选路是 IP 最重要的功能之一,在主观上可将其简单拆分为两个部分:

  • 选路策略:通过路由守护程序提供,决定将哪些路由放入到路由表中。
  • 选路机制:由 IP 层做出的路由决策,它搜索路由表并决定向哪个网络接口发送分组。

由于整个 IP 选路是非常复杂的,包括在主机上运行何种路由协议、如何与相邻路由器交换选路信息以及选路协议如何工作等。因此在这里我们只是简单了解单个 IP 层做出的路由决策,更深入的内容可通过专业的书籍和文献了解。

首先 IP 层收到的数据报有两个来源:本地主机产生、通过网络接口接收。

  • 本地主机产生:主机会对数据报进行选路和转发。
  • 网络接口接收:
    • 若目的地址是本机,则将数据报送到首部协议字段指定的协议模块处理。
    • 若目的地址不是本机,且主机未被配置成路由器,数据报会被静默丢弃,主机被配置成路由器则会对数据报进行转发。

路由表中包含的信息决定了 IP 层做出的选路决策,接下来让我们了解一下路由表的每项包含的信息:

  • 目的 IP 地址(Destination):
    • 可以是完整的主机地址,包含非 0 的主机号。
    • 也可以是一个网络地址,主机号为 0,表示网络中所有主机。
  • 网关(Gateway):下一跳路由器的 IP 地址,或有直接连接的网络 IP 地址。下一跳路由器指一个在直接相连网络上的路由器,通过它转发数据报。
  • 标志(Flags):
    • U:该路由可以使用。
    • G:该路由器是一个路由器(Gateway),若无该标志,说明目的地是直接相连的接口。
    • H:该路由是一个主机,若无该标志,说明目的地址是一个网络地址。
    • D:该路由是由重定向报文创建的。
    • M:该路由已被重定向报文修改。
  • 引用计数(Refcnt):表示正在使用路由的活动进程个数。面向连接的协议(如 TCP)在建立连接时需要固定路由。
  • 分组数(Use):表示通过该路由发送的分组数。
  • 接口(Interface):表示数据报传输的一个本地网络接口。

IP 路由选择是逐跳进行的,IP 并不知道到达目的的完整路径,路由选择只为数据报的传输提供下一跳路由器的 IP 地址,它假定下一跳路由器更接近目的地,并且下一跳路由器与该主机是直接相连的。

简单了解了 IP 层维护的路由表信息,接下来讲讲 IP 搜索路由表的步骤:

  1. 查找是否有与目的 IP 地址完全匹配的表目,若找到,则将报文发给该表目指定的下一跳路由器或直连的网络接口。
  2. 查找与目的网络号相匹配的表目,若找到,则将报文发给该表目指定的下一跳路由器或直连的网络接口(目的网络上的所有主机都通过该表目处理)。
  3. 查找标为「默认」的表目,若找到,将报文发送给该表目指定的下一跳路由器。
  4. 以上步骤都不成功(如路由表中无默认项且找不到匹配项),则数据报不会被发送。
    1. 若数据报来自本机,则给应用程序发送一个「主机不可达」或「网络不可达」的错误。
    2. 若数据来自网络接口,则给原始发送端发送一份 ICMP 主机不可达的差错报文。

由于 IP 路由选择不一定要完全匹配目的 IP 地址,所以为一个网络而非每个主机指定一个路由器,可以避免维护大量非同一网络下的主机 IP,极大地缩小路由表的规模。

子网

由于 A、B 类地址为主机号分配了太多空间,而一个网络中并不会安排这么多主机,所以现在所有的主机都要求支持子网编址,把主机号再分成一个子网号和一个主机号。

由系统管理员决定是否为某类 IP 网络号建立子网,以及分配多少 bit 给子网号和网络号。例如 B 类地址原本的主机号为 16 bits,管理员可以决定将这 16 bits 中的前 8 bits 用于子网号,后 8 bits 用于网络号:

image.png

如图所示,这样就允许有 254 个子网,每个子网有 254 台主机(全 0 或全 1 的主机号都是无效的)。

子网对于外部路由器来说隐藏了内部网络组织的细节,与全 C 类地址相比,B 类地址划分子网可以缩小路由表的规模。当然,C 类地址也可以通过 CIDR 技术缩减路由表规模。

子网掩码

上面提到了 IP 地址可以划分子网,那么一台主机是如何知道这个子网的划分结果,以及自己是处于哪个子网呢?答案是通过子网掩码来确定子网号与主机号的分界的。

一个主机除了需要知道自己的 IP 地址外,还需要通过子网掩码来确定有多少比特用于子网号以及多少比特用于主机号。子网掩码是一个 32 bits 的值,值为 1 的比特位留给网络号和子网号,值为 0 的比特位留给主机号。例如对一个 B 类地址的两种不同划分:

image.png

IP 地址常用点分十进制表示,但由于子网掩码是一个比特掩码(界限并非一个字节),常用十六进制表示。

在主机知道到 IP 地址和子网掩码后,首先通过 IP 地址高位可得知是哪类地址,就可知道网络号和子网号的分界线,再结合子网掩码就可知道主机号与网络号的分界线。

有了上面的数据,在主机获取到一个数据报时,就可以确定 IP 数据报的目的地是否:

  1. 本子网上的主机
  2. 本网络中其他子网的主机
  3. 其他网络上的主机

以上就是 IP 协议的一些框架知识梳理,有兴趣进行深入了解的,还是建议看一下专业的书籍。