互联网上最大的安全UDP数据包大小是多少?

245

我读了许多关于UDP数据包大小的文章,但无法得出正确结论。

许多服务限制最大的UDP数据包为512字节(如DNS)。

考虑到互联网上的最小MTU为576,IPv4头部大小为20字节,UDP头部大小为8字节。因此,还剩下548字节可用于用户数据。

如果不需要分片,我是否能够使用大小为548的数据包?或者是DNS创建者知道的某些问题,这就是为什么他们将其限制为512字节。

甚至可以安全地超过548字节吗?


2
重复,请参见https://dev59.com/yXNA5IYBdhLWcg3wmfAa - ChrisW
13
这是一个略微不同的问题。我正在问的是,在不了解其他网络或进行探测的情况下,我可以发送的最大数据包大小(不需要分段)。基本上是最大安全尺寸,适用于所有设备而无需担心连接的探测。 - K M
2
你无法消除碎片化的可能性,但这并不会使事情变得不安全。如果一个分片被丢弃,那么与UDP本身丢弃整个数据包是一样的。不安全的情况是数据包超过了路由器所需支持的最小大小,并因此不能保证可传递(而不是保证已传递)。这就是512字节的数字发挥作用的地方。 - Beejor
13个回答

160

IPv4标头通常为20个字节,UDP标头为8个字节,这是真实的。但是,可以包括IP选项,这可能会将IP标头的大小增加到60个字节。此外,有时需要中间节点将数据报封装在另一种协议中,例如IPsec(用于VPN等),以便将数据包路由到其目的地。因此,如果您不知道特定网络路径上的MTU,最好为可能未预期的其他标头信息留出合理的余地。512字节的UDP有效负载通常被认为可以做到这一点,但甚至这也不能为最大大小的IP标头留出足够空间。


47
只是为了明确:为了避免分段,拥有小的大小并不意味着数据包的传递是“安全”的,仍然存在无限的可能性使得传递变得不可靠,例如狗咬断了我的网络电缆。话虽如此;拥有较少的分段使传递更加“安全”,因为如果有多个分段中的任何一个没有到达目的地,UDP 就会丢弃整个数据包(数据报)。 - markmnl
6
为了提出问题,人们会假定使用海报上的“安全”定义,而不是一些他们从未见过的标准书中的定义。 - Astara
1
现实世界的路由器是否会放弃UDP数据包而不是对它们进行分片? - user253751

93
最大安全UDP负载为508字节。 这是一个576字节的数据包大小(“最小最大重组缓冲区大小”),减去最大60字节的IP头和8字节的UDP头。
任何这个大小或更小的UDP负载都可保证通过IP传送(尽管不能保证传送成功)。任何大于此的负载可能会因任何原因而被任何路由器直接删除,除非在仅支持IPv6的路由上,其最大负载为1212字节。正如其他人所提到的,在某些情况下可能会添加附加协议头。更为保守的值约为300-400字节可能更合适。 最大可能的UDP负载为67 KB,分成45个IP数据包,增加额外的900字节的开销(IPv4,MTU 1500,最小20字节的IP头)。 任何UDP数据包都可能被分段。但这不太重要,因为丢失一个片段与丢失未分段的数据包具有相同的效果:整个数据包都会被丢弃。对于UDP来说,这两种情况都可能发生。 IP数据包包括分段偏移字段,该字段指示UDP分段相对于其UDP数据包的字节偏移量。该字段是13位的,允许8192个值,并且以8字节为单位。因此,IP数据包可以引用的偏移范围为0...65528字节。作为偏移量,我们要为最后一个UDP片段添加1480个字节,得到67008。减去第一个分段中的UDP头,我们得到一个漂亮、圆满的67 KB。 来源:RFC 791、RFC 1122和RFC 2460。

3
默认情况下,任何 UDP 数据包都被认为是“不可靠”的。你只能期望接收到大小为 1 的未分片数据包才是安全的。如果你想要“安全”的数据包,请使用一个基于 TCP 的数据包协议。 - Astara
45
@Astara 是的,通过其本质,UDP是不可靠的。但问题在于一个特定大小的数据包是否有保证能够被传送到目的地,而不是保证一定会被送达。任何路由器都可能因为各种原因丢弃某些超过限定大小的数据包,而小一些的数据包则必须按照行业标准经过尽力处理后再发送。所以,在这里“安全”意味着“我的车能否通过桥下”,而不是“我的车会不会被堵在交通中”。 - Beejor
4
我建议停止重复一些随机人说的话并核实事实,因为UDP实际上相当可靠。顺便说一下,我在UDP之上有安全数据包,而无需TCP不必要的开销。 - Pablo Ariel
10
UDP并非因为丢包数量的问题而被称作“不可靠”,而是因为数据包有可能(并且确实)丢失。你不能“依赖”于任何特定的数据包到达、顺序或确认。数据很脆弱,这就像说99%能够工作,但只有89%朝着正确的方向行驶的汽车转向是可靠的一样。并不是说UDP在许多方面不好用,只是使用它需要你基本上编写自己的“TCP”版本。这里有一个有趣的现实案例可以看看(虽然有些过时):http://www.gamasutra.com/view/feature/131781 - Beejor
3
为什么你说“65,536是片段的最大数量”?IP数据包包括2字节长的“片段偏移”。这允许44个大小为1480字节的片段和一个最终大小为425字节的片段。 - Ali Tou
显示剩余8条评论

