(对于以下内容,我将忽略任何 DNS 查找或第二层操作,因为这不是 NAT 故事的相关部分。)
任何 TCP 连接都是由四部分组成的元组:
<source IP> <source port> <destination IP> <destination port>
简而言之:目的 IP 用于将数据包发送到正确的机器,目的端口用于将该机器上的数据包发送到正确的程序/会话 源 IP 用于知道将任何回复发送到哪里。源端口也是如此。发送回复时,源和目标只是交换。
让我们从没有任何 NAT 的两台计算机开始:
- 电脑有IP
1.1.1.1
- 网络服务器有IP
3.3.3.3
- HTTP 的标准端口是
80
当计算机请求网页时,它首先会从随机范围 (1024-65535) 中随机选择一个未使用的端口号。让我们挑2345
。然后将发生以下序列:计算机发送它的数据包:源 IP 1.1.1.1
、源端口2345
、目标 IP 3.3.3.3
、目标端口80
。数据包到达网络服务器,它看到自己的 IP 和端口80
,因此它知道这是对网页的请求。然后,网络服务器将网页以包含源 IP 3.3.3.3
、源端口 80、目标 IP1.1.1.1
和目标端口的数据包的形式发回2345
。计算机收到这些数据包,并知道它是哪个请求的网页,因为端口号2345
。
这些端口组合通常写成这样:1.1.1.1:2345
和3.3.3.3:80
。
现在,互联网上的计算机数量远远超过可用的 IPv4 地址数量。为了保留地址空间,引入了一组私有地址范围,可以自由地用于地址共享。这些范围被称为 RFC1918,如下所示:
- 192.168.0.0 - 192.168.255.255
- 172.16.0.0 - 172.31.255.255
- 10.0.0.0 - 10.255.255.255
这些地址不在 Internet 路由表中的任何位置,因此如果您要在 Internet 主干上发送具有这些范围内的目的地的数据包,它们将被丢弃。这是因为数百万人使用相同的地址。这些地址需要转换为对互联网有用的东西。这就是网络地址转换的用武之地:
我们有两台电脑:
- A:
192.168.0.1
和 B:192.168.0.2
- 他们的网关的公共 IP 为
1.1.1.1
.
- 我们保持相同的网络服务器。
- 两台计算机都希望来自同一服务器的相同网页。
首先两台计算机都选择一个随机端口:比方说:192.168.0.1:2345
和192.168.0.2:5432
。
计算机 A 发送带有源192.168.0.1:2345
和目标的数据包3.3.3.3:80
。网关将此数据包转换为源1.1.1.1:2345
目的地,3.3.3.3:80
并记住对此组合的任何回复都转到192.168.0.1
。因此,当它收到带有 source3.3.3.3:80
和 destination的回复时1.1.1.1:2345
,它会将其转换为 source3.3.3.3:80
和 destination192.168.0.1:2345
并继续发送数据包。
计算机 B 发送带有源192.168.0.2:5432
和目标的数据包3.3.3.3:80
。网关将此数据包转换为源1.1.1.1:5432
目的地,3.3.3.3:80
并记住对此组合的任何回复都转到192.168.0.2
。因此,当它收到带有 source3.3.3.3:80
和 destination的回复时1.1.1.1:5432
,它会将其转换为 source3.3.3.3:80
和 destination192.168.0.2:5432
并继续发送数据包。
如果两台计算机碰巧选择了相同的源端口号,网关将简单地选择另一个免费的随机源端口号,并记住转换端口号。这有时称为 PAT(端口地址转换)。这基本上是 NAT 的一个子集。
这有几种实现方式。网关可能只记住“计算机 X 使用源端口 Y”并将任何带有端口 Y 的内容转发到计算机 X。它可能会记住计算机 X 使用源端口 Y 和目标 Z”并且只将任何从端口 Z 到端口 Y 的内容转发回计算机 X。或者有一个选项,它记住整个元组,并且只将流量发送到与整个源/目标 ip 和端口匹配的计算机 X。