当我在这里写到“通常”时,我想到的是具有合理配置的普通消费者 WLAN-NAT 路由器,或者一些具有默认设置的简单 Linux 网络。像往常一样,这可以根据需要变得复杂或复杂。由于这个问题非常基本,这对我来说似乎最有意义,而不是直接寻求任何更复杂的企业级 NAT 解决方案。
您已经接受了一个答案,但让我尝试直接解决您提出的问题:
NAT 如何决定哪些连接是入站的,哪些是出站的?
决策(对于路由器中的任何决策)的基础是某种形式或方式的一组规则。在这种情况下,对于涉及的每个接口(即内部 LAN 接口与外部 WAN/上行链路接口),管理员将实施规则。这些规则完全不同,即 LAN 接口的规则看起来与 WAN 接口的规则大不相同。
知道数据包来自哪里以及它去哪里是路由器工作的基本要素。
让我从一个
例子
维基百科的 NAT 页面有很多关于这个问题的文字,但一个简单的案例(一个简单的公司 LAN 与单个 DSL 上行链路)是这样的:
- 客户端 PC 尝试启动到基于 Internet 的服务器的 HTTP 连接,例如 198.51.100.20。PC 本身有一个非路由地址,如 192.0.2.2。廉价的 DSL 路由器有两个接口,一个是内部接口 (192.0.2.1),一个是外部接口 (203.0.113.10,很可能经常更改并由 DLS 提供商通过某些本地链接协议提供)。因此 PC 通过其默认网关 192.0.2.1 向 198.51.100.20:80 发送一个 SYN 数据包。
- 路由器在其接口 192.0.2.1 接收数据包,就像根本不涉及 NAT 一样。它已配置为在此接口上执行 NAT,因此它继续执行以下操作:
- 发明一个新的端口号,目前尚未使用。例如 12345。
- 将 IP 标头中的“发送者”地址更改为 203.0.113.10。
- 记住 TCP 头中的原始发送端端口号(由 PC 提供),我们称之为 4321。
- 更改 TCP 标头以包含 12345 发送方端口号。
- 在其 NAT 转换表中添加一个条目 (12345; 192.0.2.2; 4321)。
- 将数据包以愉快的方式发送到其自己的上行链路/网关。
- 198.51.100.20 最终接收到数据包,注意到它是一个 SYN(“建立新连接”)并向发送方发回 SYN-ACK 消息。从它的角度来看,这是IP地址203.0.113.10,TCP目的端口为12345。
- 路由器在其 WAN 接口上接收此数据包。WAN 接口已配置为解析这样的 NAT 地址。然后路由器...
- ...检查其 NAT 转换表,找到条目...
- ...将数据包修改为目的地 192.0.2.2...
- ...将 TCP 目标端口修复回 4321 ...
- ...并沿着它的快乐方式发送它(在 LAN 接口上)。
- PC 收到数据包,但看不到任何有关 NAT 过程的信息。包看起来只是一样,如果198.51.100.20送了它,仿佛NAT路由器是根本不存在。
根本没有出现“连接”的话题。NAT 路由器(以其最简单的形式)不需要关心消息的内容。它关心发送方和接收方的 IP 地址和端口,但不关心其他。(当然:这可能会跳过所有与安全和性能相关的问题;但这是关于非常基本的原则,就像这个问题中手头的原则。)
那么路由器是怎么知道的呢?
路由器根本不需要知道“连接”。事实上,对于无连接的 UDP 协议(UDP 打洞)存在类似为 TCP 描述的类似过程,或者实际上可以为任何在传输层中具有端口号之类的协议实现。
路由器需要知道与 NAT 相关的传输层协议(TCP、UDP 等)的原因主要是端口本身不是 IP 的一部分;和端口是使(这种)NAT 很容易实现的“黑客”的原因。
所以,对于你的问题:
NAT 如何决定哪些连接是入站的,哪些是出站的?
根据定义,出站连接以出现在 LAN 接口上的 SYN 数据包(或在 UDP 的情况下为初始 UDP 穿孔)开头。在 NAT 的情况下称它们为“连接”有点过分;它们最终只是作为 NAT 转换表中的临时条目(加上单个 NAT 路由器可能采用的任何安全/性能添加)。
到目前为止,我在答案中使用的场景中不存在入站连接。当然有 NAT 的变体可以做到这一点;例如,您可以使用 LAN 接口上的特定 IP:PORT 静态识别路由器 WAN 接口上的端口,这使得在 NATted LAN 内运行服务器成为可能。廉价的消费类 DSL/WLAN 路由器通常也支持这一点。使用“真正的”路由器,您显然能够以您喜欢的任何形式或方式配置它们。
进一步的入站/出站IP 数据包与示例中给出的数据包没有什么不同。一旦初始 SYN 握手完成并且路由器在其转换表中有条目,它将通过(使用与示例中解释的相同的转换)所有进一步的两个方向的数据包。
如果在这样建立的 TCP 连接的上下文中,服务器想要向客户端发送数据(这是完全可能的 - TCP 是双向的),就 NAT 路由器而言,这些只是进一步的 IP 数据包。它不会真正关心这些数据包的内容(即,它们是否包含某些有效载荷,或者只是 TCP 的“管理”数据包或其他任何内容)。
当您放置路由器时,路由器绝不会以某种方式“关闭管子”。显然,路由器会知道什么时候可以从转换表中清除条目(可能是当它注意到结束连接的 FIN 握手时,或者由于某些超时或某些错误状态),但从头到尾它是一件连续的事情。