对于 NAT,你想知道的,可能包括以下几点:
NAT 是啥
为啥需要 NAT
NAT 的分类
NAT 是怎么实现的
NAT 有什么问题
防火墙与 NAT
01 NAT 是啥
NAT,全称叫 Network Address Translation,网络地址转换/翻译,简单讲就是能将私有地址和公有地址进行转换的一个技术。NAT 功能通常会被集成到路由器、防火墙、或独立的 NAT 设备中。
02 为啥需要 NAT
为什么需要转换私有地址和公有地址,以及什么是私有地址和公有地址?
我们知道,由于历史原因,IPv4 地址起初设计的时候,长度只有 32 位,所以只能提供大约 40 亿个地址。这造成了 IPv4 地址的耗尽危机。虽然后面 IPv6 地址被设计出来,能够提供更多的 IP 地址。
但 IPv4 和 IPv6 并不兼容,IPv4 向 IPv6 迁移也并不容易。在迁移的这段时间内,急需一些替代技术来缓解 IPv4 地址的稀缺。NAT 就是其中一种,另外还有 CIDR。
理论上,每个 IP 地址代表了 Internet 上的一个设备,但有一些地址被保留,用作私有的 IP 地址,如下面的三段:
From To
10.0.0.0 10.255.255.255
172.16.0.0 172.31.255.255
192.168.0.0 192.168.255.255
私有地址只用于局域网内部通信,与之对应的就是公有地址。理论上,私有地址不应该在互联网被看到,而公有地址正恰好相反。由于互联网上有通信需求的设备众多,所以公有地址就显得格外稀缺而珍贵,这个时候,如果说能将私有地址在不同的私有网络中重复使用,那将大大缓解公有地址的使用耗尽。
NAT 就是提出来为私有网络服务的。在私有网络中的主机使用私有 IP 地址,当需要与外部 Internet 通信时,网关路由器执行 NAT 功能,将私有 IP 地址转为公有地址。这就可以缓解设备对公有 IP 地址的需求。
03 NAT 的分类
NAT 从概念上说很简单,就是进行私有地址和公有地址的转换,但是怎么转换的,一对一,还是多对一?不同的方法对公网 IP 地址的节省都不一样,根据使用公网 IP 地址数量的不同, NAT 分为以下三类:
① 静态 NAT
这个是最基本的,一对一 NAT,就是静态配置一个私有地址对应一个公网地址,但是问题也很明显,基本没有缓解对公网 IP 地址的使用。
内网 IP | 外网 IP |
---|---|
192.168.1.10 | 219.152.168.222 |
192.168.1.11 | 219.152.168.223 |
192.168.1.12 | 219.152.168.224 |
② 动态 NAT
也叫地址池 NAT,网关路由器维护一个动态变化的 NAT 地址池,当有私网设备要访问公网时,会得到一个临时的公有 IP 地址,若该设备在一定时间内没有和公网通信,这个临时地址就会被释放,给其他设备用,有关它的 IP 映射关系也会从 NAT table 中删除。
通常来说,一个局域网中只有少数设备处于开机状态,且有访问外网的需求,动态 NAT 就非常适用,它可以极大减少公有 IP 地址的分配和使用。但这样还不够,公有地址分配还是相对较多,且管理上不够灵活,所以就有了下面这种方式。
NAPT
全称叫 Network Address and Port Translation,网络地址和端口转换,它比前面的方式多利用了 Port 层面的信息进行转换,可以实现多对一,即多个私有地址映射一个公有地址的需求,更能节省地址且管理更灵活。
其实更为准确的理解应该是 IP + session 的转换,session 是更为通用的一种说法,指代的是能够对不同类型的数据进行标识的特定字段,比如 TCP/UDP 报文,session=port,ICMP 报文,session=ICMP Indentifier。下面显示一个带 IP+端口号的 NAT 表:
内网 IP | 外网 IP |
---|---|
192.168.1.10:5566 | 219.152.168.222:9200 |
192.168.1.11:80 | 219.152.168.222:9201 |
192.168.1.12:4465 | 219.152.168.222:9202 |
可以看到,只用了一个 公网 IP,即可完成三个内网 IP 的转换。
以上方法是根据使用公网 IP 地址数量进行分类,也有一种分类是根据 NAT 的数据流向进行分类,将 NAT 分为:
SNAT :数据流从私网访问公网,到达 NAT 网关进行 SNAT,根据配置的 NAT 表,将数据包的
src_ip
改为对应的公网地址,如果 port 有记录,也要相应修改DNAT :数据流从公网访问私网,由于不知道私网地址,所以数据包的
dst_ip
是 NAT 网关对外的公网地址,到达 NAT 网关进行 DNAT,同理将数据包dst_ip
改为对应的私网地址,同样 port 有记录也做修改
04 NAT 是怎么实现的
啰嗦这么多,想必大家应该都知道 NAT 是怎么实现的了,无非就是网关设备或者专用 NAT 设备维护一个 NAT 映射表来完成 NAT 的转换工作,这个过程我们重点注意两点:
连接跟踪
checksum 修改
在 NAT 网关收到响应包的时候,它是如何知道要传给内部的具体哪个主机呢?这里主要用到的技术就是连接跟踪。
在 NAT 网关收到内部主机的请求包之后,会做 SNAT ,然后把本次连接记录保存到一个连接跟踪表(Track Table)里,当收到响应包之后,就可以根据 Track table 确定目标主机,然后做 DNAT,转发给主机。
如果是存在端口转换的情况,即 NAPT,那么需要在 Track table 里加入端口信息区分,这样来回的 NAT 转换也就不会有问题。
图片来源ref1
checksum 的修改就是很自然的,源目的 IP (NAPT 还有端口)改变了,包头中有关联的字段也要相应改变,其中关联的就是 checksum 字段。
checksum 字段存在于 IP 头部和 TCP/UDP 头部(UDP 头部是可选的),IP 头部 checksum 的校验范围只在头部,TCP/UDP checksum 则包括一个伪首部+TCP/UDP header + TCP/UDP payload,伪首部就包含了 IP 地址信息,所以当 IP 改变了,IP 头部和 TCP/UDP 头部(如果有)的 checksum 都需要相应改变。
另外,还需要注意的是,其他的一些协议,比如说 ICMP、FTP、DNS 等,它们的数据中如果有携带 IP 和 TCP port 信息的,也需要修改 checksum 的字段。
05 NAT 有什么问题
看很多资料上,罗列了好几种 NAT 的问题,比如说 “违反 IP 的体系结构、分层原则,网关设备变重等等”,这些问题在我看来有点鸡蛋里挑骨头,要减缓公网 IP 地址的使用,这是必然的做法。
要说问题,可能就在于两点:
1)从性能上来说,地址转换增加了延迟,这个也有点挑,对于高性能的应用来说,能直接转必然也不会考虑 NAT。
2)有些嵌入 IP 地址或端口的应用可能工作会比较麻烦。典型的比如 FTP,它的 payload 中会嵌入一些 IP 地址和端口号的信息,这种情况下除了需要 NAT 转换表负责转换包头的 IP 和端口字段外,还需要额外的程序来处理 payload 中关联的字段,就会给网关设备带来更加繁重的处理压力。
06 NAT 与防火墙
NAT 将网络划分为内部网络和外部网络这个特性,基本就是实现一个防火墙的功能了。它隐藏了主机自己的真实 IP,仅通过端口复用来与外网通信。所以我们也看到,Linux系统实现的内部防火墙 iptables 中就有 NAT 的实现。
下面就来看看 iptables 中的 NAT 是如何做到防护的。
我们都知道,iptables 有 4 表 5 链的防护体系,NAT 就是其中的一张表,它可以作用在 PREROUTING、OUTPUT、POSTROUTING 这 3 条链上(有些系统还包含INPUT 链,不是必须的),如下图所示:
其中,SNAT 因为要负责转换出本机的包,所以是作用在 OUTPUT 和 POSTROUTING 两条链上,OUTPUT 负责从本机发出的包的 NAT,POSTROUTING 负责非本机转发的包的 NAT(也就是经过 FORWARD 链转发的包);
而 DNAT 则是负责转换进入主机的包,所以作用在 PREROUTING 链上。
通过 iptables 的命令,我们可以配置下面的 SNAT 和 DNAT 命令来实现地址的转换。
1. 首先配置 SNAT,我们配到 POSTROUTING 链上:
iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -j SNAT --to-source 公网IP
这条命令的意思是将来自 10.10.0.0/16 网段的报文的源地址改为公司的公网 IP 地址。
-t nat:表示 NAT 表
-A POSTROUTING:表示将该条规则添加到 POSTROUTING 链的末尾,A 就是 append。
-j SNAT:表示使用 SNAT 动作
--to-source:表示将报文的源 IP 修改为哪个公网 IP 地址
2. 然后配置 DNAT,配到 PREROUTING 链上:
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号
这条命令的意思是将来自公网IP:端口号的报文的目的地址改为私网IP:端口,可以看到这里多了端口的信息。原因是要区分公网访问的是私网的那个服务,所以需要明确到端口层级,才能精确送到客户端。而 SNAT 不需要端口信息也可以完成正确转发。
-I PREROUTING:表示将该条规则插入到 PREROUTING 的首部,I 就是 insert
--to-destination:表示将报文的目的 IP:端口修改为哪个私网IP:端口
06 总结
NAT 的分类,现在主要的应用都是 NAPT
SNAT、DNAT,NAT 与防火墙的实现
IPv6 也有 NAT 的版本,叫 NAT6,为什么 IPv6 也需要 NAT 呢?大家可以思考一下。
参考:
https://www.cnblogs.com/dongzhuangdian/p/5105844.html
http://www.zsythink.net/archives/1764
后台回复“加群”,带你进入高手如云交流群
推荐阅读:
▼
喜欢,就给我一个“在看”
10T 技术资源大放送!包括但不限于:云计算、虚拟化、微服务、大数据、网络、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公众号内回复「1024」,即可免费获取!!