RFC3489(STUN),已过时
Han Lv5

RFC3489(STUN)简介

RFC3489(Session Traversal Utilities for NAT,早期称为 Simple Traversal of UDP Through NAT)是最初定义的 STUN 协议,用于帮助客户端在有 NAT(网络地址转换)或防火墙的网络环境中,探测自身在公网上所“呈现”出来的 IP 地址和端口,并推断出 NAT 的类型,从而实现点对点通信(尤其是 UDP 通信)的打洞与穿透。

自 RFC3489 发布后,IETF 又在其基础上进行了修订并发布了 RFC5389,定义了更为通用的 STUN(Session Traversal Utilities for NAT)。但如果我们关注的是 RFC3489 的检测流程,以下内容将对其做一个较为完整的介绍。

RFC3489 检测流程概述

RFC3489 规定了一个通过发送多个 STUN Binding Request 到 STUN 服务器(一般包含至少两个地址或端口)来判断 NAT 类型的流程。它主要基于以下假设:

  1. 服务器可同时在两个不同地址或端口上侦听(通常称为 Server Reflexive Transport Address #1Server Reflexive Transport Address #2)。
  2. 客户端可以根据 STUN 服务器返回的结果(Binding Response)来判断自己“看到”的外部 IP 地址及端口,以及基于对不同测试行为结果的分析,推断 NAT 的行为模式。

注意:随着互联网的发展和 NAT 技术的多样化,RFC3489 中的 NAT 类型检测算法在实际环境中并不总是准确;后来才有了更完善的 RFC5389 / ICE(Interactive Connectivity Establishment)等方案。不过理解 RFC3489 的经典检测流程,对于理解 NAT 和 STUN 依然有帮助。

关键概念

  1. Mapped Address
    客户端从 STUN 服务器收到的 MAPPED-ADDRESS 属性(在 Binding Response 中),表示服务器看到的源 IP 与端口,即“公网上”映射出的地址。
  2. Changed Address
    STUN 服务器在响应中可能会携带 CHANGED-ADDRESS 属性,用于指示另一个可用于测试的 STUN 服务器地址或端口(RFC3489 中常常是同一物理服务器上的另一个端口或 IP)。
  3. NAT 类型
    RFC3489 按照不同的 NAT 行为,将 NAT 分为以下几类:
    • Full Cone NAT
    • Restricted Cone NAT
    • Port Restricted Cone NAT
    • Symmetric NAT
      以及在无 NAT 的情况即“Open Internet”。

RFC3489 检测流程详解

下文给出了经典的 RFC3489 检测流程示例。实际使用中,客户端需要实现一个简单的“状态机”,根据不同测试步骤获得的结果来判断 NAT 类型。

步骤 1: 基础测试 I (Test I)

  1. 客户端 → 服务器(IP1:PORT1)

    • 客户端向 STUN 服务器(第一个地址/端口,记为 IP1:PORT1)发送一个 Binding Request,请求返回自身的外部映射地址。
  2. 服务器响应

    • 服务器收到请求后,将客户端源地址作为 MAPPED-ADDRESS 写入 Binding Response 中。
    • 同时在 Binding Response 中携带 CHANGED-ADDRESS,即服务器可用来进行后续测试的“备用地址/端口” (IP2:PORT2)。
  3. 客户端处理响应

    • 若客户端收到了正确的响应,则可以在返回的消息里读取 MAPPED-ADDRESS。假设该地址为 MappedAddr1

    • 判断 MappedAddr1与客户端自身的本地绑定地址是否相同:

      • 如果相同,说明客户端可能不在 NAT 后(或在一个 Full Cone NAT 中)。继续进行下一步测试以确认具体类型。
      • 如果不同,说明客户端在 NAT 后,需要进一步测试确定 NAT 种类。

步骤 2: 基础测试 II (Test II)

  1. 客户端 → 服务器(IP1:PORT1),但在请求中指定 CHANGE-REQUEST
    • 客户端这次仍然向 IP1:PORT1 发送 Binding Request,但是在 STUN 消息的属性中带上 CHANGE-REQUEST,要求服务器使用与之前不同的地址和端口(即 IP2:PORT2)来发送响应。
  2. 服务器行为
    • 如果服务器实现了 RFC3489,则会检查 CHANGE-REQUEST 属性,如果属性中指定要“Change IP 和 Change Port”,那么服务器就会从 IP2:PORT2 向客户端发送响应。
  3. 客户端的结果判断
    • 如果客户端 能收到 服务器从 IP2:PORT2 发来的响应,则意味着客户端的 NAT 不会阻止来自不同地址和端口的 UDP 数据包通过。这通常表明客户端所在网络是 Open Internet 或 Full Cone NAT
    • 如果客户端 收不到 响应,则通常意味着客户端所在的 NAT 会阻止来自不同 IP/端口的响应包,这一现象多与 Symmetric NAT 或者 (Port) Restricted Cone NAT 类型相匹配。为了区分,还需要下一步测试。

步骤 3: 备用地址测试(Test III)

  1. 客户端 → 服务器(IP2:PORT2)
    • 这次,客户端直接向服务器的另一个地址和端口 IP2:PORT2(即 CHANGED-ADDRESS)发送 Binding Request。
  2. 服务器响应
    • 服务器收到请求后,会返回客户端的 MAPPED-ADDRESS,记为 MappedAddr2
  3. 比较 MappedAddr1MappedAddr2
    • 如果 MappedAddr1MappedAddr2 不同(即,分别是不同的外部端口或 IP),那么通常可以判定为 Symmetric NAT。因为 Symmetric NAT 的映射端口取决于目的地址/端口,对不同目标地址时会出现不同的外部端口。
    • 如果 MappedAddr1MappedAddr2 相同,则说明 NAT 在面对不同的服务器地址时依旧使用同一个外部映射,即不是 Symmetric NAT。结合之前的结果,可以判断是 Restricted Cone NATPort Restricted Cone NAT

流程图

RFC3489.png

常见结果与 NAT 类型判定

以下是根据上述三个测试的可能结果,结合 RFC3489 给出的 NAT 类型划分示例:

  1. Open Internet
    • 在 Test I 中,MappedAddr1 与本地地址相同;
    • 在 Test II 中可以收到响应。
    • 说明无 NAT 或路由器不进行地址转换。
  2. Full Cone NAT
    • Test I 中,MappedAddr1 ≠ 本地地址,表示存在 NAT;
    • Test II 中可以收到响应,说明对于外部地址/端口的变化并不受限;
    • 进一步测试可能仍会得到相同的 MAPPED-ADDRESS
  3. Restricted Cone NATPort Restricted Cone NAT
    • Test I 中,MappedAddr1 ≠ 本地地址;
    • Test II 中收不到响应;
    • Test III 中,MappedAddr1 == MappedAddr2
    • 说明对于来自外部的地址(或端口)存在一定限制,但对同一外部地址使用相同的映射端口。
  4. Symmetric NAT
    • Test I 中,MappedAddr1 ≠ 本地地址;
    • Test II 中收不到响应;
    • Test III 中,MappedAddr1MappedAddr2 不同。
    • 说明在不同外部目的地址时,客户端会被 NAT 分配不同的映射端口。

小结

  • RFC3489 的检测流程主要是依赖一台可以在“两个地址或端口”上提供 STUN 服务的服务器,通过客户端向这两个地址发送请求并观察响应结果来推断 NAT 类型。
  • 关键属性包括 MAPPED-ADDRESSCHANGED-ADDRESS,以及 CHANGE-REQUEST 选项,用来探测 NAT 对外部流量的限制程度。
  • 典型的三个测试(Test I, Test II, Test III)可帮助判断是否有 NAT,以及 NAT 的类型是 Full Cone、Restricted Cone、Port Restricted Cone 还是 Symmetric。
  • RFC3489 虽已被 RFC5389 取代,但它所示范的 NAT 探测流程仍然是理解 NAT 行为和 STUN 工作原理的经典参考。
 评论