网络基础: NAT 是如何工作的 ?
2018-02-10 计算机网络
什么是 NAT ?
NAT(Network Address Translation,网络地址转换) 是一种网络技术,通过重写 IP 数据包的 {源 IP 地址} 或者 {目标 IP 地址} 信息,被普遍用来解决 “公网 IP 地址短缺” 的问题。
主要功能
将内部网络 (如企业或居民住宅) 的私有 IP 地址转换为公网 IP 地址,从而允许多个内部主机/设备共享一个公网 IP 地址与外部网络 (一般指互联网) 进行通信。
为什么需要 NAT ?
- 缓解 公网 IPv4 地址短缺问题 (最主要的原因)
- 提高网络安全性,NAT 通过隐藏内部网络的 IP 地址结构,外部用户无法直接访问内部网络设备 (透明代理)
- 私有 IP 地址可以灵活扩展,不同的私有地址可以在不同的内部网络中使用 (例如 A 公司的某台服务器和 B 公司的某台客户端具有相同的 IP 地址,这是完全 OK 的,因为这两个设备之间不会进行通信)
当然,NAT 同时也存在一些不足 (缺点):
- 资源开销:NAT 设备需要维护大量的地址转换信息
- 协议兼容性:一些应用层协议(如 SIP、IPSec)流量可能无法穿越 NAT 设备,需要额外的配置或技术来解决
- 性能:由于每个数据包都需要进行地址转换,会对网络性能产生一定的影响
- 限制: NAT 受限于未被占用的端口号数量
实现类型
既可以在支持网络地址转换的路由器(称为 NAT 网关)中配置 NAT,也可以在 Linux 服务器中配置 NAT(Linux 服务器实际上充当的是 “软件路由器” 的角色)。
NAT 根据实现方式分为三类:
1. 静态 NAT
内网 IP 与公网 IP 是一对一的永久映射关系。
例如:内部地址 192.168.1.10 映射到公网地址 203.0.113.10。
2. 动态 NAT
内网 IP 从公网 IP 池中,动态选择一个进行映射。
例如:多个内部地址 192.168.1.10, 192.168.1.11 等可以动态映射到公网地址池中的 203.0.113.10, 203.0.113.11 等。
3. NAPT
网络地址端口转换 NAPT(Network Address and Port Translation),目前主流的 NAT 实现方式,目标是为了更有效地利用公网 IP 地址 (一个公网 IP 应该服务于尽可能多的内部 IP),现代的 NAT 转换表把传输层的端口号也加上了,这样多个内部的主机/设备就一个共用一个公网 IP, 一般将 NAPT 简称为 “地址转换表”。
地址转换类型
在描述 NAT 的技术实现原理之前,首先来介绍几个专业术语。
SNAT
SNAT(Source Network Address Translation)主要用于转换数据包中的源 IP 地址,目标 IP 地址保持不变,主要目标是隐藏内部网络中设备的私有 IP 地址,并将其转换为一个公网 IP 地址。
应用场景:多个内网 IP 地址共享一个公网 IP 地址。
PACKET FORWARDED PACKET RECEIVED
|----------------------| |----------------------|
| IP PACKET | | IP PACKET |
| | | |
| SRC: 192.168.0.2 | | SRC: 100.100.100.100 |
| DST: 123.125.115.110 | | DST: 123.125.115.110 |
| |---------------| | | |---------------| |
| | TCP PACKET | | = (SNAT) => | | TCP PACKET | |
| | DPORT: 80 | | | | DPORT: 80 | |
| | SPORT: 2345 | | | | SPORT: 3456 | |
| | ... DATA ... | | | | ... DATA ... | |
| |---------------| | | |---------------| |
|----------------------| |----------------------|
DNAT
DNAT (Destination Network Address Translation) 主要用于转换数据包中的目标 IP 地址,源 IP 地址保持不变,主要目标是将 公网 IP 地址的请求重定向到内部网络的特定网络设备。
应用场景:将外部请求重定向到内部服务器,同时隐藏外部请求对应的后端服务器的真实 IP 地址。
PACKET RECEIVED PACKET FORWARDED
|----------------------| |----------------------|
| IP PACKET | | IP PACKET |
| | | |
| SRC: 123.125.115.110 | | SRC: 123.125.115.110 |
| DST: 100.100.100.100 | | DST: 192.168.0.2 |
| |---------------| | | |---------------| |
| | TCP PACKET | | = (DNAT) => | | TCP PACKET | |
| | DPORT: 3456 | | | | DPORT: 2345 | |
| | SPORT: 80 | | | | SPORT: 80 | |
| | ... DATA ... | | | | ... DATA ... | |
| |---------------| | | |---------------| |
|----------------------| |----------------------|
双向地址转换
同时使用 SNAT 和 DNAT,当接收到网络包时,执行 DNAT,把目标 IP 转换为内部 IP;而在发送网络包时,执行 SNAT,把源 IP 替换为外部 IP。
下面通过一个小例子来说明,为了便于演示,这里省略 NAT 网关中的端口映射关系。
- 内部主机 (IP: 192.168.0.2) 访问 http://baidu.com (123.125.115.110)
- NAT 网关会把源 IP 地址 (192.168.0.2) 转换成自己的公网 IP (100.100.100.100),然后发送给 http://baidu.com
- baidu.com 收到请求后,发送响应
- NAT 网关接收到 baidu.com 的响应数据包后,将目标 IP 地址转换成内部 IP 地址 (192.168.0.2),发送给内部对应的主机
实现原理示例
NAT 的基本原理是在转发网络包时,对 IP 头部中四元组的 (源 IP, 目标 IP, 源端口,目标端口) 进行改写。
下面通过一个具体的小例子,来说明 NAT 的工作原理。
私有 (内网) 地址向公网地址发送数据包
假设这里的 NAT 转换工作是由网关来完成的,其中 (NAT 网关) 公网 IP + 端口号 <=> 私有 IP + 端口号
的映射关系如下图所示,当然,这个映射关系也就是 地址转换表
.
现在私有 IP 10.10.1.1
要通过端口 1025
向公网 IP 192.0.2.79
的 80
端口发送数据,其中,NAT 网关的 IP 为 198.18.8.31
。
- 私有 IP
10.10.1.1
通过端口1025
发送数据包 - SNAT: 网关通过地址转换表,将数据包中的源 IP 改写为自身 IP
198.18.8.31
, 源端口改写为私有地址的映射端口5436
- 公网 IP
192.0.2.79
的80
端口接收到数据包后,进行响应的处理,然后向网关 IP198.18.8.31
的端口5436
发送数据包 - DNAT: 网关接收到数据包后,通过地址转换表,将数据包中的目标 IP 改写为私有 IP
10.10.1.1
, 目标端口改写为私有地址的端口1025
公网地址向私有 (内网) 地址发送数据包
整个过程和 私有地址向公网地址发送数据包 类似,这不过是网关的 SNAT, DNAT 工作顺序整好相反,这里不再赘述,感兴趣的读者可以参考下图进行推导。
NAT 设备支持端口数量上限
💡 网络连接 {五元组} 对于 NAT 设备依然适用。
NAT 设备最多可以支持的端口号映射数量取决于:
-
端口数量:NAT 设备可以使用的端口号范围从 1 到 65535,其中一些端口号(如 0-1023)通常保留用于特权服务(如 HTTP、HTTPS、FTP 等),因此可用的端口号大约在 1024 到 65535 之间,这样实际可用的端口号大约有 64511 个。
-
IP 地址数量:如果 NAT 设备只有一个公有 IP 地址,那么它最多可以映射约 64511 个端口。但如果设备有多个公有 IP 地址,每个 IP 地址都可以使用约 64511 个端口号,支持的端口映射数量可以组合增加。例如,如果 NAT 设备有 10 个公有 IP 地址,那么它可以支持的端口映射数量大约是 10 × 64511 = 645110 个。
-
设备性能和内存:虽然理论上可以支持这么多的端口号映射,但实际情况中,NAT 设备的硬件性能(CPU、内存)和软件实现也会限制其实际支持的连接数。
如果某个内网主机向公网服务端发起了大量连接,例如 10 万连接,这会占用 NAT 设备的大量端口号资源。
假设 NAT 设备有两个公有 IP 地址(203.0.113.1 和 203.0.113.2),每个 IP 地址最多支持 64511 个端口,并且负载均衡策略为轮询,那么连接端口映射情况如下:
- 为 203.0.113.1 分配 50000 个连接
- 为 203.0.113.2 分配 50000 个连接
NAT 和 iptables
iptables 中的 NAT 表
用于实现网络地址转换,包含 3 种内置链:
- PREROUTING
- POSTROUTING
- OUTPUT
iptables 的基本语法命令格式:
iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]
通过 iptables 实现流量转发,将目标 IP 地址为 192.168.1.1
+ 目标端口为 27017
的所有 TCP 数据包转发到 10.0.0.2:1234
。
iptables \
-A PREROUTING # 追加一条规则到 PREROUTING 链,常用于 DNAT
-t nat # 用于 nat 表
-p tcp # 这条规则仅适用于 TCP 数据包
-d 192.168.1.1 # 这条规则仅适用于目标 IP 地址为 192.168.1.1 的数据包
--dport 27017 # 这条规则仅适用于目标端口为 27017 的数据包
-j DNAT # 指定目标网络地址转换
--to-destination # 指定转发的目标地址为 10.0.0.2:1234
10.0.0.2:1234
下面是流量转发的示意图,因为是 DNAT, 所以源 IP 地址和源端口在转发过程中不会发生变化。
PACKET RECEIVED PACKET FORWARDED
|---------------------| |---------------------|
| IP PACKET | | IP PACKET |
| | | |
| SRC: 192.168.1.2 | | SRC: 192.168.1.2 |
| DST: 192.168.1.1 | | DST: 10.0.0.2 |
| |---------------| | | |---------------| |
| | TCP PACKET | | =(DNAT)=> | | TCP PACKET | |
| | DPORT: 27017 | | | | DPORT: 1234 | |
| | SPORT: 23456 | | | | SPORT: 23456 | |
| | ... DATA ... | | | | ... DATA ... | |
| |---------------| | | |---------------| |
|---------------------| |---------------------|
更多 iptables 技术原理和使用方法可以参考 这篇文章。