目录 ← 首页
CS168

IP 头部

IP 头部设计目标

回想一下,像 IP 这样的协议由语法和语义组成。语法决定了 IP 头部包含哪些字段,而语义决定了这些字段如何被处理。

此外,IP 数据包由头部和有效载荷组成。头部包含 IP 协议可处理的相关元数据。有效载荷包含将被传递到更高层协议的任何数据,且不会被 IP 协议解析。

最后,回想一下,当数据在协议栈中向下传递时会添加头部,而当数据包向上传递时会剥离头部。IP 头部会在终端主机和每个中间路由器上被处理。

IP 头部应尽可能小。每个在互联网上发送的数据包都需要附加 IP 头部,因此即使 IP 头部大小增加 1 字节,也会显著增加互联网的总带宽消耗。

IP 头部应尽可能简单。每个路由器和终端主机在发送和接收 IP 数据包时都必须处理它们,因此难以处理的头部会拖慢整个互联网。理想情况下,我们希望头部能纯硬件处理,因此在处理该头部时,不能假设我们可以使用通用 CPU 操作。

IP 头部字段

IP 协议需要完成四件事:

所有设备(终端主机、路由器)都需要能够解析数据包并理解这些比特的含义。为支持这一点,头部将包含IP 版本(4 位值)、头部长度(4 位值,以 4 字节为单位,因为 IP 头部长度不固定)和数据包长度(16 位值,以字节为单位)。

路由器(而非终端主机)需要将数据包转发到下一个路由器。为支持这一点,头部将包含目的 IP 地址(32 位值)。

终端主机(而非路由器)需要将数据包向上传递到更高层。为支持这一点,头部将包含协议号(8 位值),它告诉我们应该使用哪个第四层协议(TCP 或 UDP)来处理有效载荷。例如,协议号 6 表示使用 TCP 协议读取剩余的有效载荷(将有效载荷的前几位作为 TCP 头部,依此类推)。协议号 17 对应 UDP 协议。

img

终端主机和路由器需要能够向源端发送回复。为支持这一点,头部将包含源 IP 地址(32 位值)。

IP 错误处理

终端主机和路由器还需要能够在数据包需要额外处理时指明问题或特殊情况

IP 数据包可能会陷入循环(例如,如果路由协议尚未收敛)。一种可能的选择是让数据包无限循环,直到路由收敛,但数据包转发是以纳秒级进行的,而路由收敛是以毫秒或秒级进行的。让数据包循环到路由收敛可能需要很长时间,并浪费大量带宽。为防止无限循环,IP 头部有一个生存时间(TTL)(8 位值),每经过一跳就会递减。如果 TTL 达到 0,数据包将被丢弃,并向源端发送错误消息。(IP 规范要求发送错误消息,但实际上并不总是发送。)

IP 数据包可能会损坏(例如,线路上的比特可能因电气过程而损坏)。为检测损坏,IP 头部包含一个校验和(16 位值),如果校验和不正确,数据包将被丢弃。

请注意,IP 校验和仅对 IP 头部计算。校验和只能检测 IP 头部中的错误,而不能检测 IP 有效载荷中的错误。这体现了端到端原则,即我们要求有效载荷由终端主机检查,而非中间路由器。

每个路由器都会更新 IP 校验和,因为 TTL 会变化,所以必须重新计算校验和。一种可能的替代设计是在校验和中排除 TTL,以节省路由器的额外工作。

IP 数据包可能对于特定链路来说太大。每条链路都有一个最大传输单元(MTU),表示该链路可以作为一个单元承载的最大数据包大小(以字节为单位)。例如,链路可能在沿线路发送比特时,用于记住数据包的内存有限。

终端主机不知道数据包将通过哪些链路传输,因此终端主机可能发送对于其中一条链路来说太大的数据包。为解决此问题,路由器可以执行分片,将数据包分割成多个片段,链路另一端的路由器必须重组这些片段以恢复原始数据包。头部中的标识(16 位)、标志(3 位)和偏移量(13 位)字段用于实现分片。

img

分片可以通过硬件实现(例如,路由器可以快速分片数据包,而无需将数据包移交进行特殊处理),但会引入额外开销。现代互联网尽可能避免分片。例如,我们尝试使 MTU 标准化(现代标准是 1500 字节)。

