RFC8085 UDP使用指南

RFC8085 UDP使用指南

RFC 8085: UDP Usage Guidelines

摘要

UDPUser Datagram Protocol)提供了最小的基于消息的传输,没有固有的拥塞控制机制。本文为应用程序、隧道和其他使用UDP的协议的设计者提供了UDP的使用指南。拥塞控制指南是一个主要焦点,但本文也提供了其他主题的指导,包括消息大小、可靠性、校验、中间件穿越、使用显式拥塞通知(ECN)、差异化服务码点(DSCP)和端口。

由于拥塞控制对互联网的稳定运行至关重要,选择使用UDP作为互联网传输的应用程序和其他协议必须采用机制来防止拥塞崩溃,并与并发流量建立某种程度的公平。他们可能还需要实现额外的机制,这取决于他们如何使用UDP

一些指南也适用于其他协议的设计(例如,直接分层在IP上或通过基于IP的隧道的协议),特别是当这些协议本身不提供拥塞控制时。

本文废除了RFC 5405,并增加了组播UDP使用指南。

1、介绍

UDP[RFC768]为希望在IP上运行的应用程序和其他协议(如隧道)提供了一个最小的、不可靠的、尽力的、基于消息的传输。在本文其余部分,两者都被简单地称为"应用程序"

与其他传输协议相比,UDP及其UDP-Lite变体[RFC3828]是独特的,因为它们不在通信的终端系统之间建立端到端连接。因此,UDP通信不会产生连接建立和拆除的开销,而且相关的终端系统状态最小。由于这些特点,UDP可以为一些应用提供非常高效的通信传输。

UDP的第二个独特特点是它没有提供固有的拥塞控制机制。在许多平台上,应用程序可以以平台链路接口的线路速率发送UDP数据报,这往往远远大于可用的端到端路径容量,这样做会造成路径的拥堵。[RFC2914]描述了当前互联网中拥塞控制的最佳实践。它指出了拥塞控制机制对互联网的稳定运行至关重要的两个主要原因:

1)防止拥塞崩溃,如网络负荷的增加导致网络所做的有用工作减少的状态。

2)建立一定程度的公平性,即允许多个流量合理公平地分享路径的容量。

因为UDP本身没有提供拥塞控制机制,所以要由使用UDP进行互联网通信的应用来采用合适的机制来防止拥堵崩溃并建立一定程度的公平性。[RFC2309]讨论了拥塞无反应流的危险,并指出"所有基于UDP的流媒体应用都应纳入有效的拥塞避免机制"[RFC7567]重申了这一声明。这是一个重要的要求,即使对于不使用UDP进行流媒体的应用也是如此。此外,拥塞控制的传输对应用本身也有好处,因为它可以减少自我引起的数据包丢失,尽量减少重传,从而减少延迟。即使在相对较慢的传输速率下,拥塞控制也是必不可少的。例如,一个应用程序在一秒钟内产生51500字节的UDP数据报,已经超过了56Kb/s路径的容量。对于那些可以在更高的、可能无限制的数据速率下运行的应用,拥塞控制对于防止拥塞崩溃和建立某种程度的公平性变得至关重要。第3节为这类应用的设计者描述了一些简单的指导。

