当位于 NAT 后面时,为什么主机 B 不能充当服务器并接受 TCP 连接?

网络工程 ipv4 纳特
2021-08-04 00:12:06

最初,我认为我凭直觉理解了为什么 B 不能接受 TCP 连接,但是当我读到 P2P 应用程序如何通过使用不在 NAT 后面的中间对等点来规避这个确切问题时,我感到非常困惑。

例如,如果 B 在 NAT 后面,而 A 不在,但仍想联系 B,文献指出 A 可以通过不在 NAT 后面的对等方 C 联系 B。但是为什么不直接联系 B,因为 A 和 C 实际上等效,因为它们都没有 NAT?

编辑#1:我被要求提供一些额外的信息,但是这是一个问题,因为我在教科书中阅读了有关 NAT 功能的内容(Kurose/Ross 的自上而下的网络方法)。以下摘录是问题的动机:“... NAT 的另一个主要问题是它会干扰 P2P [应用程序]。回想一下...在 P2P [应用程序] 中,任何参与的 Peer A 都应该能够发起到任何其他参与的 Peer B 的 TCP 连接。问题的本质是,如果 Peer B 位于 NAT 之后,它就不能充当服务器并接受 TCP 连接“

然后,在教科书的后面,它很快提到了连接反转/NAT 穿越的过程(说 A 可以通过中间对等方 C 联系对等方 B)。从而导致我原来的问题。因此,我认为不需要额外的防火墙/网络拓扑信息。

3个回答

地址转换有四种方式:

  • 静态 NAT – 仅转换 IP 地址,其中管理员在转换后明确定义 IP 地址
  • 静态 PAT – IP 地址和端口的转换,其中管理员明确定义转换后的 IP 地址和端口
  • 动态 PAT – IP 地址和端口的转换,其中路由器在转换后确定新的 IP 地址和端口
  • 动态 NAT – 仅转换 IP 地址,路由器在转换后确定新的 IP 地址

这些名称取决于您正在阅读的供应商文档

除了这些类型的转换中的一种之外,所有类型的转换都是双向的——无论是从内部主机还是外部主机发起的,都可以通过转换来处理流量。

一个不是(动态 PAT)是单向的——只有当内部主机发起流量时,流量才会流动

您没有明确指出您指的是哪种类型的翻译,但我认为可以肯定地说您在谈论动态 PAT。为此,您实际上要问的问题是......

为什么动态 PAT 是单向的?

要理解,您必须首先查看动态 PAT 如何处理流量。首先,让我们看一下出站流量:

实用网络 :: 动态 PAT :: 出站

当内部主机通过配置了动态 PAT 的设备发送流量时,设备会转换源 IP 和源端口,然后发送数据包。

原始数据包属性和转换后的数据包属性记录在转换表中。

在返回的路上,返回数据包与转换表进行匹配,以确定如何“未转换”数据包并将其发送到正确的发起主机:

实用网络 :: 动态 PAT :: 入站响应流量

请注意,原始请求的响应流量允许通过转换设备(在本例中为路由器,但许多设备可以执行动态 PAT)返回,因为转换表中的条目存在

但是,如果流量是从外部向动态 PAT IP 地址发起的:

实用网络 :: 动态 PAT :: 入站初始流量

路由器在转换表中没有条目,因此不知道将数据包发送到哪个内部主机(A、B 或 C)。因此,路由器所能做的就是丢弃数据包。

如果你会原谅双关语,NAT 本身是一个重载的术语,因为它可以指代发生在第 3 层和第 4 层(或通常两者)的进程。

在纯 L3 NAT 的情况下,根据定义,转换地址和外部地址之间存在 1:1 映射。重复使用上面的术语, A 是一个私有地址,它被转换为地址E,它可以从 B 和 C 直接到达。从 A 到 C 的数据包被转换,这样 NAT 网关发出它们显然来自 E。来自 A 的响应流量到E,当然,翻译就为A通过网关的方式回到d类似地,任何源自C 并绑定到 E 的流量最终都有效地作为从 C 到 A 建立的连接。换句话说,L3 的 NAT 是双向的。

