SNAT、DNAT介绍
通过SNAT和DNAT可以使内网和外网进行相互通讯
SNAT(源地址转换):指数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样接收方就认为数据包的来源是被替换的那个IP的主机【在postrouting链】【改写数据包源地址,目的地址保持不变】
DNAT(目的地址转化):指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么实际上访问的是B。【在prerouting链】【对数据包的目的地址修改,源地址不变】
SNAT
SNAT 应用场景:
- 多台内网机器使用同一个公网IP上网
- 将服务器的源IP隐藏,改成公开的IP
1 | 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的源地址,源端口号不变
地址转换时数据包的情况:
- 若只开启路由转发,未做地址转换:
- 从局域网访问外网的数据包经过网关转发后其源IP地址保持不变。当外网中的主机收到这样的请求数据包后,响应数据包将无法正确返回,从而导致访问失败
- 开启路由转发,并设置SNAT转换:
- 局域网访问外网的数据包到达网关服务器时,会先进行路由选择。如果该数据包需要从外网接口
eth0
向外转发,则将其源IP地址修改为网关的外网接口地址,然后发送给目标主机 - 优点:外网中的服务器并不知道局域网PC机的实际IP地址,中间的转换完全由网关主机完成,起到了保护内部网络的作用
- 局域网访问外网的数据包到达网关服务器时,会先进行路由选择。如果该数据包需要从外网接口
SNAT策略的应用:
- 局域网各主机正确设置IP地址/子网掩码
- 局域网各主机正确设置默认网关地址
- Linux网关支持IP路由转发
DNAT
DNAT 应用场景:
- 端口映射:对数据包进行转发到指定的地址
- 隐藏后端服务的真实地址,用户访问公开的地址,由NAT服务进行转发
1 | iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543 |
-t nat
: 配置的是nat表,-t指定了nat表
-A POSTROUTING
:A代表的是append,增加一个PREROUTING的chain
-p tcp --dport 1233
代表的是匹配到的数据包的特征,使用tcp协议,目的端口号是1233号
-j
表示的是action,该action就是进行目标地址转换
--to-destination 127.0.0.1:6543
: IP地址改成127.0.0.1,端口号改成6543
实际应用场景
场景: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