65
在Windows上,UDP数据包的最大理论大小限制为65507字节。这在此处有记录:documented here
正确的最大UDP消息大小是65507,由以下公式确定: 0xffff - (sizeof(IP Header) + sizeof(UDP Header)) = 65535-(20+8) = 65507
话虽如此,大多数协议限制更小的大小,通常为512或偶尔8192。如果您在可靠的网络上广播,通常可以安全地将其设置得更高548以上,但是如果您在互联网上进行广播,则越大越容易遇到数据包传输问题和数据丢失。

47
微软的链接不是规范参考。RFC文件是规范参考,而你引用的内容仅适用于IPv4。 - user207421
2
仅仅因为微软允许这样做,并不意味着它总是一个好主意,因为中间路由器等可能被迫分割更大的数据包大小(正如您所提到的)。 - rogerdpack
2
@EJP 在微软链接中他们没有清楚地解释,但这似乎是IPv4的必然结果:IPv4总长度字段为16位,该值必须包括IP头和UDP头的长度。 - jtpereyda
2
@ChristianStewart 最大的UDP数据包大小可以达到65507。如果您的路由器或网卡不支持这种大小,它将不得不在底层对数据包进行分片,以满足IPv4定义的最大数据包大小(即64kb减去IP和UDP头大小)。 https://zh.wikipedia.org/wiki/%E4%BD%BF%E7%94%A8%E8%80%85%E6%95%B0%E6%8D%AE%E5%8C%85%E5%8D%8F%E8%AE%AE - Pablo Ariel
2
“Reed Copsey” - 原帖并没有要求最大允许大小,而是他可以使用的最大大小,并且可以合理地期望不会发生碎片化。我没有理解他要求非碎片化的保证,只是一个他可以在算法中使用的粗略值。无论哪种方式,你都没有回答问题。 - Astara
显示剩余3条评论

50

576是“最小最大重组缓冲区大小”,即每个实现必须能够重组至少这个大小的数据包。详见IETF RFC 1122


2
只有在你的网络不支持IPv6时,才需要使用IPv6头的最大数据包大小减去封装头来进行IPv4 over IPv6。;-) - Astara
1
@Astara 在IPv6中,分段是由发送者完成的,因此不存在不良不符合中间路由器的问题。而且,如果接收方不是内存受限的嵌入式大小,那么它可能至少能够重新组装64kB的数据包。 - user253751
在哪些情况下,IPv6路由器允许分片数据报? - user253751
@user253751 我还没有太多的IPv6经验,但这里有一个例子:想象一下一个IPv6网络向另一个也支持巨型数据报的IPv6网络发送巨型数据报(>65536字节)。进一步假设路径MTU发现说这些巨型数据报应该在不分段的情况下得到支持。但是然后路由器被重新启动,网络路径的一部分被替换为未配置巨型数据报的设备。 - dstromberg
@dstromberg 那么路径的 MTU 已经改变,PMTUD 将学习新的较低 MTU。 - user253751
显示剩余2条评论

15
本文介绍了最大传输单元(MTU)http://en.wikipedia.org/wiki/Maximum_transmission_unit。它指出,IP主机必须能够处理576字节的IP数据包。然而,它还指出最小值为68。RFC 791:“每个互联网模块都必须能够转发一个68个八位组的数据报而无需进一步分片。这是因为互联网头可以长达60个八位组,而最小片段为8个八位组。” 因此,安全的数据包大小508 = 576-60(IP头)-8(udp头)是合理的。
如用户607811所提到的,其他网络层的分段必须重新组装。https://www.rfc-editor.org/rfc/rfc1122#page-56
3.3.2重新组装 IP层必须实现IP数据报的重组。 我们将EMTU_R(“接收有效MTU”)指定为可重组的最大数据报大小;有时称为“重组缓冲区大小”。 EMTU_R必须大于或等于576。

12