一个UDP数据报是在一个IP包中承载的,因此,对于IPv4来说,它的最大有效载荷是65,507字节,对于IPv6来说,是65,527字节。大的IP数据包的传输通常需要IP分片。分片会降低通信的可靠性和效率,应该避免。当沿路的所有链路层都支持时,IPv6允许选择在没有分片的情况下传输大数据包("jumbograms"[RFC2675]。第3节中的一些指导描述了应用程序应如何确定适当的消息大小。本文的其他部分提供了关于可靠性、校验、中间件穿越和使用组播的指导。

本文提供了指导和建议。尽管大多数UDP应用被期望遵循这些指导,但确实存在特定应用决定不遵循特定指导的合理理由。在这种情况下,建议应用设计者在他们的应用或协议的技术规范中引用本文的相关部分,并解释他们的设计选择的理由。

[RFC5405]的范围是只为单播应用提供指导,而本文也为使用IP任播、多播、广播的UDP流以及使用UDP隧道支持IP流的应用提供指导。

最后,尽管本文特别提到了UDP的使用,但其一些指导的精神也适用于其他消息传递的应用和协议(特别是在拥塞控制、消息大小和可靠性方面)。例如,选择通过向IANA注册自己的IP协议号直接在IP上运行的信令、隧道或控制应用。本文预计将为此类应用和协议的设计者提供有用的背景阅读。

3. UDP使用指导

互联网路径可以有广泛不同的特性,包括传输延迟、可用带宽、拥塞水平、重排概率、支持的消息大小或丢包率。此外,同一互联网路径在不同时期可能有非常不同的条件。因此,可能在互联网上使用的应用程序决不能对特定的路径特征进行假设。它们必须使用机制在非常不同的路径条件下安全运行。通常情况下,这需要保守地探测对应互联网路径的当前条件,以建立一个可以维持的传输行为,并且对共享路径的其他流量是合理公平的。

这些机制很难正确实现。对于大多数应用,使用现有的IETF传输协议之一是获得所需机制的最简单方法。这样做还可以避免使用新的IP协议号的协议在互联网上部署时面临的问题,因为互联网上有时会出现只支持TCPUDP的中间件。因此,本节其余部分描述的UDP使用的推荐替代方案是使用IETF传输协议,如TCP[RFC793]SCTP[RFC4960]。和SCTP部分可靠性扩展(SCTP-PR[RFC3758],或数据报拥塞控制协议(DCCP[RFC4340]及其不同的拥塞控制类型[RFC4341][RFC4342][RFC5622],或IETF未来指定的传输协议。(UDP封装的SCTP[RFC6951]DCCP[RFC6773]可以为穿越防火墙和其他不支持本地协议的中间件提供支持。)

如果使用得当,这些功能更全面的传输协议并不像通常所说的那样"重量级"。例如,几十年来,TCP算法一直在不断改进,效率和正确性已经达到了自定义应用层机制难以轻易复制的水平。此外,许多TCP实现允许连接由应用程序根据其目的进行调整。例如,TCPNagle算法[RFC1122]可以被禁用,以更频繁的--但仍然是拥塞控制的--数据包传输为代价,改善通信延迟。另一个例子是TCP SYN cookie机制[RFC4987],它在许多平台上都可用。带有SYN cookieTCP不要求服务器在连接建立之前维持每个连接的状态。TCP还要求关闭连接的一端保持TIME-WAIT状态,以防止一个连接实例的延迟段干扰到后面的连接实例。意识到这一行为并为之设计的应用程序可以通过控制哪一端关闭TCP连接来改变对TIME-WAIT状态的维护,以节约资源[FABER]。最后,TCP内置的容量检测和对路径支持的最大传输单元(PMTU)的认识支持了高效的数据传输,在交换超过几个段的传输情况下,可以快速补偿初始连接设置延迟。

3.1. 拥塞控制指导

如果应用程序或协议选择不使用拥塞控制的传输协议,就应该控制向目的主机发送UDP数据报的速率,以满足[RFC2914]的要求。需要强调的是,一个应用程序应该对其发送到目的地的所有UDP流量进行拥塞控制,这与它如何产生该流量无关。例如,一个fork多个工作进程或使用多个套接字来生成UDP数据报的应用程序,应该对总流量进行拥塞控制。

本节的其余部分将讨论执行拥塞控制的几种方法。本节描述了通用的主题,重点是单播和任播[RFC1546]的使用。并不是下面讨论的所有方法都适用于所有UDP传输的应用。3.1.2讨论了通过UDP进行批量传输的应用的拥塞控制选项。这类应用可以采用一些方案,在随后的几次往返中对路径进行采样,在交换数据的过程中确定路径在当前负载下可以支持的发送速率。其他应用程序只与目的地交换几个UDP数据报。3.1.3讨论了这种"low data-volume"应用的拥塞控制选项。因为它们通常不会传输足够的数据来反复采样路径以确定安全的发送速率,需要采用不同的拥塞控制机制。3.1.11讨论了UDP作为隧道协议使用时的拥塞控制考虑。第4节提供了关于广播和多播使用的额外建议。

需要注意的是,拥塞控制不应该被看作是一个已完成的应用程序的附加物。下面的指导中讨论的许多机制都需要应用的支持才能正常运行。应用设计者需要在整个应用的设计过程中考虑拥塞控制,就像他们在整个设计过程中考虑安全方面一样。

在过去,IETF还研究了综合拥塞控制机制,该机制作用于两个主机之间的流量集合,即一个框架,如拥塞管理器[RFC3124],其中活动会话可以以独立于传输协议的方式共享当前的拥塞信息。这样的机制目前还没有得到部署,但以其他方式简化了UDP会话的拥塞控制机制的设计,使其满足[RFC2914]的要求。

3.1.1. 协议定时器指导

了解通信端点之间的延迟通常是协议和应用的有效拥塞控制实现的一个关键部分。延迟估计可用于一些协议功能,如计算拥塞控制的传输速率、触发重传和检测丢包。其他协议功能,例如,确定探测路径的时间间隔,确定keep-alive消息的时间间隔,确定测量体验质量的时间间隔,或确定远程端点是否响应了请求,通常比拥塞控制的时间尺度更长,因此本节不涉及。

本文的一般建议是,应用程序应该利用现有的拥塞控制技术和其中规定的延迟估计器(见下一小节)。下面的指导是为需要设计自己的延迟估计机制的应用提供的。

该指导以"延迟"而不是"往返时间"为框架,因为有些情况只需要描述基于网络的延迟(例如TCP友好速率控制(TFRC[RFC5348]),而其他情况需要包括远端提供反馈所需的时间(例如对何时重传消息的理解)。

端点之间的延迟通常是一个动态属性。因此,估计值应该代表最近多个测量样本的某种平均数,以考虑到差异性。利用指数加权移动平均(EWMA)已被证明对这一目的有用(例如,在TCP [RFC6298]TFRC [RFC5348])。

应该为端点与之通信的每个目的地维护独立的延迟估计。

延迟样本决不能从含糊不清的事务中得出。典型的例子是在一个重传数据的协议中,但随后不能确定哪个副本被确认。这种模糊性使得延迟的正确计算成为问题。见[RFC6298]中关于Karn算法的讨论。这一要求确保发送方建立一个合理的延迟估计,而不依赖误导性的测量。

当延迟估计被用来启动提供丢包检测的定时器时--无论是否有重传--定时器的过期必须被解释为网络拥塞的迹象,导致发送速率被调整为安全的保守速率(例如,TCP将拥塞窗口折叠为一个段[RFC5681])。

有些应用需要在端点之间的延迟被经验性采样之前有一个初始延迟估计。例如,在启动重传定时器时,需要一个初始值来保护端点采样延迟前发送的消息。对于给定的应用,这个初始延迟估计值一般应尽可能保守(大)。例如,在没有任何关于路径延迟的知识的情况下,TCP要求初始重传超时(RTO)设置为不低于1[RFC6298]UDP应用也应同样使用1秒的初始延迟估计。短于1秒的值可能有问题(见[RFC6298]附录中的数据分析)。

3.1.2. 批量传输应用(Bulk-Transfer)

通过UDP向对端进行数据批量传输的应用,即每个RTT交换超过几个UDP数据报的应用,应该实施TFRC [RFC5348]、基于窗口的TCP类拥塞控制,或者以其他方式确保应用符合拥塞控制原则。

TFRC旨在以与IETF的其他传输协议兼容的方式提供拥塞控制和公平性。如果应用程序实现了TFRC,则无需遵循3.1.2中的其余指导,因为TFRC已经解决了这些问题,但仍应遵循第3节后续小节中的其余指导。

选择不实施TFRC或类似TCP的窗口化的大容量传输应用程序应实施拥塞控制方案,该方案将导致带宽(容量)使用在一个数量级内与TCP公平竞争。

[RFC3551]2节建议应用程序应监控丢包率,以确保其在可接受的参数范围内。如果在相同的网络条件下,通过相同网络路径的TCP流在合理的时间尺度上达到不低于UDP流的平均吞吐量,则认为丢包是可接受的。无法精确指定与TCP的比较,但其目的是在时间尺度和吞吐量方面进行数量级比较。3.1.1中规定的计时器管理建议也适用。

最后,一些批量传输应用程序可能选择不实施任何拥塞控制机制,而是依赖于通过保留路径容量进行传输(见3.1.9)。对于受限网络环境的子集来说,这可能是一个可接受的选择,但对于在更广泛的互联网上运行来说,这绝不是一个安全的做法。当这些应用程序的UDP流量泄漏到未设置的互联网路径时,它会显著降低共享该路径的其他流量的性能,甚至导致拥塞崩溃。默认情况下,支持非受控或非自适应传输行为的应用程序不应这样做,而是应要求用户明确启用此操作模式,并且应验证是否为其保留了足够的路径容量。

3.1.3. 低数据量应用(Low Data-Volume)

任何时候都仅与目的地交换少量UDP数据报的应用程序实施TFRC3.1.2中的其他拥塞控制方案时,网络几乎看不到任何好处,因为这些机制以仅对较长传输有效的方式执行拥塞控制。

任何时候都仅与目的地交换少量UDP数据报的应用程序仍应通过平均每个RTT最多发送一个UDP数据报来控制其传输行为。与[RFC1536]中的建议类似,应用程序应使用3.1.1中规定的方法维护任何目的地的RTT估计值。

某些应用程序无法为目的地维护可靠的RTT估计。这些应用程序不需要或无法使用协议计时器来测量RTT3.1.1)。可以确定两种情况:

1. 第一种情况是,应用程序与对端交换的UDP数据报太少,无法建立统计上准确的RTT估计,但可以监控传输的可靠性(3.3)。这样的应用可以使用丢包时以指数方式退避的预定传输间隔。TCP指定1秒的初始值[RFC6298],这也是UDP应用程序的建议初始值。一些低数据量应用程序,例如SIP[RFC3261]和通用Internet信令传输(GIST[RFC5971]使用500 ms的间隔,在许多情况下,较短的值可能会出现问题。与前一种情况一样,请注意初始超时不是最大可能超时,请参见3.1.1

2. 第二种情况是,应用程序无法维护目的地的RTT估计,因为目的地不发送返回流量。此类应用程序不应在3秒内发送一个以上的UDP数据报,并应尽可能使用更少的激进速率。在许多情况下,较短的值可能有问题。请注意,这种情况下的发送速率必须比以前的情况更加保守,因为缺少返回流量会阻止对丢包(即拥塞)的检测,因此应用程序无法执行指数退避以减少负载。

3.1.4. 支持双向通信的应用程序

双向通信的应用程序应该对通信的两个方向采用拥塞控制。例如,对于客户机-服务器、请求-响应类型的应用程序,客户机应该对请求传输进行拥塞控制,而服务器应该对响应进行拥塞控制。正向和反向的拥塞是不相关的,应用程序应该独立地检测并响应两个方向的拥塞,或者基于整个往返路径上已确认的响应来限制新的和重新传输的请求。

3.1.5. RTT和丢包测量对拥塞控制的影响

TCPSCTPDCCP等传输提供了对拥塞的及时检测,从而在遇到拥塞时立即降低其最大发送速率。这种反应通常在遇到丢包/拥塞后1-2RTT完成。使用UDP的应用程序应实施拥塞控制方案,该方案可对指示拥塞的信号做出快速反应(例如,通过在拥塞信号后的下一个RTT内降低速率)。

UDP拥塞控制算法的操作可能与TCP非常不同。这包括在时间尺度上响应的拥塞控制,适合那些不能在TCP"RTT变化率"模型中有效工作的应用。经历低的或变化的RTT的应用特别容易受到采样错误的影响(例如,由于测量噪声或定时器的准确性)。这表明需要在一个较长的时间间隔内对丢包/拥塞和RTT测量进行平均化;然而,这也会在检测拥塞时造成额外的延迟。一些应用程序可能由于各种原因(包括以下原因)不会立即通过降低发送速率做出反应。RTT和丢包测量只是定期进行(例如,使用RTCP),需要额外的时间来过滤信息,或者应用程序只能在预先确定的时间间隔内改变其发送速率(例如,一些视频编解码器)。

在设计拥塞控制算法时,设计者需要考虑在反馈或拥塞事件之后减少总负载的时间。如果最近的RTT测量值小于实际RTT或测量的丢包率小于实际速率,则可能导致高估可用容量。这种高估可能会导致发送速率对共享路径容量的应用程序或其他流造成拥塞,并可能导致拥塞崩溃——这两种情况都需要避免。

UDP设计的拥塞控制在遇到拥塞时应尽快响应,并且在选择新速率时应同时考虑丢包率和响应时间。实施的拥塞控制方案应在一个数量级内实现与TCP相当的带宽(容量)使用,从而不会使共享一个瓶颈的其他流陷入饥饿。

3.1.6. 突发缓解和起搏(Pacing)

UDP应用程序应该提供机制来调节应用程序可能发送到网络的突发传输。许多TCPSCTP实现提供了防止发送者以线速产生长突发的机制,因为这些机制已知会导致共享网络瓶颈的应用程序的早期丢包。使用TCP[ALLMAN]的节奏也被证明可以改善TCP流与其他流的共存。应用程序的规范中也注意到需要避免过度的传输突发(例如,[RFC7143])。

即使是低数据量UDP流也可能受益于报文节奏,例如,建议发送数据包的三个副本以提高对丢包的鲁棒性的应用程序在几个RTT上调整这三个数据包的速度,以降低由于相同拥塞事件而丢失所有三个数据包的概率(或其他事件,如突发性损坏)。

3.1.7. 显式拥塞通知

互联网应用程序可以使用显式拥塞通知(ECN[RFC3168]为其支持的服务获取好处[RFC8087]

互联网传输,如TCP,提供了一套利用ECN所需的机制。ECN的运作方式是在发送的数据包的IP头中设置一个支持ECN的码点(ECT0)或ECT1))。这表明具有ECN功能的网络设备(路由器和其他设备)可以标记(设置经历拥塞,即Congestion Experience (CE)码点),而不是丢弃IP数据包,作为初步拥塞的一个信号。

UDP应用程序也可以启用ECN获益,前提是API支持ECN,并且它们实现了支持ECN所需的协议机制。

应用程序通过UDP使用ECN所需的一组机制包括:

o 发送方必须提供一种方法来确定(例如,协商)相应的应用程序能够使用兼容的ECN方法提供ECN反馈。

o UDP端口启用ECN的接受者必须检查此端口上接收的每个UDP数据报的ECN字段。

o 接收应用程序需要向发送应用程序提供拥塞信息的反馈。这必须通过提供一种机制将拥塞信息反馈给发送应用程序,来报告接收到的带有CE标记的数据报的存在。反馈还可能报告ECT1)和ECT0)或非ECT数据包的存在[RFC7560]。([RFC3168][RFC7560]TCP指定了方法。)

o 发送支持ECN的数据报的应用程序在收到指示已经历拥塞的反馈时,必须提供适当的拥塞反应。这将导致UDP拥塞控制方法(见3.1)降低发送速率,该方法不低于TCP在同等条件下的反应。

o 发送方应检测不正确支持ECN字段的网络路径。当检测到时,它们需要对拥塞做出保守的反应,甚至退回到不使用ECN的状态[RFC8087]。此方法需要对网络路径内可能在会话生命周期内变化具有鲁棒性。

o 鼓励发送方提供一种机制,以检测未报告CE标记数据包的行为不端的接收方,并对其作出适当反应[RFC8087]

[RFC6679]通过描述一种允许ECN用于使用实时协议(RTP)的基于UDP的应用的方法,提供了这种支持的指导和一个例子。鼓励不能提供这套机制但希望获得使用ECN好处的应用程序使用已经支持ECN的传输协议(如TCP)。

3.1.8. 区分服务模型

使用UDP的应用程序可以使用区分服务(DiffServ)服务质量(QoS)框架。要启用区分服务处理,UDP发送方将发送到网络中的DSCPDifferentiated Services Code Point)码点设置上。通常,UDP/目的端口对将为属于一个流的所有数据包设置一个DSCP值,但如本节后面所述,可以使用多个DSCPDSCP可以从一小组固定值(class选择器码点)中选择,或者从每跳行为(PHBPer Hop Behavior)规范中定义的一组推荐值中选择,或者从对支持DiffServ的特定网络具有纯本地含义的值中选择。通常,包可以在源和目的地之间跨多个网络转发。