IP 的早期设计者并未完全接受尽力而为的设计,他们认为允许应用程序根据自身需求发送不同类型的数据包可能是有用的。为实现这一点,IP 头部有服务类型(ToS) 位(8 位值),可用于请求不同形式的数据包交付。例如,某些数据包可以标记为对延迟敏感或高优先级。多年来,这些位已被重新定义以表示不同的协议,ToS 不再以其原始形式存在。相反,这些位现在表示某种优先级概念。使用这些位的协议示例包括区分服务代码点(DSCP)(定义某些流量类别)和显式拥塞通知(ECN)(将有助于解决流量拥塞,稍后讨论)。

在原始 IP 设计中,可以在 IP 头部添加额外的选项位,以请求对数据包进行更高级的处理。例如,发送方可以请求路由器记录数据包所经过的路由(例如,用于诊断)。发送方可以在数据包头中包含源路由,并强制数据包沿特定路由传输。数据包头还可以包含时间戳。在现代实现中,这些选项几乎总是禁用的,因为它们会导致不必要的复杂实现,增加数据包处理开销。例如,这些选项迫使 IP 头部成为可变长度,这比固定长度头部更难处理。

img

IPv6 头部变化

IPv6 的出现是因为担心我们最终会耗尽 32 位 IPv4 地址。IPv6扩展了地址,使地址长度为 128 位。可能的 IPv6 地址数量极其庞大(想想:宇宙中的原子数量),因此我们几乎肯定永远不会耗尽 IPv6 地址。

IPv6 的设计者借此机会清理和现代化 IP 头部,移除和更新过时的字段。最初,IPv6 旨在成为一个更具雄心的协议,具有许多新的寻址功能,但这些功能中的大多数从未实现。实际上,除了这种 “大扫除” 式地移除过时功能外,与 IPv4 相比,该协议没有太多重大变化,因此结果是一个更简洁的 IP 协议,没有太多雄心勃勃的改变。

注意:如果你好奇的话,IPv5 于 1990 年发布(早于 1998 年的 IPv6)。它是一个实验性协议,从未被广泛实现。

IPv6取消了 IP 数据包头中的校验和。支持包含校验和的论点是:如果数据包损坏且未被检测到,损坏的数据包会继续发送,浪费带宽。包含校验和可确保数据包被丢弃,不会在损坏的数据包上浪费带宽。在现代,带宽不再是瓶颈,因此校验和不再必要,即使一些损坏的数据包被发送到整个网络,对性能的影响也不大。

IPv6取消了分片。如果 IPv6 数据包对于特定链路来说太大,路由器会丢弃该数据包,并向源端发送包含最大允许数据包大小(MTU)的错误消息。原始发送方负责将数据拆分为更小的数据包,并重新发送这些更小的数据包。终端主机(例如你的个人计算机)处理的数据包比路由器(例如数据中心的路由器)少,因此将分片工作从路由器转移到终端主机可提高互联网的整体可扩展性。

IPv6 用协议字段的修改实现取代了可变长度的选项部分。在 IPv4 中,选项是有问题的,因为它们创建了可变长度的头部,更难解析。在 IPv6 中,头部长度是固定的。这也意味着可以取消头部长度字段。

为了继续支持选项,IPv6 将协议字段泛化,允许 IP 数据包在到达第四层之前被传递上去进行特殊处理。(回想一下,IPv4 中的协议头部设置为 7 或 19,以指示下一个处理数据包的第四层协议。)在 IPv6 中,该字段从 “协议” 重命名为 **“下一个头部”**。

img

如果你希望有额外的协议来处理 IP 数据包,你可以将该协议对应的编号放入 “下一个头部” 字段中。这些额外协议的设计者和用户需要就哪些编号对应哪些协议达成一致,并且需要一个标准组织来管理这些编号。然后,有效载荷可以传递给该额外协议,该协议可以读取一个额外的头部(在第三层 IPv6 头部之后,但在第四层头部之前)并执行额外处理,然后将剩余的有效载荷传递给第四层。

如果数据包没有额外的选项,那么 “下一个头部” 字段与旧的 “协议” 字段相同,允许 IP 数据包直接传递到第四层协议,无需进一步处理。

“下一个头部” 的概念可以泛化,允许多个协议在 IPv6 之后、第四层之前处理数据包。例如,IPv6 可以有一个用于特殊处理的 “下一个头部”。然后,特殊处理协议的头部也可以包含一个 “下一个头部” 字段,该字段要么指定一个第四层协议,要么指定另一个特殊处理协议。这种方法具有前瞻性,因为它支持尚未发明的未来协议。这些未来协议可以通过这种 “下一个头部” 方法添加,而不会破坏 IPv6 或需要更新 IPv6。

