跳到主要内容

7. 基本协议过程 (Base Protocol Procedures)

本节定义 STUN 协议的基本过程. 它描述消息如何构造, 如何发送, 以及接收后如何处理. 它还定义 Binding method 的详细处理过程. 本文档的其他章节描述某种用法可在特定情况下选择使用的可选过程. 其他文档可以通过增加新的 methods, 新的 attributes, 或新的 error response codes 来定义 STUN 的其他扩展.

7.1. 构造 Request 或 Indication (Forming a Request or an Indication)

构造 request 或 indication message 时, agent 必须遵循 Section 6 中创建头部的规则. 此外, message class 必须为 "Request" 或 "Indication" (视情况而定), method 必须是 Binding 或其他文档中定义的某个 method.

随后, agent 添加 method 或 usage 指定的任何 attributes. 例如, 某些 usages 可能指定 agent 使用某种 authentication method (Section 10) 或 FINGERPRINT attribute (Section 8).

如果 agent 正在发送 request, 它应该向该 request 添加 SOFTWARE attribute. 根据 method 的不同, agent 可以在 indications 中包含 SOFTWARE attribute. STUN 扩展应讨论 SOFTWARE 在新的 indications 中是否有用.

对于不使用认证的 Binding method, 除非 usage 另有规定, 否则不要求任何 attributes.

所有通过 UDP 发送的 STUN 消息, 如果已知 path MTU, 其大小应该小于 path MTU. 如果 path MTU 未知, 对于 IPv4 [RFC1122], 消息大小应该取 576 bytes 与 first-hop MTU 中较小者; 对于 IPv6 [RFC2460], 应该为 1280 bytes. 该值对应 IP packet 的整体大小. 因此, 对于 IPv4, 实际 STUN 消息需要小于 548 bytes (576 减去 20-byte IP header, 再减去 8-byte UDP header, 假定不使用 IP options). STUN 不提供处理如下情况的能力: request 小于 MTU, 但 response 会大于 MTU. 预计该限制不会成为 STUN 的问题. MTU 限制是 SHOULD, 而不是 MUST, 这是为了涵盖 STUN 本身被用于探测 MTU 特征 [BEHAVE-NAT] 的场景. 除此类或类似应用外, MTU 约束必须遵循.

7.2. 发送 Request 或 Indication (Sending the Request or Indication)

随后, agent 发送 request 或 indication. 本文档规定如何通过 UDP, TCP, 或 TLS-over-TCP 发送 STUN 消息; 未来可以加入其他传输协议. STUN usage 必须指定使用哪种传输协议, 以及 agent 如何确定接收方的 IP 地址和端口. Section 9 描述了一种基于 DNS 的方法, 用于确定服务器的 IP 地址和端口, usage 可以选择使用该方法. STUN 可以与 anycast addresses 一起使用, 但仅限 UDP, 且仅限未使用认证时.

在任何时候, client 可以对同一个 STUN server 保持多个未完成的 STUN requests (即多个正在进行的 transactions, 且具有不同 transaction IDs). 如果没有其他对新 transactions 速率的限制 (例如 ICE 为连通性检查指定的限制, 或 STUN 运行在 TCP 上时的限制), client 应该按 RTO 间隔向某个 server 发起新的 transactions, 并应该将对同一 server 的未完成 transactions 限制为十个.

7.2.1. 通过 UDP 发送 (Sending over UDP)

当 STUN 运行在 UDP 上时, STUN messages 可能被网络丢弃. STUN request/response transactions 的可靠性通过客户端应用重传 request message 来实现. STUN indications 不会被重传; 因此, UDP 上的 indication transactions 不可靠.

client 应该以 RTO ("Retransmission TimeOut") 为初始间隔重传 STUN request message, 并在每次重传后将间隔加倍. RTO 是 round-trip time (RTT) 的估计值, 按 RFC 2988 [RFC2988] 中的描述计算, 但有两个例外. 第一, RTO 初始值应该可配置 (而不是 RFC 2988 建议的 3 s), 且应该大于 500 ms. 对该 "应该" 的例外是: 使用其他机制推导拥塞阈值的情况 (例如 ICE 为固定速率流定义的机制), 或 STUN 用于已知网络容量的非 Internet 环境时. 在固定线路接入链路中, 推荐使用 500 ms. 第二, RTO 值不应该向上取整到最接近的秒. 相反, 应该保持 1 ms 精度. 与 TCP 一样, 使用 Karn's algorithm [KARN87]. 这意味着, 不应该从导致 request 重传的 STUN transactions 中计算 RTT 估计值.