在设置非默认DSCP值时,应用程序必须知道DSCP标记可能会在流量源和目的地之间更改或删除。这对使用DSCP的应用程序的设计有影响。具体而言,应用程序的设计不应依赖于特定网络处理的实现;相反,他们需要实施拥塞控制方法,以确定其当前发送速率是否会导致网络拥塞。

[RFC7657]描述了使用DSCP的含义,并提供了在单个网络五元组中使用多个DSCP的建议(源地址和目的地址、源端口和目的端口,以及传输协议得协议号,在本例中为UDPUDP Lite),尤其是对传输协议交互的预期影响,具有拥塞控制或可靠性功能(例如,重传、重新排序)。使用多个DSCP会增加发送方使用的网络转发资源集,从而导致重新排序。它还可能增加资源耗尽或失败的风险。

3.1.9. QoS、预配置或保留容量

IETF通常指定在尽力而为的通用互联网中使用的协议。有时,指定具有不同适用性的协议是相关的。使用UDP的应用程序可以使用集成服务QoS框架。此框架通常在受控环境中可用(例如,在单个管理域内或域之间双边商定的连接)。用于互联网的应用程序不应假定QoS机制由使用的网络支持,因此需要提供拥塞控制、错误恢复等,以防实际网络路径不提供对应的服务。

某些UDP应用程序预计只能部署在使用预配置容量或使用动态调配(例如RSVP)保留容量的网络路径上。多播应用程序也可与预配置容量一起使用(例如,接入网络内的IPTV部署)。这些应用程序可以选择不实施任何拥塞控制机制,而是仅依赖于在为该用途提供和保留容量的路径上传输。对于受限网络环境的子集来说,这可能是一个可接受的选择,但对于在更广泛的互联网上运行来说,这绝不是一个安全的做法。选择此选项的应用程序应仔细详细地描述实现所需控制的供应和管理过程。

默认情况下,支持非受控或非自适应传输行为的应用程序不应这样做,而应要求用户明确启用此操作模式。

为在受控环境中使用而设计的应用程序(见3.6)可以利用网络管理功能来检测它们是否造成拥塞,并做出相应的反应。如果此类应用程序的流量泄漏到未设置的互联网路径,则会显著降低共享该路径的其他流量的性能,甚至导致拥塞崩溃。为此类网络设计的协议应在网络边缘提供机制,以防止流量泄漏到未设置的互联网路径(例如,[RFC7510])。为了保护共享相同路径的其他应用程序,应用程序还应部署适当的断路器,如3.1.10所述。

针对受控环境的IETF规范应提供适用性声明,将应用限制在受控环境中(见3.6)。

3.1.10. 断路器机制

传输断路器是一种自动机制,用于估计流量造成的拥塞,并在检测到过度拥塞时终止(或显著降低)流量[RFC8084]。这是防止拥塞崩溃(其他流可用资源匮乏)的安全措施,对于异构的互联网和难以提前预测的流量至关重要。

断路器是作为保护机制的最后手段。在正常情况下,不应触发断路器;设计用于在严重过载时提供保护。目标通常是限制反映网络路径可用容量的最大传输速率。断路器可以对单个UDP流或流量聚合进行操作,例如,使用网络隧道发送的流量。

[RFC8084]提供了断路器使用指导和示例。[RFC8083]中规定了RTP中断路器的使用。

如果通用互联网中使用的应用程序未实施拥塞控制或运行低数据量服务,则应实施传输断路器(见3.6)。所有的应用都可以实现传输断路器[RCF8084],并鼓励考虑至少实施一个慢动作的传输断路器,以提供对其网络流量的最后保护。

3.1.11. UDP隧道

UDP的一种日益流行的用途是作为隧道协议[INT-TUNNELS],其中隧道端点将另一协议的报文封装在UDP数据报内,并将其传输到另一隧道端点,该隧道端点将UDP数据报解封并转发有效负载中包含的原始报文。这种协议的一个例子是Teredo[RFC4380]。隧道建立虚拟链接,直接连接物理互联网拓扑中较远的位置,并可用于创建虚拟(专用)网络。当路径上可能存在的中间件不支持有效负载协议时,使用UDP作为隧道协议很有吸引力,因为许多中间件支持使用UDP传输。

实现良好的隧道通常对通过包含隧道链接的路径传输的端点不可见。另一方面,对于沿UDP隧道路径的路由器,即两个隧道端点之间的路由器,UDP隧道生成的流量是常规UDP流,封装器和解封装器显示为常规UDP发送和UDP接收应用程序。因为其他流可以与一个或多个UDP隧道共享路径,所以需要考虑拥塞控制。

有两个因素决定UDP隧道是否需要采用特定的拥塞控制机制:第一,有效负载流量是否基于IP;第二,隧道方案产生的UDP流量是否与隧道内携带的有效载荷流量的数量相一致。

基于IP的单播业务通常被假定为拥塞控制的,即假定在发送方处生成基于IP的单播业务的传输协议已经采用足以解决路径上的拥塞的机制。因此,承载基于IP的单播业务的隧道应该已经与共享路径的其他流量进行了适当的交互,隧道的特定拥塞控制机制是不必要的。

但是,如果已知隧道中的IP流量未受到拥塞控制,则建议采取其他措施限制隧道流量对共享路径的其他流量的影响。有关承载IP多播流量的隧道的具体情况,见4.1

以下指导更详细地定义了这些可能的情况:

1. 隧道生成与有效负载流量数量一致的UDP流量,并且有效负载通信量基于IP且受拥塞控制。

这可以说是互联网隧道中最常见的情况。在这种情况下,UDP隧道不应该采用自己的拥堵控制机制,因为隧道流量的拥堵损失已经在隧道流量的原始发送者处触发了适当的拥堵响应。一个断路器机制可以通过控制聚合流量的包络来提供好处。

请注意,本指南建立在大多数基于IP的通信都是拥塞控制的假设之上。如果UDP隧道用于已知不受拥塞控制的基于IP的流量,则适用下一组指导。

2. 隧道产生的UDP流量与有效载荷流量的数量相对应,并且有效载荷流量不是基于IP的,或者基于IP但没有拥塞控制。

例如,当某些链路层协议封装在UDP中时(但不是所有链路层协议;有些是拥塞控制的),可能会出现这种情况。由于不知道隧道传输的非IP流量的拥塞丢失会在发送方触发适当的拥塞响应,UDP隧道应采用为其承载的流量设计的适当拥塞控制机制或断路器机制。由于就中间路由器而言,隧道通常是批量传输应用,因此适用3.1.2中的指导。

3. 隧道产生的UDP流量与有效载荷流量不一致,与有效载荷流量是否基于IP或拥塞控制无关。