这里明显的问题是,这在节省地址空间方面完全无效,因此,通常对公共 Internet 连接没有用。由于它的双向性,它是一种在地址分配之间转换或互连部分重叠范围的良好机制。

NAT 对公共 Internet 连接有用的是 L4 NAT - 或者更常见的是端口地址转换 (PAT)。在这种情况下,我们仍然有一个私有源A,一个带有公共地址E的 NAT 网关和其他外部主机BC. 当 A 连接到 C 时,NAT 网关不仅将 L3 地址转换为 E,而且实际上还在 L4 维护了一个状态表 - 特别是(内部源地址、目标地址、源 L4 端口、目标 L4 端口)和(外部 /已转换的源地址、目标地址、已转换的 L4 源端口、目标 L4 端口)。所以在我们的例子中,这将是 - 例如 (A, B, 1023, 80) : (E, B, 1025, 80)。请注意,假设源端口是短暂的。当 B 上的服务器响应时,它将显示为第二个元组的逆元组或 (B, E, 80, 1025),然后 NAT 网关可以将其转换回 (B, A, 80, 1023)。这似乎是一个如从一个正常响应会议继续。请注意,这很容易适用于大多数 TCP 或 UDP 协议,但可能需要不同的规则来处理其他协议(ICMP 等)。

这里的关键优势是大量设备可以共享 NAT 网关的单个地址。缺点是内部主机必须启动 NAT(或实际上是PAT)网关的连接才能了解如何处理响应流量。NAT 网关不知道如何处理由 B发起任意流量。解决这个问题的方法要么是让A 和 B 都可以连接到中间节点C(...正如你所指出的)静态规则NAT 网关表示所有传入特定端口/协议上的公共地址E 的流量都将转换为私有连接返回到A(..也称为端口转发)。

这显然让我们处于一个地方,即公共地址上的给定端口号只能对应于单个内部地址 - 例如,端口 80 到E的连接仅对应于A某个端口没有办法知道(在 L4)端口 80 上E的入站连接应该重定向到A',而无需进行额外的配置和跟踪状态信息。

A 需要联系 B,A 不在 NAT 后面,B 是。

我们必须假设 B 位于隐藏 NAT 之后(过载,根据 RFC 2663 NAPT)并且没有创建静态 NAT 的选项,否则 A 可以使用静态 NAT 打开到 B 的连接,在这种情况下不需要C。

问题是由于 NAT 类型,B 无法接受入站连接。NAPT 没有开放的入站端口。连接是从 B 通过 NAT 发起的,并且 B 的 IP 被转换为为 NAT 配置的 IP。如果 B 的端口号在 NAT 上不是空闲的,也可能会被转换。

B 当然可以发起到 A 的连接,但是如果 B 是服务器,它就不会知道 A 正在尝试联系它,或者使用什么地址来到达 A。

如果您了解用于允许 A 连接到 B 的 NAT 遍历方法,那么这将有所帮助,然后您在任何时候都看不到任何连接入站到 B 的方法,这符合 NAT 对 B 入站连接的限制:

实现连接的一种简单方法是中继:

  • B可以联系A,但是不知道A的IP地址
  • A 和 B 都知道中间设备的 IP 地址 - C(不在 NAT 后面)
  • A 和 B 都与 C 建立出站连接
  • C 将两个连接缝合在一起,并将消息从 A 中继到 B,反之亦然。

另一种方法是连接反转:

  • B可以联系A,但是不知道A的IP地址
  • A 和 B 都知道中间设备的 IP 地址 - C
  • A 和 B 都与 C 建立出站连接
  • B 现在可以获知 A 的 IP 地址和端口
  • B 现在可以与 A 建立直接出站连接

通过中继,C 上的开销很大,因为它位于 A 和 B 之间所有流量的数据路径中。在连接反转的情况下,C 仅用于了解 A 的 IP 地址。建立连接后,A 和 B 之间的流量将直接路由,绕过 C。

