从 NAT 说起

来源:互联网 发布:钢琴知乎 编辑:程序博客网 时间:2024/06/02 14:30

从 NAT 说起

Capture

假设北京办事处的一台机器 IP 是 10.0.0.1(这是一个内网 IP,不可以在 Internet 上使用),上海办事处的一台机器 IP 是 10.0.0.2,它们要通过 Internet 通信。北京办事处的公网(Internet)IP 是 1.1.1.1,上海办事处的公网 IP 是 2.2.2.2。

一种简单的方式是,在北京办事处的边界路由器(Edge Router)把出去的数据包源 IP 10.0.0.1 变成 1.1.1.1,目的 IP 10.0.0.2 变成 2.2.2.2;把进来的数据包目的 IP 1.1.1.1 变成 10.0.0.1,源 IP 2.2.2.2 变成 10.0.0.2。在上海办事处的边界路由器做类似的地址翻译。这样 10.0.0.1 和 10.0.0.2 就能通信了,它们完全不知道 Internet 和地址翻译过程的存在。这就是基本的 NAT(Network Address Translation)。

Capture

不过这种做法有严重的问题。设想上海办事处增加了一台机器,内网 IP 为 10.0.0.3。不管北京办事处那边怎么处理,上海办事处的边界路由器收到一个目的 IP 为 2.2.2.2 的数据包,该发给 10.0.0.2 还是 10.0.0.3 呢?这种 bug 看起来很简单,但却是设计者很容易忽略的。设计网络拓扑或网络协议时,不能光想着数据包怎么出去,还得想好回复的数据包怎么进来。使用简单 NAT 的话,每增加一台内网机器,就要在边界路由器上增加一个公网 IP。

我们知道公网 IP 是很宝贵的,NAPT(Network Address and Port Translation)应运而生。Linux 里的 NAT 事实上是 NAPT。出去和进来的连接需要分别考虑。对于进来的连接,NAPT 的基本假设是共享同一公网 IP 的两台机器不会提供相同的服务。例如 10.0.0.2 提供 HTTP 服务,10.0.0.3 提供 HTTPS 服务,则上海办事处的边界路由器可以配置成 “目的 IP 是 2.2.2.2 且目的端口是 80(HTTP)的发到 10.0.0.2,目的端口是 443(HTTPS)的发到 10.0.0.3”。这就是 DNAT(Destination NAT)。

对于出去的连接,事情就稍微复杂一些。10.0.0.2 发起了一个到 10.0.0.1 的连接,其源端口是 20000目的端口是 80。10.0.0.3 也发起了一个到 10.0.0.1 的连接,其源端口是 30000,目的端口也是 80。当一个来自北京办事处的回复包到达上海办事处的边界路由器时,其源端口是 80,目的端口是 20000,如果边界路由器不保存连接状态,显然不知道这个包该转给谁。也就是边界路由器要维护一张表:

Capture

当一个回复包过来的时候,查源端口(80)和目的端口(20000),匹配上第一条记录,知道该发给 10.0.0.2。为什么需要“新的源端口”这一列呢?如果 10.0.0.2 和 10.0.0.3 分别以相同的源端口发起了到相同目的 IP、相同目的端口的 TCP 连接,这两个连接的回复包将无法区分。这种情况下,边界路由器必须分配不同的源端口,实际发出去的包的源端口就是“新的”。对出去的连接做网络地址转换叫做 SNAT(Source NAT)。

0 0
原创粉丝点击