此类示例包括以恒定速率发送、在丢包情况下增加传输速率的UDP隧道,例如,由于使用前向纠错时增加冗余,或者在传输行为中不受限制。UDP在隧道中的这些特殊用途超出了本文中给出的一般指导的范围。这种专用隧道的实施者在设计隧道机制时应仔细考虑拥塞控制,并应考虑使用断路器机制。

封装负载的类型可以通过UDP端口识别;由以太网类型或IP协议号标识。隧道应提供限制隧道可能携带的流量类型的机制。例如,设计用于承载IPUDP隧道需要在入口过滤掉非IP流量。当使用通用隧道封装(例如,使用EtherType值进行封装)时,这一点尤为重要。此类隧道应提供一种机制,以限制给定部署封装的流量类型(见[INT-tunnels])。

与许多其他UDP应用程序相比,设计隧道机制需要更多的专业知识,因为隧道通常对通过隧道传输的端点透明,因此它们需要正确模拟IP链路[INT-tunnels]的行为,例如:

o 要求隧道使用ECN代码点进行运输或封装 [RFC6040]

o 隧道端点对IP DSCP字段的使用[RFC2983]

o 隧道设计中的封装考虑[ENCAP]

o ICMP消息的使用[INT-TUNNELS]

o 隧道碎片和数据包大小的处理[INT-tunnels]

o 设计用于支持等成本多路径(ECMP)路由的隧道的源端口使用(见5.1.1)。

o 关于需要保护头[INT-TUNNELS]IPv6隧道校验和使用的指导(见3.4.1)。

o 支持运营和维护[INT-TUNNES]

同时,从隧道传输的网络角度来看,隧道传输的流量与其他任何流量一样,都是应用程序流量。本文仅涉及实施UDP隧道的拥塞控制注意事项;对其他所需隧道行为的讨论超出范围。

3.2. 消息大小指导

IP分片降低了互联网通信的效率和可靠性。单个分片的丢失会导致整个数据包的丢失,因为即使正确接收到所有其他分片,原始数据包也无法重新组装和交付。IPv4和IPv6都存在分片的基本问题。

此外,一些NAT和防火墙会丢弃IP分片。NAT执行的网络地址转换仅在完整的IP数据包上运行,一些防火墙策略也需要检查完整的IP数据包。即使是这样,一些NAT和防火墙也没有实现必要的重组功能;相反,他们选择丢弃所有分片。最后,[RFC4963]说明了特定于IPv4分片的其他问题。(在高速发送的情况下,一秒钟就有可能超出分片序列号-65535,会组装错误)

由于这些问题,应用程序不应发送会导致IP数据包超过PMTU的UDP数据报。因此,应用程序应该使用IP层提供的路径MTU信息,或者实现路径MTU发现(PMTUD)本身[RFC1191][RFC1981][RFC4821],以确定到达目的地的路径是否支持其所需的消息大小而不出现分片。

然而,支持路径MTU发现的ICMP消息正越来越多地通过中间件(包括防火墙)进行过滤[RFC4890]。当路径包括隧道时,某些充当隧道入口的设备会丢弃源自隧道通过的网络设备的ICMP消息,从而阻止这些消息到达UDP端点。

封装层路径MTU发现(PLPMTUD)[RFC4821]不依赖于ICMP消息的网络支持,因此被认为比标准PMTUD更健壮。它不易受到ICMP消息“黑洞”的影响。为了操作,PLPMTUD需要更改传输的使用方式:传输探测数据包和解释这些探测的丢失或成功。这不仅更新了PMTU算法,还影响了丢包恢复、拥塞控制等。可以在面向连接的传输中(例如TCP、SCTP、DCCP)实现这些更新机制,但它们不是UDP的一部分;这种类型的反馈通常不适用于单向应用。

因此,PLPMTUD对希望使用此方法的UDP应用程序提出了额外的设计要求。这对于UDP隧道尤其如此,因为需要考虑发送探测报文的开销,并且可能需要向隧道添加拥塞控制机制(见3.1.11),以及使隧道解封装器处的数据路径复杂化。

不遵循建议进行PMTU/PLPMTUD发现的应用程序仍应避免发送可能导致IP数据包超过路径MTU的UDP数据报。由于实际路径MTU未知,此类应用程序应返回发送短于默认有效发送MTU的消息(见[RFC1122])。对于IPv4,EMTU_S是576字节和第一跳MTU[RFC1122]中较小的一个。对于IPv6,EMTU_S是1280字节[RFC2460]。直接连接的目的地(路径上没有路由器)的有效PMTU是配置的接口MTU,它可能小于最大链路有效负载大小。在支持较大PMTU的路径上传输最小UDP数据报效率低下,这是实现PMTU发现的第二个原因。

要确定适当的UDP有效负载大小,应用程序必须从PMTU大小中减去IP报头的大小(包括任何IPv4可选首部或IPv6扩展首部)以及UDP首部的长度(8字节)。该大小称为最大段大小(MSS,Maximum Segment Size),可以从TCP/IP堆栈[RFC1122]中获得。

不发送超过IPv4或IPv6有效PMTU的消息的应用程序不需要实现上述任何机制。请注意,隧道的存在可能会导致有效PMTU[INT-TUNNES]的额外减少,因此实施PMTU发现可能是有益的。

将应用层消息分段为多个UDP数据报的应用程序应执行分段,以便每个数据报可以独立接收,并在应用程序实现其自身可靠性机制的情况下独立重新传输。

3.3. 可靠性指导

应用程序设计者通常知道UDP不提供任何可靠性,例如,不重传任何丢失的数据包。通常,这是考虑UDP作为传输协议的一个主要原因。确实需要可靠消息传递的应用程序本身必须实现适当的机制。

UDP也不能防止数据报重复,即,应用程序可能会收到同一UDP数据报的多个副本,其中一些副本的到达时间可能比第一个副本晚得多。应用程序设计者应该优雅地处理这种数据报重复,因此他们可能需要实现检测重复的机制。即使UDP数据报接收仅触发幂等运算,应用程序也可能希望抑制重复数据报以减少负载。

需要按序交付的应用程序必须自行重新建立数据报顺序。例如,由于路由瞬变、间歇连接或移动性,相对于其他分组,因特网可以显著地延迟一些分组。这可能导致重新排序,其中UDP数据报以不同于发送顺序的顺序到达接收器。

使用多个传输端口的应用程序需要能够在会话之间重新排序。网络内的负载均衡技术,如ECMP转发,也可能导致不同传输会话之间缺乏顺序,甚至是在相同的两个网络端点之间。

需要注意的是,数据包重新排序或重复数据仍然可以到达的时间可能非常长。更重要的是,没有明确的上限。[RFC793]将TCP段应经历的最大延迟(最大段生存期(MSL))定义为2分钟。没有其他RFC为其他传输协议或IP本身定义MSL。为TCP定义的MSL值足够保守,其他协议(包括UDP)应该使用它。因此,应用程序对于在这2分钟间隔内接收到的延迟或重复数据包的接收应该是健壮的。

丢失数据包或消息的重新传输是一种常见的可靠性机制。这种重传可以增加网络负载以响应拥塞,从而加剧拥塞。使用重传的任何应用程序负责其重传的拥塞控制(以及应用程序的原始流量);因此,须遵守3.1中的"拥塞控制指导"。3.1.1中关于RTT测量的指导也适用于重传丢包检测的计时器。

需要可靠和有序消息传递的应用程序应该尽可能选择提供这些功能的IETF标准传输协议,而不是自行实现这些相对复杂的可靠性机制。

3.4. 校验和指导

UDP首部包括一个可选的16位1的补码校验和,提供完整性检查。从编码或加密的角度来看,这些检查不是很强,设计用于检测物理层错误或恶意修改数据报[RFC3819]。在数据完整性很重要的情况下,应用程序开发人员应实施额外的检查,例如,通过循环冗余检查(CRC)或数据中包含的密钥或非密钥加密哈希来验证通过UDP服务发送的整个对象/文件的完整性。

UDP校验和提供了有效负载在传输过程中未损坏的统计保证。它还允许接收方验证它是数据包的预期目的地,因为包含IP地址、端口号和协议号,并且验证数据包没有被截断或填充,因为它包含大小字段。因此,它可以防止应用程序接收损坏的负载数据来代替或补充发送的数据。[RFC6396]3.1提供了使用校验和字段执行的检查集的更多说明。

应用程序应启用UDP校验和[RFC1122]。对于IPv4,[RFC768]允许通过设置零校验和值来禁用其使用。允许应用程序选择性地丢弃校验和为零的UDP数据报[RFC1122]。

在IPv6上使用UDP时,UDP校验和用于保护IPv6和UDP首部不受损坏(因为IPv6缺少校验和),并且必须按照[RFC2460]中的规定使用。在特定条件下,允许UDP应用程序使用带隧道协议的UDP零校验和模式(见3.4.1)。

选择禁用UDP校验和的应用程序不得对接收到的数据的正确性进行假设,并且在接收到最初发送到其他目的地或已损坏的UDP数据报时,必须正确操作。

3.4.1. IPv6零UDP校验和

