SNAT、DNAT介绍

通过SNAT和DNAT可以使内网和外网进行相互通讯

SNAT(源地址转换):指数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样接收方就认为数据包的来源是被替换的那个IP的主机【在postrouting链】【改写数据包源地址,目的地址保持不变】

DNAT(目的地址转化):指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么实际上访问的是B。【在prerouting链】【对数据包的目的地址修改,源地址不变】

SNAT

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的源地址,源端口号不变


地址转换时数据包的情况:

  • 若只开启路由转发,未做地址转换:
    • 从局域网访问外网的数据包经过网关转发后其源IP地址保持不变。当外网中的主机收到这样的请求数据包后,响应数据包将无法正确返回,从而导致访问失败
  • 开启路由转发,并设置SNAT转换:
    • 局域网访问外网的数据包到达网关服务器时,会先进行路由选择。如果该数据包需要从外网接口eth0 向外转发,则将其源IP地址修改为网关的外网接口地址,然后发送给目标主机
    • 优点:外网中的服务器并不知道局域网PC机的实际IP地址,中间的转换完全由网关主机完成,起到了保护内部网络的作用

SNAT策略的应用:

  • 局域网各主机正确设置IP地址/子网掩码
  • 局域网各主机正确设置默认网关地址
  • Linux网关支持IP路由转发

DNAT

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 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的映射。

模拟:

  1. step1: Server A执行 nc -l -p 6543 监听本地的6543端口
  2. step2: Server A执行 iptables -t nat -A PREROUTING -p tcp --dport 1233 -j DNAT --to-destination 127.0.0.1:6543 进行地址映射
  3. step3: 在Clinet 所在的机器访问Server A的1233端口,假设Server A的公网IP是22.23.34.1,nc 22.23.34.1 1233
  4. step4: 在Client建立连接后,输入几个字符,在Server A监听的6543端口上有显示即可。

解决方案2:

  1. 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端口去,一定要是本地访问本地的时候才行。


  1. 使用上述的NAT功能前,一定要先开启linux nat转发的功能:echo 1 > /proc/sys/net/ipv4/ip_forward ,重启后失效,如果需要重启后还开启,需要写到/etc/rc.local中去
  2. 上述提到的场景,可扩展为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

参考文章

使用iptables配置NAT

iptables防火墙的应用和SNAT/DNAT策略

评论