互联网服务器如何响应来自私有 IP 的请求?

互联网服务器如何响应来自私有 IP 的请求?

我正在学习私有/公共 IP、端口转发和 NAT,但仍然找不到一个简单问题的答案:

假设同一网络上的两个用户正在与其网络外的单个服务器通信(例如,我和我的妻子向 yahoo.com 发送 http 请求)。服务器将两个用户视为单个公共 IP,并且通常(如本例)在同一个端口上通信。路由器如何根据两个不同的连接路由数据包?数据包中除了 IP/端口之外还有其他路由信息吗?是否有某个地方维护着某个“会话表”?由谁维护,它到底包含什么?

答案1

在计算机内部、进程之间

首先让我们看看单身的计算机区分并发连接。

大多数传输协议,如 TCP、UDP、SCTP使用港口、来源地和目的地– 即连接两端各一个。也就是说,数据包不要只需“穿过”港口即可;相反,他们端口 X港口 Y。

目的地端口通常是众所周知的(HTTP 为 80,DNS 为 53……),但来源端口通常由操作系统本身随机选择,这也确保了 src/dst 组合是唯一的。

因此,当你的浏览器多次连接到“Yahoo 的 80 端口”时,它们实际上都有不同的源端口,并且操作系统会保留一个套接字表,例如:

PROCESS       PROTO  LOCAL                REMOTE            STATE
9894/firefox  tcp    192.168.6.175:39163  google.server:80  established
9894/firefox  tcp    192.168.6.175:52909  yahoo.server:80   established
17463/chrome  tcp    192.168.6.175:64981  yahoo.server:80   established
9894/firefox  udp    192.168.6.175:4984   8.8.8.8:53        --

因此,当操作系统从yahoo.server:80本地端口 52909 接收到 TCP 数据包时,它可以将其映射到 Firefox 建立的特定连接。

需要注意的是,这与 NAT 无关然而,即使您直接连接,也会发生同样的事情。(但是,NAT 会利用它。)

(您可以使用netstat -n或 Windows 上的各种图形工具查看此表。“本地/远程”通常标记为“源/目标”,尽管这并不完全准确。)


在 NAT 网络内,计算机之间

关于 NAT 的问题的答案非常相似,只是一切都是在更大规模上进行的。

执行 NAT 的路由器会保留一个包含内部和外部地址及端口的“状态”表。例如,如果您的两个 HTTP 请求使用了单独的 TCP 连接,则它们可能会被跟踪为:

PROTO   ORIG-SRC             ORIG-DST         REPLY-SRC        REPLY-DST
6/tcp   192.168.6.42:52909   yahoo.server:80  yahoo.server:80  your.public.ip.addr:52909
6/tcp   192.168.6.175:39163  yahoo.server:80  yahoo.server:80  your.public.ip.addr:39163
6/tcp   192.168.6.175:52909  yahoo.server:80  yahoo.server:80  your.public.ip.addr:28330
17/udp  192.168.6.175:4984   8.8.8.8:53       8.8.8.8:53       your.public.ip.addr:4984

当路由器收到来自 REPLY-SRC(雅虎)发往 REPLY-DST(你的公网 IP 地址)的数据包时,它知道真实的为了撤消 NAT,必须从 ORIG-SRC 列中获取目的地。

(如果没有匹配状态,则处理手动配置的端口转发规则。如果仍然不匹配,则该数据包实际上是发往路由器本身的。)

注意状态表包含地址端口,允许通过端口组合区分到同一服务器的多个连接。在我的示例中,两台计算机意外使用了相同的端口组合,因此第二个连接的端口也进行了转换。

(事实上​​,一些 NAT 看起来仅有的在端口处并完全忽略源地址;这减少了可能的连接数,但使对等程序更容易执行“NAT 打洞”。)

即使对于无连接协议(例如 UDP 或 ICMP),也会保留这种状态,因此即使没有明确的“关闭连接”数据包,这些条目也会在一段时间不活动后过期。(状态表实际上是防火墙的一部分,因此即使没有完成 NAT,路由器仍可能使用它来区分“活动”连接和杂散数据包。)

(如果您的路由器是基于 Linux 的,conntrack -Lcat /proc/net/nf_conntrack将显示此表。对于 OpenBSD 或 pfSense,请尝试pfctl -s state。)

相关内容