[RFC6935]定义了一种方法,该方法允许在隧道协议中使用零UDP校验和模式,前提是该方法满足[RFC6936]中的要求。启用此模式时,应用程序必须实现机制、使用限制。这包括定义使用范围和防止流量泄漏到其他UDP应用程序的措施(见附录A和3.6)。IPv4不存在使用零IPv6 UDP校验和的这些附加设计要求,因为IPv4首部验证IPv6数据包中未受保护的信息。主要要求是:

o 在IPv6中使用UDP校验和必须是所有实现的默认配置[RFC6935]。接收端点必须仅允许在特定启用的UDP目标端口上对IPv6使用UDP零校验和模式。

o 支持不同于[RFC2460]的校验和的应用程序必须符合[RFC6936]第4节规定的所有实现要求和[RFC6936]第5节规定的使用要求。

o UDP应用程序必须检查源IPv6地址和目标IPv6地址是否对具有P零校验和的任何数据包有效,并且必须丢弃此检查失败的任何数据包。为了防止误发,新的封装设计应包括传输层的完整性检查,其中至少包括用于封装的IPv6首部、UDP首部和shim首部(如果有)[RFC6936]。

o 帮助满足[RFC6936]要求的一种方法可能是限制此类隧道的使用,例如,如3.6所述,限制运营商网络的流量。UDP[RFC7510]中为MPLS定义的封装选择了这种方法。

与IPv4中一样,选择禁用UDP校验和的IPv6应用程序不得对接收到数据的正确性进行假设,并且在接收到最初发送到其他目的地或已损坏的UDP数据报时,其行为必须正确。

UDP校验和为零的IPv6数据报将不会通过任何基于[RFC2460]验证校验和或更新UDP校验和字段(如NAT或防火墙)的中间件传递。更改此行为需要更新此类中间件,以正确处理UDP校验和为零的数据报。为了确保端到端的健壮性,可以部署在通用互联网中的应用程序必须提供一种机制,在路径包含丢弃零UDP校验和IPv6数据报的中间件时,可以安全地退回到使用校验和。

3.4.2. UDP-Lite

当使用包含易出错链接的路径时,一类特殊的应用程序可以从交付而不是丢弃部分损坏的有效负载中获益。此类应用程序可以容忍有效负载损坏,并且可以选择使用UDP的轻量级用户数据报协议(UDP Lite)[RFC3828]变体,而不是基本UDP。选择使用UDP Lite而不是UDP的应用程序仍应遵循第3节中描述的用于UDP的拥塞控制和其他指导。

UDP-Lite将UDP“负载长度”字段的语义更改为“校验和覆盖长度”字段的语义。否则,UDP-Lite在语义上与UDP相同。UDP-Lite的接口与UDP的接口不同,它增加了一个(套接字)选项,用于通信校验和覆盖长度:在发送方,这指定了预期的校验和覆盖范围,负载的剩余未受保护部分称为“错误不敏感部分”。默认情况下,UDP-Lite校验和覆盖范围扩展到整个数据报。如果需要,应用程序可以动态修改此长度值,例如,为某些消息提供更大的保护。UDP-Lite始终验证数据包是否已发送到预期目的地,即始终验证首部字段。不敏感部分中的错误不会导致目标丢弃UDP数据报。因此,使用UDP-Lite的应用程序不得对UDP-Lite负载的不敏感部分中接收的数据的正确性进行假设。

UDP-Lite发送方应选择包含所有敏感负载信息的最小校验和覆盖率。例如,使用实时协议(RTP)[RFC3550]的应用程序可能希望保护RTP首部免受损坏。在适当的情况下,应用程序还必须对UDP-Lite负载的不敏感部分(例如,内部CRC)中携带的协议信息引入自己的适当有效性检查。

UDP-Lite接收方必须为传入数据包设置最小覆盖阈值,该阈值不得小于发送方使用的最小覆盖[RFC3828]。接收方应选择一个足够大的阈值,以阻止具有不适当短覆盖域的数据包。这可能是一个固定值,也可能由应用程序协商。UDP-Lite不提供在发送方和接收方之间协商校验和覆盖的机制。因此,这需要由应用程序执行。

当使用UDP-Lite时,应用程序仍然会遇到丢包。UDP-Lite提供的增强依赖于能够截获UDP-Lite首部的链接,以正确识别所需的部分覆盖。当使用隧道和/或加密时,这可能导致UDP-Lite数据报与UDP数据报相同对待,如都会丢包。使用IP分片还可以阻止对UDP-Lite数据报进行特殊处理,这也是应用程序应避免IP分片的另一个原因(3.2)。

某些端点协议栈支持UDP-Lite。当前中间件对UDP-Lite的支持较差,因为UDP-Lite使用的IPv4协议号或IPv6“下一个首部”值与UDP使用的不同;因此,目前很少有中间件能够解释UDP-Lite并在转发数据包时采取适当的操作。这使得UDP-Lite不太适合需要支持互联网的应用程序,直到UDP-Lite在中间件中获得更好的支持。

3.5穿越中间件的指导

NAT和防火墙是中介设备("中间件")的例子,它们可以沿着端到端的路径存在。 中间件通常执行一种功能,要求它维护每个流量的状态。 对于面向连接的协议,如TCP,中间件窥探和解析连接管理信息,并相应地创建和销毁每个流的状态。 对于像UDP这样的无连接协议,这种方法是不可能的。 因此,中间件可以在观察到(根据一些本地标准)指示新流量的报文时创建每流状态,并在没有属于同一流的数据包到达的一段时间后,销毁该状态。

根据中间件执行的具体功能,这种行为可以引入一种时间依赖性,限制了在中间件上成功的UDP流量交换的种类。例如,NAT和防火墙通常将其一侧的部分路径定义为其服务的域的内部,而其另一侧的部分路径则定义为该域的外部。 当第一个数据包从内部穿越到外部时,通常会创建每流状态,当该状态存在时,NAT和防火墙将转发返回的流量。 在每流状态超时后到达的返回流量将被丢弃,其他从外部到达的流量也是如此。

许多使用UDP进行通信的应用都是跨中间件操作的,不需要采用额外的机制。 一个例子是域名系统(DNS),它是严格的请求-响应的通信模式,通常在几秒钟内完成。
 
   在应用程序不交换任何UDP流量的期间,中间件破坏与应用程序会话相关的每流状态时,其他应用程序可能会遇到通信失败。 应用程序应该能够优雅地处理这种通信失败,并实施机制来重新建立应用层的会话和状态。
  
对于某些应用,例如媒体传输,这种重新同步是非常不可取的,因为它可能导致用户可感知的播放伪影(artifacts)。 这种专门的应用可能会定期发送keep-alive消息,以尝试刷新中间件的状态(例如,[RFC7675])。 需要注意的是,不建议在一般情况下使用keep-alive消息,因为它们对许多应用来说是不必要的,而且会消耗大量的系统和网络资源。
 
    在有中间件的情况下,需要使用keep-alive消息来通过UDP提供有用服务的应用,不应超过每15秒一次的传输频率,并应尽可能使用更长的时间间隔。 对于任意中间件的每流UDP状态,没有指定通用的超时。 NAT要求状态超时为2分钟或更长[RFC4787]。 然而,经验证据表明,目前部署的中间件中有相当一部分不幸地使用了更短的超时。 15秒的超时源于互动连接建立(ICE)协议[RFC5245]。 当应用程序在受控环境中部署时,部署者应调查目标环境是否允许应用程序使用更长的间隔,或者是否提供了明确控制中间件状态超时时间的机制,例如使用端口控制协议(PCP)[RFC6887]、中间件通信(MIDCOM)[RFC3303]、信令下一步(NSIS)[RFC5973]或通用插拔(UPnP)[UPnP]。 建议应用对keep-alive发送的时间进行轻微的随机变化("抖动"),以减少来自不同主机的keep-alive传输之间持续同步的可能性[RFC7675]。
 
发送 keep-alive 消息并不能替代实施机制来恢复中断的会话。 像所有的UDP数据报一样,keep-alive消息可能被延迟或丢弃,导致中间件状态超时。 此外,3.1中的拥塞控制指南涵盖了应用程序的所有UDP传输,包括中间件保持信息的传输。 因此,拥塞控制可能导致keep-alive传输的延迟或暂时中止。
 
  不建议在一般情况下使用keep-alive消息。 它们对许多应用来说是不必要的,而且可能消耗大量的资源。 例如,在电池供电的设备上,如果应用需要在很少的流量下保持长时间的连接,那么发送keep-alive消息的频率就会成为控制功耗的决定性因素,这取决于基础网络技术。
 
    由于许多中间件被设计为需要TCP连接的keep-alive消息,其频率远远低于UDP所需的频率,因此在这些部署中,仅这一差异就足以使人们倾向于选择TCP而不是UDP。 另一方面,有传闻表明,通过中间件的直接通信,例如通过使用ICE [RFC5245],TCP的成功率确实比UDP低。 不同传输协议之间的权衡--特别是当涉及到中间件穿越时--值得仔细分析。
 

   在设计可能部署在互联网上的UDP应用时,需要了解中间件的行为有许多变体,虽然UDP是无连接的,但中间件经常为每个UDP流保持状态。 使用多个UDP流会消耗可用的状态空间,也会导致中间件处理后续数据包的方式发生变化(要么是为了保护其内部资源,要么是为了防止被认为是误用)。 当应用程序并行使用多个UDP流时,路径失败的概率会增加(关于使用多个端口的建议,见5.1.2)。