我认为您的主要困惑在于这些方法中的每一个的第一步。是的,在您的具体示例中,如果 B 知道要连接到哪个 IP:port,B 可以直接联系 A,但事实并非如此,因此要么需要通过中继服务器代理整个连接,要么使用中间服务器来了解 IP :port 然后使该连接本身出站。

RFC 5128 - State of Peer-to-Peer(P2P) Communication Across Network Address Translators(NATs) 中有更多细节

https://www.rfc-editor.org/rfc/rfc5128#page-8

解释了很多方法,这可能是 3.1 Relaying 的变体

3.1. 接力

在存在 NAT 设备的情况下实现对等通信的最可靠但效率最低的方法是使对等通信看起来像通过中继的客户端/服务器通信一样的网络。考虑图 1 中的场景。两台客户端主机 A 和 B 各自发起了到知名集合服务器 S 的 TCP 或 UDP 连接。集合服务器 S 具有可公开寻址的 IP 地址,用于注册目的,发现和中继。NAT 后面的主机向服务器注册。对等主机可以发现 NAT 后面的主机并使用服务器中继所有端到端消息。客户端驻留在单独的专用网络上,它们各自的 NAT 设备阻止任一客户端直接启动与另一个的连接。

                       Registry, Discovery
                       Combined with Relay
                             Server S
                        192.0.2.128:20001
                                 |
    +----------------------------+----------------------------+
    | ^ Registry/              ^   ^ Registry/              ^ |
    | | Relay-Req Session(A-S) |   | Relay-Req Session(B-S) | |
    | | 192.0.2.128:20001      |   |  192.0.2.128:20001     | |
    | | 192.0.2.1:62000        |   |  192.0.2.254:31000     | |
    |                                                         |
  +--------------+                                 +--------------+
  | 192.0.2.1    |                                 | 192.0.2.254  |
  |              |                                 |              |
  |    NAT A     |                                 |    NAT B     |
  +--------------+                                 +--------------+
    |                                                         |
    | ^ Registry/              ^   ^ Registry/              ^ |
    | | Relay-Req Session(A-S) |   | Relay-Req Session(B-S) | |
    | |  192.0.2.128:20001     |   |  192.0.2.128:20001     | |
    | |     10.0.0.1:1234      |   |     10.1.1.3:1234      | |
    |                                                         |
 Client A                                                 Client B
 10.0.0.1:1234                                        10.1.1.3:1234

     Figure 1: Use of a Relay Server to communicate with peers

两个客户端可以简单地使用服务器 S 在它们之间中继消息,而不是尝试直接连接。例如,要向客户端 B 发送消息,客户端 A 只需将消息沿其已建立的客户端/服务器连接发送到服务器 S,然后服务器 S 使用其与 B 的现有客户端/服务器连接将消息发送到客户端 B。

这种方法的优点是只要
两个客户端都连接到服务器,它就始终有效航路 NAT 设备不需要是 EIM-NAT。中继的明显缺点是它会消耗服务器的处理能力和网络
带宽,
即使服务器有足够的 I/O
带宽并且在拓扑上正确定位,对等客户端之间的通信延迟也可能会增加TURN 协议
[TURN] 定义了一种
以相对安全的方式实现与应用程序无关、面向会话的数据包中继的方法。

您还可以使用 3.2 - Connection Reversal 更具体地适用于您的情况:

3.2. 连接反转

