一、SNAT 和 DNAT是什么
本文使用的是操作系统是Linux,配置工具是iptables。
相关概念的描述
1. Source NAT (SNAT)
源地址转换,改写数据包的源地址, 目的地址保持不变。常使用的场景有:
- 多台内网机器使用同一个公网IP上网的
- 将服务器的源IP隐藏,改成公开的IP
配置的命令:iptables -t nat -A POSTROUTING -p tcp --dport 1233 -j SNAT --to 192.168.0.1
命令详解如下:
-t nat : 配置的是nat表,-t指定了nat表
-A POSTROUTING:A代表的是append,增加一个POSTROUTING的chain
-p tcp --dport 1233 代表的是匹配到的数据包的特征,使用tcp协议,目的端口号是1233号
-j 表示的是action,该action就是进行源地址转换
--to 192.168.0.1转换成192.168.0.1的源地址,源端口号不变
2. Destination NAT (DNAT) 目的地址转化,对数据包的目的地址进行修改,其源地址保持不变。常使用的场景:
- 端口映射,对数据包进行转发到指定的地址
- 隐藏后端服务的真实地址,用户访问公开的地址,由NAT服务进行转发
配置的命令:iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543
命令详解如下:
-t nat : 配置的是nat表,
-t指定了nat表
-A PREROUTING:A代表的是append,添加一个PREROUTING的chain
-p tcp --dport 1233 代表的是匹配到的数据包的特征,使用tcp协议,目的端口号是1233号
-j 表示的是action,DNAT就是进行目的地址转换
--to-destination 127.0.0.1:6543: IP地址改成127.0.0.1,端口号改成6543
补充: SNAT 要在POSTROUTING链添加, DNAT需要再PREROUTING链添加。关于POSTROUTING和PREROUTING的区别,以及iptables的相关原理会在后面文章中详述。
二、 实际应用场景
上面对SNAT和DNAT的原理以及命令配置做了简单的描述,各位可能还不知道NAT的在工作中可以应用的场景。以下列举实际工作中会遇到的场景。
场景: Server A 运行着一个服务s1,只开放的本地地址连接,开放的端口号是6543。即Server A的服务s1监听的端口是127.0.0.1:6543。本地客户端Client想连接到服务s1去,这时可以修改s1的配置文件,让其监听所有的地址。也可以使用iptables配置NAT,使得可以访问6543的端口。
解决方案1:在Server A中执行iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543,让连接到Server A的1233的端口转发到本地的6543端口上去,完成了NAT的映射。
模拟操作步骤:
- step1: Server A执行
nc -l -p 6543监听本地的6543端口 - step2: Server A执行
iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543进行地址映射 - step3: 在Clinet 所在的机器访问Server A的1233端口,假设Server A的公网IP是22.23.34.1,
nc 22.23.34.1 1233 - step4: 在Client建立连接后,输入几个字符,在Server A监听的6543端口上有显示即可。
解决方案2:
iptables -t nat -A PREROUTING -p tcp --dport 5000 -j REDIRECT --to-ports 6543
使用REDIRECT的action,直接将Server A的5000端口数据转发到本地的6543端口中去。
上述提到的两个解决方案,在本地验证是通过不了的。即Server A和Client 都是同一台机器,因为使用lo网卡的时候,是没有PREROUTING这个阶段的,如果一定要在本地进行NAT的验证。可以使用此命令:iptables -t nat -I OUTPUT -p tcp -o lo --dport 1232 -j REDIRECT --to-ports 6543 。此命令是设置了,lo网卡的数据包的目的端口是1232的时候,转发到6543端口去。使用的是OUTPUT,因此从外部访问Server A的1232端口的话,不会转发的6543端口去,一定要是本地访问本地的时候才行。
##三、 后记
- 使用上述的NAT功能前,一定要先开启linux nat转发的功能:
echo 1 > /proc/sys/net/ipv4/ip_forward,重启后失效,如果需要重启后还开启,需要写到/etc/rc.local中去 - 上述提到的场景,可扩展为Server A的1233端口,转发到Server B(假设地址是8.8.8.8)的6543端口中去,Server A的角色是一个跳板,只要修改一下命令:把
iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543改成iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 8.8.8.8:6543