3.6. 有限的适用性和受控环境

对于使用UDP的IETF应用程序规范,已确定了两种不同类型的适用性:

通用互联网。默认情况下,IETF规范以通用互联网上的部署为目标。经验表明,在一个特定环境或特定应用中开发的成功协议往往会在更广泛的环境中使用。例如,最初在局域网内部署的协议随后可能会在穿越互联网的虚拟网络上使用,或者在一般的互联网上使用。为一般互联网使用而设计的应用可能会经历一系列的网络设备行为,特别是应该考虑应用是否需要在可能包括中间件的路径上运行。

受控环境。协议/封装/隧道可设计为仅在受控环境中使用。例如,为网络运营商使用而设计的应用程序可能仅部署在该单一网络运营商的网络内,或部署在相邻一组合作网络运营商的网络上。然后,可以对应用程序流量进行管理以避免拥塞,而不是依赖于在通用互联网上运行时所需的内置机制。针对有限适用性用例的应用程序可能能够利用使用子网的特定硬件(例如,载波设备)或底层协议特性。

解决有限适用性用例或受控环境的规范应该确定在其限制性部署中如何提供相当于为在一般互联网上运行而设计的协议的安全水平(例如,基于特定方法部署的广泛经验的设计,这些方法提供了一般互联网设备中无法预期的功能,以及MPLS设计对首部损坏的稳健性都有助于证明使用替代的UDP完整性检查[RFC7510])。

针对受控环境的IETF规范应提供适用性声明,将应用程序流量限制在受控环境中,并应说明如何提供方法阻止或防止损坏的数据包从环境中逃逸(例如,本规范第5节)[RFC7510])。

4. 多播UDP使用指导

本节补充了第3节,提供了适用于UDP的多播和广播使用的附加指导。

多播和广播传输[RFC1112]通常使用UDP传输协议,尽管它们可能与其他传输协议(例如UDP-Lite)一起使用。

目前有两种多播交付模型:[RFC1112]中定义的任意源多播(ASM,Any-Source Multicast)模型和[RFC4607]中定义的源特定多播(SSM,Source-Specific Multicast)模型。ASM组成员将接收任何源发送到组的所有数据,而SSM将分发树限制为仅一个源。

特殊类别的应用程序也使用UDP进行IP多播或广播[RFC919]。这种专用应用程序的设计需要超越简单的单播特定准则的专业知识,因为这些发送方可能同时跨潜在的非常异构的路径向潜在的非常多的接收方发送数据,这大大复杂了拥塞控制、流控和可靠性机制。

本节提供多播和广播UDP使用的指导。应用程序对广播的使用通常受到本地子网路由器的限制。然而,使用隧道技术和代理可以、并且确实会导致一些广播流量穿越互联网路径。因此,这些指导也适用于广播流量。

IETF定义了一个可靠的多播框架[RFC3048]和几个构建块,以帮助多播应用程序的设计者,如[RFC3738]或[RFC4654]。

任播目的地的发送者必须知道,发送到同一任播IP地址的连续消息可能会传递到不同的任播节点,即到达拓扑中的不同位置。

大多数承载IP多播流量的UDP隧道都使用带有单播目的地址的隧道封装,例如自动多播隧道[RFC7450]。这些必须遵循与承载单播数据的隧道相同的要求(见3.1.11)。有些部署案例和解决方案中,UDP隧道的outer header包含多播目的地址,例如[RFC6513]。这些案例主要部署在保留容量的受控环境中,通常在单个管理域内运行,或在具有保留容量的双边商定路径上的两个域之间运行,因此拥塞控制是可选的,但仍然建议使用断路器技术,以便在提供的负载超过保留容量(例如,由于配置错误)时恢复一定程度的服务。

4.1. 多播拥塞控制指导

单播拥塞控制传输机制通常不适用于多播分发服务,或者根本不适用于大型多播树,因为它们需要双向通信并调整发送速率以适应单个接收方的网络条件。相比之下,多播分发树可能散开到大量的接收者,这限制了带内返回信道控制发送速率的可伸缩性,并且多播分发树的一对多性质阻止了速率适应单个接收者的要求。因此,实现拥塞控制的应用程序负责为互联网多播数据(原生或隧道)生成与TCP兼容的聚合流量。

使用多播的应用程序应该提供适当的拥塞控制。多播拥塞控制需要使用对多播分发树和属于组的接收者的潜在异构性都具有鲁棒性的机制来设计。异质性可能表现在一些接收者比其他接收者遭受更多的丢包、更高的延迟和/或更少的网络条件响应能力。对于所有或部分多播分发树跨越接入网络(例如,家庭网关)的任何多播会话,拥塞控制尤其重要。RFC系列中定义了两种类型的拥塞控制:

o 基于反馈的拥塞控制,其中发送方从接收方接收多播或单播UDP消息,允许其评估拥塞水平,然后调整发送方速率(例如,[RFC5740]、[RFC4654])。与单播相比,多播方法可以在更长的时间尺度上运行(例如,由于异构组的组RTT更高)。控制方法可以决定不降低整个多播组响应于从单个接收者接收的控制消息的速率(例如,发送方可以设置最小速率并决定请求拥塞的接收方离开多播组,还可以决定使用单播拥塞控制以较低速率将内容分发给这些拥塞的接收方)。

o 接收者驱动的拥塞控制,不需要接收者发送显式UDP控制消息进行拥塞控制(例如,[RFC3738]、[RFC5775])。相反,发送方在多个IP多播组之间分发数据(例如,使用一组{S,g}通道)。每个接收者确定其自身的拥塞级别,并仅使用在网络控制平面中发送的多播加入/离开消息来控制其接收速率。该方法可扩展到任意大的接收组。

任何启用多播的接收者都可以尝试加入并接收来自任何组的流量。这可能意味着需要对单个接收者或聚合多播服务进行速率限制。注意,在传输层,无法阻止连接消息传播到下一跳路由器。

某些类别的多播应用程序支持可以在接收者处监控用户级传输质量的应用程序。能够检测到用户质量显著降低的应用程序应将其视为拥塞信号(例如,使用分层多播编码离开组);如果没有,他们应该使用该信号提供断路器,通过离开多播组来终止流。

4.1.1. 批量传输多播应用(Bulk-Transfer)

通过多播分发树执行数据批量传输的应用程序,即每个RTT交换多个UDP数据报的应用程序,应实现拥塞控制方法。目前推荐的IETF方法如下:异步分层编码(ALC)[RFC5775]、TCP友好多播拥塞控制(TFMCC)[RFC4654]、基于波形和方程的速率控制(WEBRC)[RFC3738]、面向NACK的可靠多播(NORM)传输协议[RFC5740]、单向传输的文件传递(FLUTE)[RFC6726],实时协议/控制协议(RTP/RTCP)[RFC3550]。

应用程序也可以按照[RFC2887]的指导并利用[RFC3048]的框架实施另一种拥塞控制方案。选择不实施[RFC4654]、[RFC5775]、[RFC3738]、[RFC5740]、[RFC6726]或[RFC3550]的批量传输应用程序应实施拥塞控制方案,该方案将导致带宽使用在一个数量级内与TCP公平竞争。

[RFC3551]第2节规定,多媒体应用程序应监控丢包率,以确保其在可接受的参数范围内。如果在相同的网络条件下,通过相同网络路径的TCP流在合理的时间尺度上达到不低于UDP流的平均吞吐量,则认为丢包是可接受的。无法精确指定与TCP的比较,但其目的是在时间尺度和吞吐量方面进行“数量级”比较。

4.1.2. 低数据量多播应用

3.1.3中的所有建议也适用于低数据量多播应用。

4.2. 多播的消息大小指导

多播应用程序不应发送导致IP数据包超过[RFC6807]第3节所述有效MTU的UDP数据报。因此,应用程序应使用“Population Count Extensions to Protocol Independent Multicast (PIM)”[RFC6807]提供的有效MTU信息,或自行实现路径MTU发现(见3.2),以确定到达每个目的地的路径是否支持其所需的消息大小而不出现分片。

5. 编程指导

TCP/IP应用程序事实上的标准应用程序编程接口(API)是“套接字”接口[POSIX]。一些平台还为应用程序提供了通过“原始套接字”或类似设施直接组装和传输IP数据包的能力。这是第二种更麻烦的使用UDP的方法。本文中的指导涵盖了应用程序使用UDP的所有此类方法。由于套接字API是目前为止最常用的方法,因此本节的其余部分将对其进行更详细的讨论。

尽管SocketsAPI是在20世纪80年代早期为UNIX开发的,但各种各样的非UNIX操作系统也实现了它。套接字API同时支持IPv4和IPv6[RFC3493]。UDP套接字API在几个关键方面与TCP不同。由于应用程序程序员通常更熟悉TCP套接字API,因此本节将讨论这些差异。[STEVENS]提供了UDP套接字API的使用示例。