1
最低限度,当然。感谢您发现它。不知道为什么这个错误在这些年里没有被注意到。 - Nikolai Fetissov
1
虽然IPv6可能具有1500的最小重组缓冲区,但不允许对IPv6数据包进行分段,最小IPv6 MTU为1280。终端设备不应需要重新组装分段的IPv6数据包。 - Ron Maupin
1
@RonMaupin IPv6数据包可以由端点进行分段。但是中间的路由器不能进行分段。 - Navin
3
@Navin,不,IPv6数据包不会被分段,数据必须在打包成IPv6数据包之前进行分段,但数据包本身没有被分段。这是有区别的。与IPv4数据包头部具有处理分段的字段不同,IPv6数据包头部没有任何处理分段的内容。IPv6数据包头比IPv4数据包头简单得多。 - Ron Maupin
@RonMaupin 为什么最终用户不在IPv6中进行碎片整理?但我在书中读到源执行分段,目的地执行碎片整理? - Alok Maity

10
我在这里看到了一些不错的答案,但是有一些小错误。有些人回答说UDP头中的消息长度字段最大为65535(0xFFFF),这在技术上是正确的。还有一些人回答实际最大值为(65535-IPHL-UDPHL = 65507)。错误在于UDP头中的消息长度字段包括所有有效负载(第5-7层)以及UDP头的长度(8个字节)。这意味着,如果消息长度字段为200字节(0x00C8),则有效负载实际上为192字节(0x00C0)。
硬性规定的是IP数据报的最大大小为65535字节。这个数字是由L3和L4头部的总和加上第5-7层的有效负载得出的。IP头+UDP头+第5-7层=65535(最大值)。
最正确的答案是UDP数据报的最大大小为65515字节(0xFFEB),因为UDP数据报包括UDP头。UDP有效负载的最大大小是65507字节,因为UDP有效负载不包括UDP头。

1
你没有回答问题。提问者想知道他们可以使用的最大尺寸以避免数据包分片。 - Astara

8

512 是您最佳的选择。它在其他地方也被使用,并且是一个漂亮的偶数(1024 的一半)。


7
考虑到IPv6的大小为1500,我认为运营商不会为IPv4和IPv6提供单独的路径(它们都是具有不同类型的IP),这将迫使他们使用旧的、冗余的、维护成本更高且不太可靠的ipv4设备。这没有任何意义。此外,这样做很容易被视为为某些流量提供优惠待遇——在他们可能并不关心的规则下是不允许的(除非他们被抓住)。
因此,1472应该是外部使用的安全值(尽管这并不意味着像DNS这样不知道EDNS的应用程序会接受它),如果您谈论内部网络,则可以更有可能了解您的网络布局,在这种情况下,巨型数据包大小适用于未分段的数据包,因此对于4096-4068字节,对于英特尔卡带有9014字节缓冲区的包大小,最大值为...等等...8086字节,将是最大值...巧合吗?咯咯地笑。
****更新****
各种答案给出了1个软件供应商允许的最大值或者假定封装的各种答案。用户没有要求最低值(例如安全UDP大小为“0”),而是最大安全数据包大小。
封装值可以多次包含在各个层中。因为一旦你封装了一个流——没有什么能阻止,比如说,在下面有一个VPN层,在上面完全重复封装层。
由于问题是关于最大安全值的,我假设他们谈论的是可以接收的UDP数据包的最大安全值。由于没有任何UDP数据包是保证的,如果您接收到一个UDP数据包,则最大的安全大小将是IPv4或1472字节的1个数据包。
请注意——如果您使用IPv6,则最大大小将为1452字节,因为IPv6的头大小为40字节,而IPv4的头大小为20字节(无论哪种方式,仍必须允许8字节的UDP头)。

1
你是如何计算1472的?以太网的MTU为1500,这是你所指的吗? - rogerdpack
4
我认为他的意思是因为IPv4和IPv6很可能共享大量基础设施,并且IPv6变得相对流行,所以可以安全地假设IPv6限制(因此为1500)。然而,我无法确定这种推理的有效性。 - Thomas
2
网络“链”中的组件必须支持IPv6,以支持1500字节的数据 -- 如果使用IPv4,在IPv6支持的链路上传输(反之不成立),那么由于IPv4的头部大小为20字节,UDP的头部大小为8字节,这将使最大安全值为1500-20-8=1472(因为IPv6不允许分段)。请注意--如果人们添加足够多的封装层,则可能没有空间用于数据。由于您要求最大值,因此将假定未使用多层封装开销。 - Astara
“网络链中的组件必须支持IPv6兼容性,最小IPv6 MTU为1280。以太网MTU为1500。” - Ron Maupin
IPv6没有分段。IPv6使用PMTUD来发现路径中最小的MTU,该MTU必须至少为1280字节。IPv6没有像IPv4那样的数据包分段和重组功能。你的陈述意味着链中的任何IPv6组件都必须支持1500字节是不正确的。在IPv6路径中,任何或所有节点支持1280字节的数据包作为最大数据包大小是完全可以接受的。 - Ron Maupin
显示剩余4条评论