transaction 完成后, client 应该缓存 RTO 值, 并将其用作发往同一 server 的下一个 transaction 的 RTO 起始值 (基于 IP 地址相同来判断). 该值应该在 10 minutes 后视为过期并丢弃.

重传持续进行, 直到收到 response, 或者总共已经发送 Rc 个 requests. Rc 应该可配置, 并且应该默认值为 7. 如果在最后一个 request 之后, 已经过了等于 Rm 倍 RTO 的时长仍未收到 response (这为最终 request 实际成功时获取 response 提供了充足时间), client 应该认为 transaction 已超时. Rm 应该可配置, 并且应该默认值为 16. 如果出现 hard ICMP error [RFC1122], UDP 上的 STUN transaction 也被视为失败. 例如, 假设 RTO 为 500 ms, requests 将在 0 ms, 500 ms, 1500 ms, 3500 ms, 7500 ms, 15500 ms, 以及 31500 ms 时发送. 如果 client 在 39500 ms 后仍未收到 response, client 将认为 transaction 已超时.

7.2.2. 通过 TCP 或 TLS-over-TCP 发送 (Sending over TCP or TLS-over-TCP)

对于 TCP 和 TLS-over-TCP, client 会打开到 server 的 TCP 连接.

在 STUN 的某些 usages 中, STUN 作为 TCP 连接上的唯一协议发送. 在这种情况下, 发送时不需要任何额外 framing 或 demultiplexing 的辅助. 在其他 usages 中, 或者结合其他 extensions 时, 它可能会与其他数据复用在 TCP 连接上. 在这种情况下, STUN 必须运行在某种 framing protocol 之上, 该 framing protocol 由 usage 或 extension 指定, 并允许 agent 提取完整的 STUN messages 和完整的 application layer messages. 在 well-known port 上运行的 STUN 服务, 或通过 Section 9 的 DNS procedures 发现的端口上的 STUN 服务, 仅用于 STUN 本身, 不用于与其他数据复用的 STUN. 因此, 到这些服务器的连接不使用 framing protocols. 当使用额外 framing 时, usage 将指定 client 如何知道要应用该 framing, 以及要连接哪个端口. 例如, 对于 ICE connectivity checks, 该信息通过 client 与 server 之间的带外协商获知.

当 STUN 独立运行在 TLS-over-TCP 上时, 至少必须实现 TLS_RSA_WITH_AES_128_CBC_SHA ciphersuite. 实现可以也支持任何其他 ciphersuite. 收到 TLS Certificate message 时, client 应该验证证书, 并检查该证书是否标识了适当的一方. 如果证书无效或已被吊销, 或者未标识适当的一方, client 不得发送 STUN message, 也不得以其他方式继续 STUN transaction. client 必须验证 server 的身份. 为此, 它遵循 RFC 2818 [RFC2818] Section 3.1 中定义的身份识别过程. 这些过程假定 client 正在解引用一个 URI. 对于本规范中的用法, client 将 Section 8.1 中使用的域名或 IP 地址视为已解引用 URI 的 host 部分. 或者, client 可以配置一组受信任的域名或 IP 地址; 如果收到的证书标识了这些域名或 IP 地址之一, client 即认为 server 的身份已通过验证.

当 STUN 在 TLS-over-TCP 连接上与其他协议复用时, 强制 ciphersuites 和 TLS 处理过程按这些协议的定义运行.

TCP 和 TLS-over-TCP 上 STUN 的可靠性由 TCP 本身处理, STUN 协议层没有重传. 但是, 对于 request/response transaction, 如果 client 在发送 SYN 以建立连接之后 Ti seconds 内没有收到 response, 它会认为 transaction 已超时. Ti 应该可配置, 并且应该默认值为 39.5 seconds. 选择该值是为了使其等于 TCP 和 UDP 在默认初始 RTO 下的 TCP timeout.

(实际实现中内容继续)