UDP数据报可以直接发送和接收,无需任何连接设置。使用套接字API,应用程序可以在单个UDP套接字上从多个IP源地址接收数据包。一些服务器使用此功能同时通过单个UDP套接字与多个远程主机交换数据。许多应用程序需要确保它们从特定的源地址接收数据包;这些应用程序必须在应用程序层执行相应的检查,或者明确请求操作系统过滤接收到的数据包。

许多操作系统还允许连接UDP套接字,即将UDP套接字绑定到特定的地址和端口对。这类似于相应的TCP套接字API功能。但是,对于UDP,这只是一个本地操作,用于简化本地发送/接收功能并过滤指定地址和端口的流量。绑定UDP套接字不会建立连接——UDP不会在发生连接时通知远程端本地UDP套接字已绑定。绑定套接字还允许配置影响UDP或IP层的选项,例如,使用UDP校验和或IP时间戳选项。在某些堆栈上,绑定套接字还允许在收到ICMP错误消息进行传输时通知应用程序[RFC1122]。

如果客户端/服务器应用程序在主机的多个IP接口上执行,则应用程序发送的任何UDP响应应遵循:IP源地址应与承载请求的UDP数据报的IP目的地址匹配(见[RFC1122]4.1.3.5)。如3.5所述,许多中间件期望这种传输行为,并丢弃从不同IP地址发送的回复。

UDP接收方可以接收负载长度为零的有效UDP数据报。请注意,这与read()套接字调用的返回值零不同,后者对于TCP表示连接结束。

UDP不提供流量控制,即发送方在任何给定时间都不知道接收方是否能够处理传入的传输。这是基于UDP的应用程序在出现丢包时需要健壮性的另一个原因。当应用程序发送数据的速度快于出站网络接口的线路速率时,这种丢失也可能发生在发送主机内。它也可能发生在目的地,当应用程序太不频繁地发出接收调用时(例如,接收缓冲区溢出),接收调用无法返回发送的所有数据。鲁棒的流量控制机制很难实现,这就是为什么需要这种功能的应用程序应该考虑使用诸如TCP之类的全功能传输协议。

When an application closes a TCP, SCTP, or DCCP socket, the transport protocol on the receiving host is required to maintain TIME-WAIT state. This prevents delayed packets from the closed connection instance from being mistakenly associated with a later connection instance that happens to reuse the same IP address and port pairs. The UDP protocol does not implement such a mechanism. Therefore, UDP-based applications need to be robust to reordering and delay. One application may close a socket or terminate, followed in time by another application receiving on the same port. This later application may then receive packets intended for the first application that were delayed in the network.

当应用程序关闭TCP、SCTP或DCCP套接字时,需要接收主机上的传输协议来保持时间等待状态。这可以防止关闭连接实例的延迟数据包错误地与稍后的连接实例关联(后者恰好重用相同的IP地址和端口对)。UDP协议没有实现这种机制。因此,基于UDP的应用程序需要对重新排序和延迟具有鲁棒性。一个应用程序可能会关闭套接字或终止,然后另一个应用程序会在同一端口上及时接收。随后,稍后的应用可以接收在网络中延迟的之前应用的报文。

5.1. 使用UDP端口

[RFC6335]中规定了管理“服务名称和传输协议端口号注册表”的规则和程序。[RFC7605]中提供了使用UDP端口的建议。

UDP发送方不应使用零值源端口。无法根据地址或负载类型轻松确定的源端口号可在接收方提供保护,以防路径外设备的数据注入攻击。UDP接收方不应绑定到端口零。

应用程序应在应用程序层执行接收方端口和地址检查,或明确请求操作系统过滤接收到的数据包,以防止接收到任意端口的数据包。此措施旨在提供额外的保护,防止路径外源(端口值可能未知)的数据注入攻击。

应用程序应提供防止路径外数据注入的检查,避免应用程序接收由未经授权的第三方创建的数据包。TCP栈通常使用随机源端口来提供这种保护[RFC6056];UDP应用程序应遵循相同的技术。中间件和终端系统通常对系统端口或用户端口进行假设;因此,建议在动态和/或专用端口范围内使用随机端口。设置“随机”源端口还可以更好地确保报告的ICMP错误源自特定流所使用路径上的网络系统。一些UDP应用程序选择使用源端口的预定值(包括一些多播应用程序),因此这些应用程序需要采用不同的技术。还可以通过随机化数据报载荷内另一协议字段的初始值,并在接收处检查该字段的有效性(例如,RTP具有随机初始序列号和随机媒体时间戳偏移[RFC3550]),来提供对路径外数据攻击的保护。

使用多播时,IP路由器对每个多播数据包执行反向路径转发(RPF)检查。这提供了对路径外数据注入的保护,限制了伪造数据包源地址的机会。当接收方加入多播组并根据源地址进行筛选时,筛选器将验证发送方的IP地址。使用SSM{S,G}通道时总是这样。

5.1.1. UDP源端口熵和IPv6流标签的使用

一些应用程序使用UDP数据报首部作为实现ECMP[RFC6438]的网络设备的熵源。针对此用途的UDP隧道应用程序使用UDP封装内部报文,其中UDP源端口值是熵的一部分,可用于使用ECMP的设备对网络流量的均衡转发。发送隧道端点选择UDP数据报首部中的源端口值,该值是根据内部流信息(例如,封装的数据包首部)计算的。为了提供足够的熵,发送隧道端点将封装的流量映射到UDP源值范围内。该值应在临时端口范围内,即49152-65535,其中端口的高两位设置为1。14位的可用源端口(使用临时端口范围)加上外部IP地址似乎足以满足大多数ECMP应用程序的熵[ENCAP]。

为了避免在IP流中重新排序,应将相同的UDP源端口值用于分配给被封装流量的所有数据包(例如,使用相关首部的散列)。流的熵映射可能在封装流[ENCAP]的生命周期内发生变化。例如,可以将其更改为拒绝服务(DOS)缓解措施,或作为通过ECMP网络实现路由的方法。但是,为流选择的源端口不应每30秒更改一次以上(例如,如[RFC8086]中所述)。

将源端口字段用于熵有几个需要考虑的副作用,包括:

o 它会增加损坏数据包的误发概率,从而增加校验和计算或等效机制的需要,以保护其他UDP应用程序免受误发错误的影响(3.4)。

o 预计将降低3.5中成功穿越中间件的概率。源端口字段的这种使用通常不适合于在通用互联网中部署的应用程序。

o 它可以阻止字段用于防止路径外攻击(如5.1)。因此,设计者需要考虑其他机制来提供等效的保护(例如,限制使用到受控环境[RCFC710]3.6)。

UDP源端口字段也被用于在IPv6中生成熵。然而,在IPv6的情况下,“流标签”[RFC6437]也可替代地用于为负载均衡[RFC6438]提供熵。使用流标签进行负载均衡与字段的定义一致,尽管需要进一步澄清,以确保字段可以一致地用于此目的。因此,指定了更新的IPv6流标签[RFC6437]和ECMP路由[RFC6438]用法。

为确保将来有机会使用流标签,UDP应用程序应设置流标签字段,即使源端口字段中也设置了熵值(例如,IPv6隧道端点可以将源端口流熵值复制到IPv6流标签字段[RFC8086])。鼓励路由器供应商开始使用IPv6流标签作为流哈希的一部分,提供对IP级ECMP的支持,而无需使用UDP。端到端使用流标签进行负载均衡是一个长期的解决方案。即使已经澄清了流标签的使用,在相当大比例的端点开始为其发起的流分配高质量的流标签之前,也会有一段过渡时间。在最终实现广泛部署之前,可能会继续使用传输首部字段的负载平衡。

5.1.2. 使用多个UDP端口的应用程序

单个应用程序可以交换多种类型的数据。在某些情况下,这可能需要多个UDP流(例如,多组流,由不同的五个元组标识)。[RFC6335]建议应用程序开发人员不要向IANA申请分配多个已知端口(用户或系统)。本节未讨论使用具有相同已知端口或成对动态端口(例如,由服务名称或信令协议标识)的多个流的含义。

使用多个流可能会以多种方式影响网络:

o 启动一系列连续连接可以增加网络路径上中间件(如NAPT或防火墙)中的状态绑定数量。基于UDP的中间件通常依赖超时来删除旧状态,因为当应用程序停止使用特定流时,中间件不知道。

o 同时使用多个流可能会导致每个流的不同网络特性。不能假设都遵循相同的路径(例如,当使用ECMP时,流量会根据端口号故意散列到不同的并行路径上)。

o 使用多个流还可以增加中间件(例如NAPT或防火墙)中绑定或查找表的占用率,这可能会导致设备更改其管理流状态的方式。

o 此外,使用过多的流可能会降低单播拥塞控制对拥塞事件作出反应的能力,除非在会话中的所有流之间共享拥塞状态。接收器驱动的多播拥塞控制要求发送应用程序将其数据分布在一组IP多播组上,因此每个接收者都希望从少量同时活动的UDP端口接收数据。

因此,当使用多个UDP流时,应用程序不得假设中间件的行为一致;随着所用端口数量的增加,许多设备的响应也不同。使用不同QoS要求的多个流需要应用程序验证使用每个流(五元组)是否达到预期性能,见3.1.9。