以下用于直接
通信的连接反转技术仅在其中一个对等方位于 NAT 设备后面而另一个不在该设备后面时才有效。例如,考虑图 2 中的场景。客户端 A 位于 NAT 之后,但客户端 B 具有可公开寻址的 IP 地址。Rendezvous Server S 有一个可公开寻址的 IP 地址,用于注册和发现的目的。NAT 后面的主机向服务器注册它们的端点。对等主机使用服务器发现 NAT 后主机的端点。

                      Registry and Discovery
                             Server S
                        192.0.2.128:20001
                                 |
    +----------------------------+----------------------------+
    | ^ Registry Session(A-S) ^     ^ Registry Session(B-S) ^ |
    | | 192.0.2.128:20001     |     |  192.0.2.128:20001    | |
    | | 192.0.2.1:62000       |     |  192.0.2.254:1234     | |
    |                                                         |
    | ^ P2P Session (A-B)     ^     |  P2P Session (B-A)    | |
    | | 192.0.2.254:1234      |     |  192.0.2.1:62000      | |
    | | 192.0.2.1:62000       |     v  192.0.2.254:1234     v |
    |                                                         |
  +--------------+                                            |
  | 192.0.2.1    |                                            |
  |              |                                            |
  |    NAT A     |                                            |
  +--------------+                                            |
    |                                                         |
    | ^ Registry Session(A-S) ^                               |
    | |  192.0.2.128:20001    |                               |
    | |     10.0.0.1:1234     |                               |
    |                                                         |
    | ^ P2P Session (A-B)     ^                               |
    | |  192.0.2.254:1234     |                               |
    | |     10.0.0.1:1234     |                               |
    |                                                         |
 Private Client A                                 Public Client B
 10.0.0.1:1234                                    192.0.2.254:1234

       Figure 2: Connection reversal using Rendezvous server

客户端 A 的私有 IP 地址为 10.0.0.1,应用程序
使用 TCP 端口 1234。此客户端已
在公共 IP 地址 192.0.2.128 和端口 20001 上服务器 S建立连接。NAT A 已
分配 TCP 端口 62000,为自己公共IP地址192.0.2.1,
作为A与
S会话的临时公共端点地址因此,服务器 S 认为客户端 A 使用端口 62000 位于 IP 地址 192.0.2.1。然而,客户端 B 拥有自己的永久 IP 地址 192.0.2.254,并且 B 上的应用程序正在接受端口 1234 上的 TCP 连接。

现在假设客户端 B 希望
与客户端 A建立直接通信会话。 B 可能首先尝试在客户
端 A 认为自己拥有的地址(即 10.0.0.1:1234)或观察到的 A 地址联系客户端 A通过服务器 S,即 192.0.2.1:62000。无论哪种情况,连接都会失败。
在第一种情况下,指向 IP 地址 10.0.0.1 的流量将
被网络丢弃,因为 10.0.0.1 不是可公开
路由的 IP 地址。在第二种情况下,来自 B 的 TCP SYN 请求
将到达定向到端口 62000 的 NAT A,但 NAT A 将拒绝
连接请求,因为只允许传出连接。

在尝试与 A 建立直接连接并失败后,客户端 B 可以使用服务器 S 将请求中继到客户端 A,以启动
与客户端 B 的“反向”连接。客户端 A 在
通过 S接收到此中继请求后,打开一个 TCP通过 B 的
公共 IP 地址和端口号连接到客户端 B。NAT A 允许连接
继续进行,因为它源自防火墙内部,而客户端 B
可以接收连接,因为它不在 NAT 设备后面。

多种当前的对等应用程序实现了这种
技术。当然,它的主要限制是它只有
在只有一个通信对等点位于 NAT 设备后面时才能工作
如果 NAT 设备是 EIM-NAT,则公共客户端可以联系外部
服务器 S 以确定
预期客户端 A 发起连接的特定公共端点,并仅允许来自这些端点的连接。如果 NAT 设备是 EIM-NAT,则公共客户端可以联系外部服务器 S 以确定
预期来自客户端 A 的连接的特定公共端点,并仅允许来自该端点的连接。如果NAT设备不是
EIM-NAT,公共客户端无法知道具体的公共端点
期望来自客户端 A 的连接。在
越来越普遍的情况下,两个对等方都可以位于 NAT 之后,
连接反转方法失败。Connection Reversal 不是
点对点连接问题通用解决方案。如果既不能
建立“正向”也不能建立“反向”连接,
应用程序通常会回退到另一种机制,例如中继。