2
“没有。”
“我要完全放弃任何 'UDP 是尽力而为' 的理由,并且只关注 '最大安全 UDP 数据包大小',它被认为是 '足够小,绝对避免沿途的任何分段'。”
“对于重要的背景:”
“你能依赖的唯一数据包大小是 24 字节(IPv4)和 56 字节(IPv6),因为片段的最小 IP 标头为 20/48 字节(v4/v6),并且片段必须有至少 4/8 字节(v4/v6)有效载荷数据。 因此,在 IP 层以下的传输系统如果不能传输这些大小的数据包,则无法用于传输 IP 流量 [总体]。”- 答案是如何将 MTU 设置为 65507 的 UDP…?。”
根据上面的答案,这是因为在那个长度下,IP 分段机制无法运行 - 它只能生成一个片段。
IP标准要求每个IP主机能够接收总大小为576字节的IP数据包。然而,需要注意的是,标准并没有说不允许分段,因此即使是一个576字节的IP数据包,在源和目的地之间的某个位置也可能被分段。

因此,任何大于互联网协议最小限制的数据包都有可能因为在传输途中“隐形”地被临时封装到略高于极限的大小而被分段,即使您选择了最小的UDP负载,其大小将为:576-8(UDP头)-20(IPv4)或40(IPv6)=最小528(如果您不确定使用的是v4还是v6)。

避免分段的原因之一是它会增加整个数据包完全丢失的可能性。更多的数据包,仅仅由于更高的开销,就意味着更大的失败可能性,更不用说每个数据包(甚至是一个分段)都代表着另一个“丢失”的机会。当然,如果该数据包恰好被传递到某个因为过大而丢弃它的链路上...

操作系统层面的TCP实现会尝试在TCP层面内选择最高安全MTU,包括动态处理其有时候的变化,因为源和目的地之间的路径的某些部分可能会逐个数据包不同。
对于UDP来说,这整个问题也成为你的问题:而且并不简单,只是“使用最大的肯定不会分段的值”。
RFC2460第5节有关IPv6的最小MTU如下所述:
IPv6要求互联网中的每个链接都具有1280个八位字节或更大的MTU。在任何无法一次传送1280个八位字节的链路上,必须在IPv6以下的层提供特定于链接的分段和重组。
因此,分段也可以发生在IP层以下,在路径中的两个主机之间的特定链接处决定将其分段,然后可能将片段推入并行管道中...在该链接的另一端重新组装成一个数据包。
如果这些数据片段的顺序错乱了,重新排序机制可能会错误地重新组装数据包,甚至没有意识到它重新排列了其中的一部分。当然,如果硬件遵循IP规范,它应该能够通过检查IP头中的片段偏移量部分来注意到数据包的顺序已经错乱,但大多数链路协议只是按接收顺序重新组装数据片段,而不关心乱序的数据包接收。现在,如果这个“低级别”的互连本身被用作网络……比如在一个大型交换机的核心中,那么在重负载和许多并行路径下,这些数据片段在重新组装之前可能会出现乱序。这非常恶劣,但可能有时会发生,导致偶尔仍然传送但严重损坏的数据包,而这些数据包仍然可以通过基于异或的简单校验和测试通过......这恰好就是IP校验和所使用的方法。TCP只设置“不分段”并处理它,但UDP则将该位保留为空白......因此,如果您正在使用UDP,则还应该假设您的字节流有时可能会在数据包内部重新排序......因此,您应该使用一种校验方法来验证您的数据,以便捕获重新排序。
大多数链接的 MTU 都会达到 1500,但链路层具有不同的最小和最大数据报大小:
  • Ethernet:64 到 1500(或更高的 MTU 能力)
  • ATM:每个数据报仅限 53 字节
  • Frame Relay:46 到 4470 字节 (参考:IP fragmentation is broken

不幸的是,UDP 头本身就占用了 8 个字节……这意味着,唯一可以 确定地 避免分段的 UDP 数据负载大小是零!(并且只能适合于最小可能的 IPv6 数据包)。

最好 / 合理的做法可能是为您的 UDP 数据报使用 512,并自己检查数据是否在数据报内按顺序传输以及处理到达顺序错误的数据包。(即,不要完全依赖 IP 来为您删除损坏的数据包)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接