IP
IP 协议初探
在真实世界中,我们使用地址找到一个地点,比如 中国 北京市 海淀区 某街道 某小区 某一栋 某一户
。
在互联网中我们如果想定位某个机器,也需要使用同样的方式给其指定一个地址,这样的地址就叫做 IP 地址,IP 的英文全程是 Internet Protocol,直译作互联网协议。
但仅有地址是不够的,如何将数据从源地址发送到目的地址也是 IP 协议需要解决的一个问题。互联网是一个由众多网络设备组成的一个全球性的网络,从 一个机器 到 另一个机器,中间可能需要经过多个的网络设备,如何保证我们的数据可以 通过某条路径到达 正确地目的地呢,这个过程需要 IP 协议和协议共同配合以实现,在后面我们会逐步了解这个过程。
IP 协议目前包含两个版本,分别是 IPv4 (Version 4)以及 IPv6 (Version 6),后文将逐步介绍这两个协议,当然重点在于掌握 IPv4 的具体细节。
IPv4 地址格式
IPv4 的地址由 4 个字节构成,共有 32 位,比如 11000000.10101000.00000100.00000010
就是一个 IPv4 的地址。
二进制的表示方式太晦涩,所以常用的表示方式是 点分十进制,上一段话中的 IPv4 地址的点分十进制表示方式就是 192.168.4.2
。
点分十进制说对于4个字节中的每个字节,我们用十进制表示其值,每个字节之间,我们用点来间隔,点分十进制因此得名。
IPv4 首部
IP 协议位于 OSI 7层模型的网络层,其承载上层(传输层)的数据,对其进行 封装,然后传递给下层(数据链路层)进行进一步的处理。
封装的具体过程就是为 传输层的数据 加上 IP 协议的首部的二进制表示,IPv4 的首部的 逻辑格式 如下图所示,其中包含多个字段,长度通常为 20 个字节。
字段初探
这一小节我会简单介绍各个字段,帮助大家建立一个粗略的了解,部分字段的细节我会在后面几个小节详解说明。
- 版本(Version):
- 4 位字段,用于指定 IP 协议版本,IPv4 的版本为 4。
- 头部长度(Header Length):
- 4 位字段,用于指示 IPv4 首部的长度,以 4 字节为单位。由于 IPv4 首部的固定部分长度为 20 字节,因此这个字段的值通常是 5(即该字段二进制表示为
0101
,5 * 4(4字节为单位) = 20
,最终表示的长度为 20)。
- 4 位字段,用于指示 IPv4 首部的长度,以 4 字节为单位。由于 IPv4 首部的固定部分长度为 20 字节,因此这个字段的值通常是 5(即该字段二进制表示为
- 服务类型(Type of Service):
- 8 位字段,用于指定数据报的服务质量(Quality of Service,QoS),包括优先级、延迟、吞吐量等。
- 总长度(Total Length):
- 16 位字段,指定整个 IPv4 数据报(包括首部和数据部分)的总长度,以字节为单位。最大值为 65535 字节。
- 标识(Identification):
- 16 位字段,用于唯一标识数据报。通常在数据报分片时用于重新组装数据报。
- 标志(Flags):3 位字段,包括以下标志:
- 最左边位:保留为 0,未使用。
- DF(Don’t Fragment):
- 如果设置为 1,表示数据报不允许分片。则路由器会丢弃该数据报,并发送一个ICMP错误消息(“Fragmentation Needed and DF Set”)返回给发送方,告知需要分片但不允许分片。
- 如果设置为 0,标识允许分片,路由器在传输过程中如果需要,可以将数据报分片,以确保数据报能够通过传输链路。
- MF(More Fragments):
- 如果设置为 1,还有更多的分片;
- 如果设置为0,表示当前分片是对应数据报的最后一个分片,或者表示当前数据报根本没有分片。
- 片偏移(Fragment Offset):
- 13 位字段,用于指示数据报分片的位置。以 8 字节为单位,表示相对于原始数据报的偏移量。
- 生存时间(Time to Live,TTL):
- 8 位字段,指定数据报在网络中可存在的最大时间(跳数),每经过一个路由器,TTL 减 1,当 TTL 减至 0 时,数据报被丢弃。
- 协议(Protocol):
- 8 位字段,指定上层协议,表示数据报的载荷是由哪个协议处理。例如,6 表示 TCP,17 表示 UDP。
- 首部校验和(Header Checksum):
- 16 位字段,用于检测 IPv4 首部的错误。
- 源 IP 地址(Source IP Address):
- 32 位字段,指定数据报的发送者的 IP 地址。
- 目标 IP 地址(Destination IP Address):
- 32 位字段,指定数据报的接收者的 IP 地址。
- 选项(Options):
- 可选字段,长度可变,用于包含一些额外的信息。IPv4 首部中的选项字段通常很少被使用。
分片和相关字段
简而言之, IP 数据报的最大长度为 65535 字节(总长度字段为 16 位,16 位可以表示的最大非负整数为 65535),而数据链路层的 MTU 往往都小于该值(比如以太网 ethernet 的 MTU 为 1500),所以为了在数据链路上传输这些数据,就需要将数据报(ip packet)进行拆分为不同的分片(ip fragmentation),更多关于分片的细节可以查看 IP数据报分片。
这个时候就会出现两个问题,我将 packet A 和 packet B 都拆分为了不同分片,比如我将 packet A 拆分为分片 A1、A2 和 A3,将 packet B 拆分 B1、B2。那么我如何区分这些不同的分片,我怎么知道 A1 是来自于 packet A 而不是 packet B 的呢?以及我如何将同一个数据报的不同分片再结合起来形成原始数据报呢?
为了实现以上需求,IP 协议首部包含如下字段:
- Identification 标识字段用于区分 不同数据报 以及其 分片
- Fragment Offset 标识字段标识当前分片中的数据在整个数据报中的偏移
差错校验字段
IP 首部的 checksum 为 IP 协议的差错校验字段,用于检验 IP 首部在传输的过程中是否发生错误,接下来我会告诉你如何通过该字段进行校验。
当一个 IP 数据报被创建时,发送端设备会计算 IP 头部的校验和,并填充 IP 数据报中的 checksum 字段。
当 路由器 和 目标机器 在收到数据报时会重新计算首部校验和,并将计算得到的校验和和接收到的 IP数据报中的 checksum 进行比较。如果不一致的话,则说明 IP 数据报中的某些数据在传输的过程中出现变动,就需要丢弃该 IP 数据报。
需要注意的是,当 IP数据报 经过某个路由器时,路由器需要重新计算并填充 checksum 字段,因为 IP 数据报中的某些字段在经过路由器时会被改变(比如 TLL 会减 1 等)。
一般而言,对于校验和,了解到以上程度即可,如果你好奇校验和究竟是如何计算且学有余力的话,可以查看checksum 校验和计算方式。
IPv4 地址初探
前文已经谈到,IP 地址是帮助我们在互联网中定位到一个机器,从而可以根据该地址进行数据传输。
所以,从逻辑上来说,IP 地址可以被拆分为两个部分:
- 网络编号:IP 地址的前若干位,以确定一个网络。
- 主机编号:IP 地址的后若干位,以在网络中确定的一个机器。
网络编号确定 IP 地址在哪个网络中,主机编号确定该机器是网络中的哪一台机器。
IPv4 地址分组
在互联网早期,IP地址采用了分类寻址(classful addressing),具体而言,就是将 IP 地址根据其网络编号(前几位)分为 A、B、C 和 D 类。
在分类寻址中,如果给定一个 IP 地址,我们可以马上判断出该 IP 地址属于哪一类网络(根据前几位的值),以及该 IP 地址的 网络编号 和 主机编号是多少。
类别 | 网络编号 | 主机数量 | 用途 | 网络数量 |
---|---|---|---|---|
A 类 | 8位,第一位一定是1 | 2^24 - 2 = 16,777,214 | 大型网络 | 2^7 = 128 |
B 类 | 16位,前两位一定是10 | 2^16 - 2 = 65,534 | 中型规模网络 | 2^14 |
C 类 | 24位,前三位一定是110 | 2^8 - 2 = 254 | 小型网络 | 2^21 |
D 类 | 4位,固定为1110 | 2^28 = 268,435,456 | 多播网络 | 1 |
分类寻址可以简化路由器的设计和IP地址的分配,而且简单的策略是最好满足当时的需求的,少就是多,从简设计并没有什么不好。
但是人算不如天算,最早设计 IP 协议的专家并没想到若干年后会有如此多的联网设备,每个设备都需要分配一个 IP 地址,而 IP 地址的数量 相比 这些设备的数量 已经捉襟见肘。
使用分类 IP 也加剧了这种问题。首先,这种分类方式过于不灵活,会造成地址空间浪费的现象。 例如,一个B类地址可以容纳65,534个主机,但如果一个组织只有几千台主机,剩余的地址就浪费了。同样,如果一个C类地址不足以满足一个组织的需求,但B类又太大,分配就变得困难。
为了解决这个问题,聪明的计算机专家们又发明了 CIDR、NAT 等技术 以及 IPv6 协议。
CIDR
无类别域间路由(CIDR,classless inter-domain routing) 的主要目标是克服传统的基于类别的 IP 地址划分方法,使网络资源的分配更加灵活和高效。
在 分类寻址 中,每一类网络的网络编号的长度是固定的,在 CIDR 中,网络编号的长度是动态的,可以根据需求定制。其中网络编号的长度叫做前缀长度(Prefix Length),前缀长度通常以 IP地址 斜杠后跟一个数字表示,例如,192.168.1.13/24
表示前 24 位是网络部分,剩下的位数用于主机。
这里就要提到子网掩码(subnet mask)这个概念,如果一个 CIDR 网络的前缀长度是 n 位的话,那么其子网掩码的二进制表示就是 111 (n 个 1) ... 0000 (32-n 个 0)
,该子网掩码对应的点分十进制如下图所示。
子网掩码的作用是找到 IP 地址的子网地址,IP地址 与 子网掩码 进行 与操作计算 即可得到对应的子网地址。子网地址的主机位全部为0。
子网划分
子网划分(Subnetting)是将一个较大的IP网络分割为多个更小的网络(子网)的过程。这种操作通常是在IP地址的网络部分与主机部分之间进一步引入子网位,以创建子网标识符。通过子网划分,网络管理员可以更有效地管理IP地址,减少网络流量,优化路由,并提高网络安全性。
在子网划分过程中,子网掩码(Subnet Mask)用于区分IP地址的网络部分和主机部分。常见的做法是通过调整子网掩码的长度,将更多位分配给网络部分,减少主机部分的位数。
子网划分包含 变长子网划分(Variable Length Subnet Masking, VLSM)和 固定长度子网划分(Fixed Length Subnet Mask, FLSM)两种方式。
变长子网划分
变长子网划分使用不同长度的掩码来划分IP地址空间,从而根据实际需求为各个子网分配不同数量的地址。
假设你有一个 C 类网络192.168.1.0/24
,需要划分给三个部门,其中 A 部门需要 100 个 IP 地址,B 部门需要 50 个 IP 地址,C 部门只需要 25 个 IP 地址。
使用 VLSM,你可能会这样划分:
部分名称 | 子网地址 | 掩码 | 地址个数 |
---|---|---|---|
A 部门 | 192.168.1.0/25 | 255.255.255.128 | 128 |
B 部门 | 192.168.1.128/26 | 255.255.255.192 | 64 |
C 部门 | 192.168.1.192/27 | 255.255.255.224 | 32 |
定长子网划分
固定长度子网划分使用相同长度的子网掩码来划分网络。这种方法在划分时更为简单和直接,但通常不如VLSM灵活高效。
假设你有一个 C 类网络192.168.1.0/24
,需要划分给A, B, C, D四个部门,可以这样划分:
部分名称 | 子网地址 | 掩码 | 地址个数 |
---|---|---|---|
A 部门 | 192.168.1.0/26 | 255.255.255.192 | 64 |
B 部门 | 192.168.1.64/26 | 255.255.255.192 | 64 |
C 部门 | 192.168.1.128/26 | 255.255.255.192 | 64 |
D 部门 | 192.168.1.192/26 | 255.255.255.192 | 64 |
注意以上地址个数中包含全0和全1的无效地址。
IP 数据报分片
P 数据报分片是一种网络通信中的过程,它允许较大的 IP 数据报在经过一些网络链路时被分割成多个较小的片段,以适应网络链路的最大传输单元(MTU,Maximum Transmission Unit)。MTU 是指网络链路能够传输的最大数据报大小,不同网络链路的 MTU 大小可能不同。当一个 IP 数据报的大小超过了某个链路的 MTU 时,它就需要被分片,以确保可以顺利传输。
注意
MTU 指的是链路层帧中有效负载(Payload)部分的最大字节数,不包括链路层的帧头(Frame Header)和帧尾(Trailer)。
数据链路中的负载(Payload)包含 IP 数据报的首部(20B)和数据部分。
以下是 IP 数据报分片的基本过程:
- 发送端分片:
- 发送端的主机首先创建一个 IP 数据报,并将它发送到目标主机。这个数据报的大小可能大于某些链路的 MTU。
- 路由器检查 MTU:
- 当数据报经过路由器时,路由器会检查下一个链路的 MTU 大小。它会比较数据报的大小和链路 MTU。
- 如果数据报的大小小于或等于链路 MTU,那么数据报会继续传输,无需分片。
- 如果数据报的大小大于链路 MTU,那么路由器需要将数据报分片为多个较小的片段,以适应链路 MTU。
- 数据报分片:
- 当数据报需要分片时,路由器会将数据报拆分成多个片段。每个片段都会包含原始数据报的一部分数据。
- 每个片段的头部将保留原始数据报的首部,但有一个特殊的标志(Fragment Offset)来指示它在原始数据报中的位置。
- 路由器将这些片段分别发送到下一个链路。
- 目标端重组:
- 当片段到达目标主机时,目标主机将重新组装这些片段以恢复原始的数据报。
- 目标主机使用每个片段的标志和偏移量信息来确定如何正确地重组数据报。
分片例子:
以上图为例,假设我们有一个 IP 数据报,其总长度为 10000 字节,它需要通过两个链路,两个链路的 MTU 分别为 4000 和 2500 字节。当 IP 数据报经过第一个链路时,它需要被拆分为 3 个分片以通过链路:
数据报 | 首部长度 | 数据长度 | 总长度 | 偏移量 | 片偏移字段 | MF 标志位 | ID 字段 |
---|---|---|---|---|---|---|---|
原始 IP 数据报 | 20 | 10000 | 10020 | - | 0 | 0 | 578 |
分片 1 | 20 | 3976 | 3996 | 0 | 0 | 1 | 578 |
分片 2 | 20 | 3976 | 3996 | 3976 | 497 | 1 | 578 |
分片 3 | 20 | 2048 | 2068 | 7952 | 994 | 0 | 578 |
注意
分片后 IP 首部字段变化情况
所有分片中的 IP 数据报首部中的标识(ID,Identification)字段保持不变。
如果是最后一个分片,则 MF(More Fragment) 标识位为 0,否则 MF 标识位为 1。
片偏移(offset)字段以 8 字节为单位,其值为 分片实际偏移量 / 8
分片后应该满足的条件
总长度 = 首部长度(20B) + 数据长度 ≤ MTU
数据长度必须为 8 的整数倍,因为 offset 字段以 8 字节为单位。
分片经过第二个链路时也会根据 MTU 进行拆分,以分片 1 为例进行说明:
数据报 | 首部长度 | 数据长度 | 总长度 | 实际偏移量 | 片偏移字段 | MF 标志位 | ID 字段 |
---|---|---|---|---|---|---|---|
分片 1 | 20 | 3976 | 3996 | 0 | 0 | 1 | 578 |
分片 1.1 | 20 | 2480 | 2500 | 0 | 0 | 1 | 578 |
分片 1.2 | 20 | 1496 | 1516 | 2480 | 310 | 0 | 578 |
IP 组播
IP 组播(IP Multicast)是一种 IP 通信模式,允许一台发送器将数据报发送到多个接收器,而不是传统的单播(点对点通信)模式。组播是一种多对多的通信方式,非常适合用于广播、多媒体流传输和分布式应用中。
以下是 IP 组播的一些关键特点和概念:
- 组播组:IP 组播通信由一个或多个组播组组成,每个组都有一个唯一的组播组地址。组播组地址属于 IPv4 地址范围的特殊区域,通常以 224.0.0.0 到 239.255.255.255(D 类地址) 为范围。多个接收器可以订阅同一个组播组。
- 发送器:发送器是将数据报发送到组播组的设备。发送器只需发送一次数据报,然后由网络基础设施复制并传送给订阅了该组播组的接收器。
- 接收器:接收器是订阅了特定组播组的设备。它们希望接收组播组中的数据。接收器可以是单个主机、路由器或多个主机。
- IGMP(Internet Group Management Protocol):IGMP 是用于管理 IP 组播成员的协议。它允许主机通知路由器它们希望加入或离开特定的组播组。路由器使用 IGMP 来了解哪些主机希望接收特定组播组的数据。
- 组播路由:组播路由器是网络中的设备,负责将组播数据报从发送器传送到接收器。组播路由器根据 IGMP 报文和组播组地址表,将数据报仅传送到订阅了该组播组的网络分支。
- 组播范围:IP 组播地址可以分为不同的范围,如永久组播地址、临时组播地址和本地链路组播地址,以满足不同的需求和使用情况。
IPv6
特点
- 扩展的地址空间:IPv6 大幅扩展了 IP 地址空间,使用 128 位地址,相对于 IPv4 的 32 位地址,IPv6 提供了约 340 亿亿亿亿(3.4 x 10^38)个可能的地址,解决了 IPv4 地址枯竭的问题。
- 简化的报头:IPv6 报头相对于 IPv4 报头更简化,减少了路由器处理数据报的开销,提高了路由性能。
- 自动地址配置:IPv6 支持自动地址配置,其中设备可以通过 Router Advertisement 消息获取自己的 IPv6 地址,减少了手动配置的需要。
- 移动性支持:IPv6 内置了对移动 IP(Mobile IP)的支持,使移动设备能够无缝地切换网络而无需更改 IP 地址。
- 改进的安全性:IPv6 在设计上包括了对 IPsec(IP Security)的支持,这增加了网络通信的安全性和隐私保护。
- 多播和任播:IPv6 对多播和任播提供了更强大的支持,使网络更加高效。
- 简化的头部处理:IPv6 取消了 IPv4 中的首部校验和,减少了路由器在处理数据报时的负担。
- 更好的 QoS 支持:IPv6 提供了更多的选项和字段来支持服务质量(Quality of Service)
地址
IPv6 地址使用 128 位,通常以冒号分隔的 16 位十六进制数表示,例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334。
IPv6 地址分为以下几种类型:
- 单播地址(Unicast Address):用于将数据报从一个源节点传输到一个目标节点。
- 多播地址(Multicast Address):用于将数据报传输到一组目标节点,而不是单个节点。
- 任播地址(Anycast Address):用于将数据报传输到一组目标节点中的最近者(最接近的一个)。
- 回环地址(Loopback Address):用于将数据报返回到发送节点,通常表示为"::1"。
- 链路本地地址(Link-Local Address):用于在同一链路上的节点之间通信,通常自动配置,范围为 FE80::/10。
- 全局地址(Global Unicast Address):用于全球范围的通信,类似于 IPv4 的公有 IP 地址。
- 唯一本地地址(Unique Local Address):类似于 IPv4 的私有 IP 地址,用于组织内的通信。
- 专用地址(Special Addresses):用于特殊用途,例如文档中的示例地址、自动配置地址等。
移动 IP
移动 IP(Mobile IP)是一种网络协议,用于实现移动设备在不同网络之间切换时,仍能够保持连接并无缝通信。移动 IP 的主要目标是支持移动性,允许移动设备在移动时保持与互联网或企业网络的连接。
通信过程:
- 移动节点在家庭网络中连接,并分配了家庭网络的永久 IP 地址,建立了通信会话。
- 当移动节点决定移动到外部网络时,它会通知家庭网络的移动 IP 服务节点,告知其即将离开。
- 家庭网络的移动 IP 服务节点会分配一个临时 IP 地址,并记录移动节点的当前位置。
- 移动节点连接到外部网络,使用临时 IP 地址与外部网络中的其他设备通信。
- 当其他设备要与移动节点通信时,数据报被发送到移动节点的临时 IP 地址,然后到达外部网络。
- 外部网络的移动 IP 服务节点接收到数据报后,将数据报转发到移动节点的临时 IP 地址。
- 移动节点接收到数据报后,可以回复或继续与外部网络中的其他设备通信。
- 如果移动节点决定返回家庭网络,它可以通知外部网络的移动 IP 服务节点,并断开与外部网络的连接。
- 移动节点返回家庭网络后,通信会话继续,并且移动节点将继续使用家庭网络的永久 IP 地址。