5.2. ICMP指导

应用程序可以利用UDP层出于各种目的向上传递的有关ICMP错误消息的信息[RFC1122]。应用程序应适当验证ICMP消息的负载,以确保这些消息是响应传输的流量而接收的(即,与应用程序实际发送的UDP数据报相对应的报告错误情况)。这需要上下文,例如关于到每个目的地的通信实例的本地状态,尽管这在面向连接的传输协议中随时可用,但基于UDP的应用程序并不总是维护这些上下文。请注意,并非所有平台都有必要的API来支持此验证,而且一些平台在将ICMP信息传递给应用程序之前已经在内部执行此验证。

对ICMP错误消息的任何应用程序响应都应该对临时路由故障(有时称为“软错误”)具有鲁棒性,例如,瞬态ICMP“不可访问”消息通常不会导致通信中断。

ICMP消息正越来越多地通被中间件过滤掉。因此,UDP应用程序不应依赖它们的传递来实现正确和安全的操作。

6. 安全考虑

UDP不提供通信安全。需要保护其通信免受窃听、篡改或伪造的应用程序应采用其他IETF协议提供的端到端安全服务。

UDP应用程序应使用随机源端口或等效技术(见5.1)提供保护,以防止路径外数据注入攻击。

响应短请求且响应可能较大的应用程序是放大攻击的潜在载体,应采取措施将其作为DoS攻击的一部分被滥用的可能性降至最低。这可能意味着在响应之前对发送者进行身份验证;请注意,请求的源IP地址不是有用的身份验证信息,因为很容易伪造。或者它可能意味着以其他方式限制未经验证的短请求产生大响应的情况。应用程序可能还希望提供一些方法来限制它们在一个时间间隔内响应的请求数量,以限制它们所消耗的带宽。

保护UDP通信安全的一个选项是IPsec[RFC4301],它可以通过身份验证首部(AH)[RFC4302]为IP数据包流提供身份验证,并通过封装安全负载(ESP)[RFC4303]提供加密和/或身份验证。应用程序使用Internet密钥交换(IKE)[RFC7296]为其会话配置IPsec。根据为流配置IPsec的方式,可以对UDP首部以及UDP负载进行身份验证或加密。如果一个应用程序只需要身份验证,ESP不需要加密但需要身份验证通常是比AH更好的选择,因为ESP可以跨中间件运行。使用IPsec的应用程序需要实现IPsec协议套件的操作系统的支持,并且网络路径必须允许IKE和IPsec通信。这可能在IPv6部署中变得更常见[RFC6092]。

尽管可以使用IPsec来保护UDP通信,但并非所有操作系统都支持IPsec或允许应用程序轻松地为其流配置IPsec。保护UDP通信的第二个选项是通过DTLS[RFC6347][RFC7525]。DTLS通过加密UDP负载提供通信隐私。它不保护UDP首部。应用程序可以在不依赖操作系统支持的情况下实现DTLS。

存在许多其他用于验证或加密UDP负载的选项。例如,GSS-API安全框架[RFC2743]或加密消息语法(CMS)[RFC5652]可用于保护UDP负载。UDP上的RTP[RFC3550]有许多安全选项,特别是要完成密钥管理,请参阅[RFC7201]。这些选项涵盖了许多用途,包括点对点、集中组通信以及多播。在某些应用程序中,更好的解决方案是保护较大的独立对象,例如文件或消息,而不是单个UDP负载。在这些情况下,可以使用CMS[RFC5652]、S/MIME[RFC5751]或OpenPGP[RFC4880]。此外,在这一领域还有许多非IETF协议。

与拥塞控制机制一样,安全机制也难以正确设计和实现。因此,建议应用程序采用众所周知的标准安全机制,如DTLS或IPsec,而不是发明自己的安全机制。

通用TTL安全机制(GTSM)[RFC5082]可在目标端点与发送方位于同一链路上时与UDP应用程序一起使用。这种轻量级机制允许接收方过滤不需要的数据包。

在拥塞控制方面,[RFC2309]和[RFC2914]讨论了拥塞对互联网无响应流的危险。[RFC8084]描述了可用于设置性能封装的方法,该性能封装有助于在没有拥塞控制或拥塞控制无法对拥塞事件做出反应时防止拥塞崩溃。本文为基于UDP的应用程序的设计者提供了拥塞控制传输的指导,并且不会引起任何额外的安全问题。

一些网络运营商经历了UDP攻击流量的激增,比UDP的基线流量率高出多个数量级。这可以激励运营商限制UDP通信的数据速率或数据包速率。这反过来可能会限制应用程序使用UDP可以实现的吞吐量,并且还可能导致UDP流量的更高丢包率,这在使用其他传输协议时是不会发生的。

发送方和接收方之间存在长期关联的UDP应用程序的设计应确保发送方定期检查接收方是否仍希望(“同意”)接收流量,并且如果没有明确确认,则需要设计为停止[RFC7675]。需要在两个方向上进行通信以实现协议功能的应用程序(如可靠性或拥塞控制)需要独立地检查通信的两个方向,并且可能必须交换保持活动的消息以穿越中间件(见3.5)。

7. 总结

本节以表格形式(表1)总结了第3-6节中制定的主要指导,以便于参考。

附录A.使用IPv6 UDP零校验和模式的案例研究

本附录简要回顾了UDP中的MPLS,作为定义UDP封装的UDP隧道封装示例。本附录的目的是提供一个具体示例,说明在IPv6上的UDP隧道中为MPLS安全使用UDP零校验和模式需要哪些机制。默认情况下,IPv6需要UDP校验和。[RFC7510]中指定了一个选项,该选项允许在特定环境中使用零IPv6 UDP校验和,并定义了使用此模式的一组操作约束。总结如下:

使用IPv6零校验和模式的UDP隧道或封装必须仅部署在单个网络(单个网络运营商)或相邻一组合作网络运营商的网络中,在这些网络中管理流量以避免拥塞,而不是通过需要拥塞控制的互联网。UDP中的MPLS已指定用于单一管理控制下的网络(例如在单一运营商的网络内),其中已知(可能通过了解设备类型和较低层检查)数据包损坏的可能性极低,并且运营商愿意承担未检测到的数据包损坏的风险。

隧道封装器应为每个使用UDP零校验和模式的UDP隧道使用不同的IPv6地址,而不考虑解封装器,以加强解封装器对IPv6源地址的检查(即,同一IPv6源地址不应与多个IPv6目标地址一起使用,这与该目标地址是单播地址还是多播地址无关)。UDP中MPLS的使用可以扩展到一组密切合作的网络管理中的网络(如同意共同提供特定服务的网络运营商)[RFC7510]。

UDP端点中的MPLS除了检查目标IPv6地址外,还需要检查源IPv6地址,强烈建议在UDP隧道中的MPLS之间重用源IPv6地址,这共同为IPv6首部缺少UDP校验和覆盖提供了一些缓解措施。此外,MPLS数据平面仅转发有效标签的分组(即,已由隧道出口标签交换路由器LSR分发的标签),当误发分组包含在接收LSR处无效转发的标签时,提供一些额外的机会来检测UDP分组误发中的MPLS。UDP中MPLS的IPv6 UDP零校验和模式的预期结果是,目标IPv6地址的损坏通常会导致数据包丢弃,因为不太可能抵消对源IPv6和/或MPLS顶部标签的损坏。

上述例外情况中的限制提供了额外的保证,这些限制将IPv6 UDP零校验和模式的使用限制在管理良好的网络上,对于这些网络,MPLS数据包损坏在实践中并不成问题。因此,UDP中的MPLS适合在上述例外情况允许的管理良好的网络中的较低层上传输,并且与未封装在UDP中的MPLS流量相比,此类网络上的内部IP数据包的损坏率预计不会增加。由于这些原因,当IPv6使用UDP零校验和模式时,UDP中的MPLS不提供额外的完整性检查,并且该设计符合[RFC6936]第5节中规定的要求2、3和5。

UDP中的MPLS没有提供一种机制,在发生路径更改时安全地退回到使用校验和,该路径更改将隧道重定向到包含丢弃零UDP校验和的IPv6数据报的中间件的路径上。在这种情况下,UDP隧道中的MPLS将被该中间件屏蔽。[RFC6936]第5节介绍了允许防火墙、NAT和其他中间件支持使用IPv6零UDP校验和的建议更改。MPLS不会由于标签堆栈损坏而累积错误状态。损坏的MPLS标签会导致数据包丢弃或转发(和遗忘),而不会累积MPLS协议状态。需要主动监控UDP通信中的MPLS是否存在错误,因为错误的发生将导致在MPLS协议之外积累一些错误信息,用于操作和管理目的。该设计符合[RFC6936]第5节规定的要求4。此外,网络运营商必须主动监控UDP校验和为零的IPv6流量是否存在错误。

运营商还应部署数据包过滤器,以防止UDP校验和为零的IPv6数据包由于配置错误或数据包错误而从网络中逃逸。此外,网络运营商必须主动监控UDP校验和为零的IPv6流量是否存在错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值