IPv6 在头部添加了一个流标签字段。在第三层,数据包是独立发送的(一个数据包的发送方式不影响其他数据包),但实际上,许多数据包通常以某种方式相关联。例如,在两个主机之间的视频流中,可能有许多数据包在相同的两个应用程序之间发送。第三层应该分别处理这些数据包,但实际上,路由器添加了更先进的系统,称为中间盒(例如防火墙、入侵检测系统),它们可能关心这些数据包是否属于同一流或连接。例如,防火墙可能需要读取一个连接中的多个数据包,以决定是否允许该连接。当所有数据包都独立发送时,这些中间盒必须猜测两个数据包是否相关(例如,它注意到具有相同源 / 目的 IP 地址的数据包)。IPv6 添加了一种明确的方式来表示多个数据包是相关的。

img

IPv4 和 IPv6 之间的版本号没有变化。数据包长度不变(尽管从 “总长度” 重命名为 “有效载荷长度”)。TTL 重命名为 “跳数限制”,但功能不变。

“服务类型” 位重命名为 “流量类别”,仍然可以用于实现某种数据包优先级概念。

总的来说,IPv6 遵循端到端原则,并在可能的情况下要求终端主机完成工作(分片、验证校验和并重新发送损坏的数据包)。有些字段,如跳数限制或 TTL,本质上是 IP 级别的问题,无法由终端主机实现。(终端主机如何帮助解决在网络中循环的数据包呢?)

IPv6 还试图简化头部(移除可变长度选项),同时仍允许未来改进的可扩展性(“下一个头部” 方法、流标签)。

IP 头部安全性

IP 没有任何内置的针对攻击者的安全性。攻击者可以发送源 IP 地址不正确的数据包,从而冒充他人。这可能导致被冒充的主机被错误地归咎于某个数据包。或者,如果攻击者发送伪造的数据包,回复可能会发送到被冒充的主机。谎报源地址被称为IP 欺骗

IP 欺骗可用于 denial-of-service(DoS,拒绝服务)攻击。DoS 攻击可通过向服务器发送大量数据包使其过载并崩溃。如果所有数据包都来自同一个发送者,服务器可以通过忽略来自攻击者 IP 地址的数据包来阻止攻击。然而,如果攻击者谎报源 IP 地址,服务器就更难区分攻击流量和合法流量。

存在更复杂的涉及欺骗的攻击,不过本课程不会详细介绍(更多细节参见加州大学伯克利分校 CS 161 的笔记)。

IP 头部中的 ToS 字段允许发送者为其数据包设置优先级。如果我们允许每个人都设置自己的优先级,恶意用户可以设置更高的优先级,并欺骗网络优先处理攻击流量。

如果网络对高优先级流量收取额外费用,攻击者可以发送伪造的高优先级数据包,而被冒充的主机将不得不为攻击者的流量付费。

原始的互联网设计并未阻止这些攻击,尽管现代 ISP(互联网服务提供商)已经实施了额外的安全措施来缓解 IP 层攻击。在现代互联网中,ISP 不允许终端主机设置 ToS 字段,并且许多 ISP 都有检测和阻止伪造数据包的工具。

在 IPv4 中,攻击者可以故意发送大型数据包,迫使路由器做额外的分片工作。或者,攻击者可以故意添加额外选项,迫使路由器处理这些额外选项。这可能被用于执行 DoS 攻击, overwhelm 路由器的处理能力。

TTL 字段可被利用来了解网络拓扑。你可以发送一个 TTL 为 1 的数据包。该数据包将在第一跳过期,第一台路由器会向你发送错误消息,使你能够了解第一台路由器的身份。

img

然后,你可以发送一个 TTL 为 2 的数据包,它将在第二跳过期。第二台路由器会向你发送错误消息,使你也能发现第二台路由器。

img

通过用 TTL 3、TTL 4 等重复此操作,你可以发现路径上的所有路由器。这种攻击被称为traceroute(跟踪路由),尽管其他人认为这不是攻击,而是有用的诊断工具。

img

对不同的源和目的地重复此攻击,可以让你了解更多的网络拓扑。有些路由器在 TTL 过期时不发送错误消息,这可能会限制这种利用。

攻击者理论上可以篡改协议或校验和字段,但这可能会导致数据包因协议无效或校验和错误而被丢弃,因此利用这两个字段的实际攻击并不存在。

img

(注:文档部分内容可能由 AI 生成)