网络-SNAT和DNAT[转]

阅读量: zyh 2021-12-26 15:20:01
Categories: > Tags:

DNAT(Destination Network Address Translation,目的地址转换) 通常被叫做目的映谢。

而SNAT(Source Network Address Translation,源地址转换)通常被叫做源映谢。

这是我们在设置Linux网关或者防火墙时经常要用来的两种方式。

IP包的结构

image-20211226154016611

在任何一个IP数据包中,都会有Source IP Address与Destination IP Address这两个字段,数据包所经过的路由器也是根据这两个字段是判定数据包是由什么地方发过来的,它要将数据包发到什么地方去。而iptables的DNAT与SNAT就是根据这个原理,对Source IP Address与Destination IP Address进行修改。

iptables数据流

image-20211226154032075

正菱形的区域是对数据包进行判定转发的地方。在这里,系统会根据IP数据包中的DIP对数据包进行分发。如果destination ip adress是本机地址,数据将会被转交给INPUT链。如果不是本机地址,则交给FORWARD链检测。

✨【DNAT】是在【PREROUTING链】中进行。

比如我们要把访问202.103.96.112的访问转发到192.168.0.112上:

iptables -t nat -A PREROUTING -d 202.103.96.112 -j DNAT --to-destination 192.168.0.112

其实就是将已经达到这台Linux网关上的数据包上的 DIP:202.103.96.112 修改为 SERVER_IP:192.168.0.112 然后交给系统路由进行转发。

✨【SNAT】是在【POSTROUTING链】中进行。

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to-source 58.20.51.66

这个语句就是告诉系统把即将要流出本机的数据的SIP修改成为58.20.51.66。这样,数据包在达到目的机器以后,目的机器会将包返回到58.20.51.66也就是本机。如果不做这个操作,那么你的数据包在传递的过程中,reply的包肯定会丢失。

注意,DNAT target只能用在nat表的PREOUTING 和 OUTPUT 链中,或者是被这两条链调用的链里。但还要注意的是,包含DNAT target的连不能被除此之外的其他链调用,如POSTROUTING。

iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10

Explanation指定要写入IP头的地址,这也是包要被转发到的地方。上面的例子就是把所有发往地址15.45.23.67的包都转发到一段LAN使用的私有地址中,即192.168.1.1到192.168.1.10。如前所述,在这种情况下,每个流都会被随机分配一个要转发到的地址,但同一个流总是使用同一个地址。我们也可以只指定一个IP地址作为参数,这样所有包都被转发到同一台机子。我们还可以在地址后指定一个或一个范围的端口。比如:–to-destination 192.168.1.1:80或192.168.1.1:80-100。SNAT的语法和这个target的一样,只是目的不同罢了。要注意,只有先用–protocol指定了TCP或UDP协议,才能使用端口。

DNAT的应用:网站发布

防火墙:

WEB服务器:

NAT表的PREROUTING链中添加DNAT规则:

iptables -t nat -A PREROUTING --dst$GW_INET_IP -p tcp --dport 80 -j DNAT / --to-destination $HTTP_LAN_IP

以上规则可以满足,外网客户端通过$GW_WAN_IP访问内网WEB服务器,但内网客户端无法通过$GW_WAN_IP访问WEB服务器。

外网客户端可以通过$GW_WAN_IP访问的原因

外网上访问我们服务器的那台机子的IP地址记为$EXT_CLIENT:

  1. 包从地址为$EXT_CLIENT的机子出发,去往地址为$GW_WAN_IP的机子。

  2. 包到达防火墙。防火墙DNAT(也就是转发)这个包,而且包会经过很多其他的链检验及处理。

  3. 包离开防火墙向$HTTP_LAN_IP前进。包到达HTTP服务器,服务器就会通过防火墙给以回应,当然,这要求把防火墙作为HTTP到达$EXT_CLIENT的网关。一般情况下,防火墙就是HTTP服务器的缺省网关。

  4. 防火墙再对返回包做Un-DNAT(就是照着DNAT的步骤反过来做一遍),这样就好像是防火墙自己回复了那个来自外网的请求包。返回包回到$EXT_CLIENT。

内网客户端无法通过$GW_WAN_IP访问的原因

假设客户机的IP为$LAN_CLIENT,其他设置同上:

  1. 包离开$LAN_CLIENT,去往$GW_WAN_IP。

  2. 包到达防火墙。包被DNAT,而且还会经过其他的处理。此时数据包SIP是:$LAN_CLIENT,DIP是:$HTTP_LAN_IP

  3. 包离开防火墙,到达HTTP服务器。HTTP服务器试图回复这个包,它在看到包是来自同一个网络的一台机子,因此它会把回复包直接发送到$LAN_CLIENT。此时回复包SIP是:$GW_WAN_IP,DIP是:$HTTP_LAN_IP

  4. 回复包到达客户机,但客户端发现恢复包的SIP不是当初请求的$GW_WAN_IP。这样,它就会把这个包扔掉而去等待“真正”的回复包。

内网客户端无法通过$GW_WAN_IP访问的解决办法

针对请求包添加SNAT规则

iptables -t -nat -A POSTROUTING -p tcp --dst$HTTP_LAN_IP --dport 80 -j SNAT / --to-source $GW_LAN_IP

✨按运行的顺序POSTROUTING链是所有链中最后一个,因此包到达这条链时,已经被做过DNAT操作了,所以我们在规则里要基于内网的地址$HTTP_LAN_IP(包的目的地)来匹配包。

☣ 这种方式,会导致WEB服务器的请求日志的源IP都是$GW_LAN_IP。因为来自Internet包在防火墙内先后经过了DNAT和SNAT处理,才能到达HTTP服务器,所以HTTP服务器就认为包是防火墙发来的,而不知道真正的源头是其他的IP。

DNS服务

通过单独的DNS服务器,内网客户使用网站域名访问HTTP服务器时,DNS将域名解析成内网地址。客户机就可以直接去访问HTTP服务器的内网地址了,从而避免了通过防火墙的操作。

DMZ区域

通过构建DMZ区域,将WEB服务器和客户端内网进行分离。

防火墙通过$GW_WAN_IP访问

从防火墙发出的请求包不会经过PREROUTING和POSTROUTING,而是经过OUTPUT。 我们要在nat表的OUTPUT链中添加下面的规则:

iptables -t nat -A OUTPUT --dst $GW_INET_IP -p tcp --dport 80 -j DNAT / --to-destination $HTTP_LAN_IP