文章内容为学习整理笔记,绝大部分来源于 倪朋飞 老师的 Linux性能优化实战
一、NAT原理
NAT 技术可以重写数据包的源 IP 或者目的 IP,被普遍地用来解决公网 IP 地址短缺的问题。它的主要原理就是,网络中的多台主机,通过共享同一个公网 IP 地址,来访问外网资源。同时,由于 NAT 屏蔽了内网网络,自然也就为局域网中的机器提供了安全隔离。
你既可以在支持网络地址转换的路由器(称为 NAT 网关)中配置 NAT,也可以在 Linux 服务器中配置 NAT。如果采用第二种方式,Linux 服务器实际上充当的是“软”路由器的角色。
NAT 的主要目的,是实现地址转换。根据实现方式的不同,NAT 可以分为三类:
• 静态 NAT,即内网 IP 与公网 IP 是一对一的永久映射关系。
• 动态 NAT,即内网 IP 从公网 IP 池中,动态选择一个进行映射。
• 网络地址端口转换 NAPT(Network Address and Port Translation),即把内网 IP 映射到公网 IP 的不同端口上,让多个内网 IP 可以共享同一个公网 IP 地址。
NAPT 是目前最流行的 NAT 类型,我们在 Linux 中配置的 NAT 也是这种类型。而根据转换方式的不同,我们又可以把 NAPT 分为三类:
第一类是源地址转换 SNAT,即目的地址不变,只替换源 IP 或源端口。SNAT 主要用于,多个内网 IP 共享同一个公网 IP ,来访问外网资源的场景。
第二类是目的地址转换 DNAT,即源 IP 保持不变,只替换目的 IP 或者目的端口。DNAT 主要通过公网 IP 的不同端口号,来访问内网的多种服务,同时会隐藏后端服务器的真实 IP 地址。
第三类是双向地址转换,即同时使用 SNAT 和 DNAT。当接收到网络包时,执行 DNAT,把目的 IP 转换为内网 IP;而在发送网络包时,执行 SNAT,把源 IP 替换为外部 IP。双向地址转换,其实就是外网 IP 与内网 IP 的一对一映射关系,所以常用在虚拟化环境中,为虚拟机分配浮动的公网 IP 地址。
二、iptables 和 NAT
Linux 内核提供的 Netfilter 框架,允许对网络数据包进行修改(比如 NAT)和过滤(比如防火墙)。在这个基础上,iptables、ip6tables、ebtables 等工具,又提供了更易用的命令行接口,以便系统管理员配置和管理 NAT、防火墙的规则。其中,iptables 就是最常用的一种配置工具。
下面,我们来看下如何在Linux服务器上配置NAT。
要实现 NAT 功能,主要是在 nat 表进行操作。而 nat 表内置了三个链:
• PREROUTING,用于路由判断前所执行的规则,比如,对接收到的数据包进行 DNAT。
• POSTROUTING,用于路由判断后所执行的规则,比如,对发送或转发的数据包进行 SNAT 或 MASQUERADE。
• OUTPUT,类似于 PREROUTING,但只处理从本机发送出去的包。
在使用 iptables 配置 NAT 规则时,Linux 需要转发来自其他 IP 的网络包,需要开启 Linux 的 IP 转发功能。
# 查看是否打开转发功能。1表示开启,0表示关闭的
root@cp1:~# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
# 临时有效
root@cp1:~# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
# 永久生效
root@cp1:~# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
root@cp1:~# sysctl -p
1、SNAT
SNAT 需要在 nat 表的 POSTROUTING 链中配置。我们常用两种方式来配置它:
第一种方法,是为一个子网统一配置 SNAT,并由 Linux 选择默认的出口 IP,这实际上就是经常说的 MASQUERADE(地址伪装,可以实现自动化的SNAT):
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j MASQUERADE
第二种方法,是为具体的 IP 地址配置 SNAT,并指定转换后的源地址:
iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100
2、DNAT
DNAT 需要在 nat 表的 PREROUTING 或者 OUTPUT 链中配置,其中, PREROUTING 链更常用一些(因为它还可以用于转发的包)。
iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2
3、双向地址转换
双向地址转换,就是同时添加 SNAT 和 DNAT 规则,为公网 IP 和内网 IP 实现一对一的映射关系,即:
iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100
iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2
三、示例
1、端口转发
# 将本机5555的端口的流量转发到本机的22上
[root@web1 ~]# iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 5555 -j DNAT --to-destination 10.0.0.7:22
[root@web1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 10.0.0.7 tcp dpt:5555 to:10.0.0.7:22
......
# 将10.0.0.8:5555的流量转发到10.0.0.7:22上
[root@m1 ~]# iptables -t nat -A PREROUTING -d 10.0.0.8 -p tcp --dport 5555 -j DNAT --to-destination 10.0.0.7:22
[root@m1 ~]# iptables -t nat -A POSTROUTING -d 10.0.0.7 -p tcp -j SNAT --to-source 10.0.0.8
[root@m1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 10.0.0.8 tcp dpt:5555 to:10.0.0.7:22
......
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT tcp -- 0.0.0.0/0 10.0.0.7 to:10.0.0.8
2、内部共享上网
环境:
web01处于内网环境,没有公网ip,其内网ip地址为172.16.1.7
web02有两块网卡,一块地址为内网172.16.1.8,一块地址为公网10.0.0.8
此时web01通过将网关指向10.0.0.8共享上网,iptables规则设置如下:
[root@web2 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf //开启内核转发参数
[root@web2 ~]# sysctl -p
[root@web2 ~]# iptables -t nat -A POSTROUTING -s 172.16.1.7 -j SNAT --to-source 172.16.1.8
[root@web2 ~]# iptables -t nat -nL
......
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 172.16.1.7 0.0.0.0/0 to:172.16.1.8
或者:
[root@web2 ~]# iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE
[root@web2 ~]# iptables -t nat -nL
......
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.16.1.0/24 0.0.0.0/0