![源是否可以同时发送两个分片的 IP 数据包?](https://linux22.com/image/624696/%E6%BA%90%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%97%B6%E5%8F%91%E9%80%81%E4%B8%A4%E4%B8%AA%E5%88%86%E7%89%87%E7%9A%84%20IP%20%E6%95%B0%E6%8D%AE%E5%8C%85%EF%BC%9F.png)
我正在开发一个在虚拟 TAP 接口和物理接口之间进行 NAT 的应用程序,我不确定应该为 IP 碎片分配多少缓冲区。
根据 Wikipedia,“片段偏移”的最大值限制为 8189,但源端是否有可能同时发送 2 个或更多碎片数据包?或者它会按顺序发送它们(即,在完成第一个碎片数据包之前不会发送另一个碎片数据包)?
答案1
片段偏移量
片段偏移量是一个 13 位字段,如果将这些位解释为无符号整数,则最大值为 8191。但实际上它是计算 8 字节的倍数,因此说值以 8 为步长从 0 到 65528 是有意义的。
此字段本身的最大有效值到底是多少并不特别重要。重要的是偏移量和长度字段之和的最大值。如果该和太大,则数据包无效。即使每个字段单独都在有效范围内,它们的总和仍可能超过有效值。在接收时未能验证总和可能会导致安全漏洞。
利用这一特定安全漏洞的数据包被称为“死亡 ping”。这有点误导,因为它与 ping 毫无关系,并导致人们普遍误以为 ping 数据包很危险。
以上所有内容都与您的问题中提到的片段偏移有关,但与您的实际问题无关。
IP ID 字段
您问的是源是否可以同时发送两个碎片数据包。根据标准,在发送方处交错两个碎片数据包当然是可以接受的。但这样做很少有意义。但是不能对此做出任何假设。
如果涉及 NAT,则从具有不同 IP 地址的两个不同主机发送的两个数据包在到达目的地后可能会具有相同的源 IP。一旦来自两个不同来源的片段流相遇,它们可能会交错。
即使没有涉及这样的 NAT,数据包仍然可能被网络重新排序(例如,如果它们通过不同的路径路由)。因此,由于多种原因,它们一旦到达目的地,最终就会被交错。
为了确保接收方能够正确地重组数据包,标头中有一个 IP ID 字段(在 IPv4 上为 16 位,在 IPv6 上为 32 位)。为了重组,接收方必须考虑源 IP、目标 IP 和 IP ID。原则上,这足以重组在传输过程中交错的有效载荷。
不幸的是,在 NAT 的情况下,事情就没那么简单了。两个具有不同 IP 的不同主机同时发送具有相同 IP ID 的数据包是有效的。(这显然是允许的,因为双方都不知道对方发送了什么数据包)。但是,如果数据包的源 IP 被 NAT 更改,以至于它们现在具有相同的源 IP,那么它们可能不再可区分。
在 NAT 中纠正这个问题并不现实。因此 NAT 通常会忽略它并希望一切顺利。这意味着通过 NAT 发送的碎片数据包可能会被错误地重组,并可能将数据从一个连接泄漏到另一个连接。
由于 IP ID 字段较大,因此 IPv6 的风险显著降低。此外,由于 IPv6 不使用 NAT(除非您喜欢调试 NAT 引入的问题),因此风险也较小。