其实所谓的snat,dnat就是对数据包的源地址和目的地址进行修改,并且保存修改前后的映射关系,并且根据需要进行还原操作。snat:出去的时候改
变原地址(snat),回来的时候改变目的地址(un_snat)dnat:进来的时候改变目的地址(dnat),出去的时候改变源地址
(un_dnat)而所谓的回环,其实同时用到了snat和dnat,例如:src 192.168.1.2(client) ,dnat
10.14.11.177(firewall),dst 192.168.2.2(http
server),添加回环规则后,从src对10.14.11.177进行请求,然后转到dst,随后进行相反操作,最后src客户端收到源为
10.14.11.177,目的为自身的数据包,因此会正确接收。过程如下:1 首先pre,进行目的地址的转换,开始:
192.168.1.2-》10.14.11.177 ,转换后:192.168.1.2 》192.168.2.2(pre)
2 然后post,进行源地址的转换,到达真正的http server;post:192.168.1.2 》192.168.2.2,转换后:10.14.11.177(post)》192.168.2.2
3 dst进行请求回复,进行pre的反操作,进行源地址的转换: 192.168.2.2》10.14.11.177,转换后:10.14.11.177(un_pre)》10.14.11.177
4 进行post的反操作,进行目的地址的转换:进入un_post:10.14.11.177》10.14.11.177,转换后:10.14.11.177》192.168.1.2(u_post)
===========================================================
iptables DNAT详解6.5.2. DNAT target
这
个target是用来做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以
被路由到正确的主机或网络。DNAT
target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个
target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随
机分配一个地址。因此,我们可以用这个target做某种类型地负载平衡。
注意,DANT target只能用在nat表的PREROUTING和OUTPUT链中,或者是被这两条链调用的链里。但还要注意的是,包含DANT target的链不能被除此之外的其他链调用,如POSTROUTING。
Table 6-16. DNAT target
Option --to-destination
Example 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或 --to-destination
192.168.1.1:80-100。SNAT的语法和这个target的一样,只是目的不同罢了。要注意,只有先用--protocol指定了TCP
或 UDP协议,才能使用端口。
因为DNAT要做很多工作,所以我要再罗嗦一点。我们通过一个例子来大致理解一下它是如何工作的。比
如,我想通过Internet连接发布我们的网站,但是HTTP
server在我们的内网里,而且我们对外只有一个合法的IP,就是防火墙那个对外的IP——$INET_IP。防火墙还有一个内网的IP——$
LAN_IP,HTTP server的IP是$HTTP_IP
(这当然是内网的了)。为了完成我们的设想,要做的第一件事就是把下面的这个简单的规则加入到nat表的PREROUTING链中:
iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP
现
在,所有从Internet来的、到防火墙的80端口去的包都会被转发(或称做被DNAT
)到在内网的HTTP服务器上。如果你在Internet上试验一下,一切正常吧。再从内网里试验一下,完全不能用吧。这其实是路由的问题。下面我们来好
好分析这个问题。为了容易阅读,我们把在外网上访问我们服务器的那台机子的IP地址记为$EXT_BOX。
包从地址为$EXT_BOX的机子出发,去往地址为$INET_IP 的机子。
包到达防火墙。
防火墙DNAT(也就是转发)这个包,而且包会经过很多其他的链检验及处理。
包离开防火墙向$HTTP_IP前进。
包到达HTTP服务器,服务器就会通过防火墙给以回应,当然,这要求把防火墙作为HTTP到达$EXT_BOX的网关。一般情况下,防火墙就是HTTP服务器的缺省网关。
防火墙再对返回包做Un-DNAT(就是照着DNAT的步骤反过来做一遍),这样就好像是防火墙自己回复了那个来自外网的请求包。
返回包好象没经过这么复杂的处理、没事一样回到$EXT_BOX。
现在,我们来考虑和HTTP服务器在同一个内网(这里是指所有机子不需要经过路由器而可以直接互相访问的网络,不是那种把服务器和客户机又分在不同子网的情况)的客户访问它时会发生什么。我们假设客户机的IP为$LAN_BOX,其他设置同上。
包离开$LAN_BOX,去往$INET_IP。
包到达防火墙。
包
被DNAT,而且还会经过其他的处理。但是包没有经过SNAT 的处理,所以包还是使用它自己的源地址,就是$LAN_BOX(译者注:这就是IP
传输包的特点,只根据目的地的不同改变目的地址,但不因传输过程中要经过很多路由器而随着路由器改变其源地址,除非你单独进行源地址的改变。其实这一步的
处理和对外来包的处理是一样的,只不过内网包的问题就在于此,所以这里交待一下原因)。
包离开防火墙,到达HTTP服务器。
HTTP服务器试图回复这个包。它在路由数据库中看到包是来自同一个网络的一台机子,因此它会把回复包直接发送到请求包的源地址(现在是回复包的目的地址),也就是$LAN_BOX。
回复包到达客户机,但它会很困惑,因为这个包不是来自它访问的那台机子。这样,它就会把这个包扔掉而去等待“真正”的回复包。
针
对这个问题有个简单的解决办法,因为这些包都要进入防火墙,而且它们都去往需要做DNAT才能到达的那个地址,所以我们只要对这些包做SNAT操作即可。
比如,我们来考虑上面的例子,如果对那些进入防火墙而且是去往地址为$HTTP_IP、端口为80的包做SNAT操作,那么这些包就好象是从$
LAN_IP来的了,也就是说,这些包的源地址被改为$LAN_IP了。这样,HTTP服务器就会把回复包发给防火墙,而防火墙会再对包做
Un-DNAT操作,并把包发送到客户机。解决问题的规则如下:
iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT \ --to-source $LAN_IP
要记住,按运行的顺序POSTROUTING链是所有链中最后一个,因此包到达这条链时,已经被做过DNAT操作了,所以我们在规则里要基于内网的地址$HTTP_IP(包的目的地)来匹配包。
警
告:我们刚才写的这条规则会对日志产生很大影响,这种影响应该说是很不好的。因为来自
Internet包在防火墙内先后经过了DNAT和SNAT处理,才能到达HTTP服务器(上面的例子),所以HTTP服务器就认为包是防火墙发来的,而
不知道真正的源头是其他的IP。这样,当它记录服务情况时,所有访问记录的源地址都是防火墙的IP而不是真正的访问源。我们如果想根据这些记录来了解访问
情况就不可能了。因此上面提供的“简单办法”并不是一个明智的选择,但它确实可以解决“能够访问”的问题,只是没有考虑到日志而已。
其他的服务也有类似的问题。比如,你在LAN内建立了SMTP服务器,那你就要设置防火墙以便能转发SMTP的数据流。这样你就创建了一个开放的SMTP中继服务器,随之而来的就是日志的问题了。
一
定要注意,这里所说的问题只是针对没有建立DMZ或类似结构的网络,并且内网的用户访问的是服务器的外网地址而言的。(译者注:因为如果建立了DMZ,或
者服务器和客户机又被分在不同的子网里,那就不需要这么麻烦了。因为所有访问的源头都不在服务器所在的网里,所以就没必要做SNAT去改变包的源地址了,
从而记录也就不是问题了。如果内网客户是直接访问服务器的内网地址那就更没事了)
较好的解决办法是为你的LAN在内网建立一台单独的
DNS服务器(译者注:这样,内网的客户使用网站名访问HTTP服务器时,DNS就可以把它解析成内网地址。客户机就可以直接去访问HTTP服务器的内网
地址了,从而避免了通过防火墙的操作,而且包的源地址也可以被HTTP服务器的日志使用,也就没有上面说的日志问题了。),或者干脆建立DMZ得了(这是
最好的办法,但你要有钱哦,因为用的设备多啊)。
对上面的例子应该考虑再全面些,现在还有一个问题没解决,就是防火墙自己要
访问HTTP服务器时会发生什么,能正常访问吗?你觉得呢:)很可惜,现在的配置还是不行,仔细想想就明白了。我们这里讨论的基础都是假设机子访问的是
HTTP服务器的外网地址,但这个外网地址其实就是防火墙对外的地址,所以当防火墙访问这个外网地址时,就是访问它自己。防火墙上如果有HTTP服务,那
客户机就会看到页面内容,不过这不是它想看到的(它想要的在DNAT上了),如果没有HTTP服务,客户就只能收到错误信息了。前面给出的规则之所以不起
作用是因为从防火墙发出的请求包不会经过那两条链。还记得防火墙自己发出的包经过哪些链吧:)我们要在nat表的OUTPUT链中添加下面的规则:
iptables -t nat -A OUTPUT --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP
有
了最后这条规则,一切都正常了。和HTTP服务器不在同一个网的机子能正常访问服务了,和它在一个网内的机子也可以正常访问服务了,防火墙本身也能正常访
问服务了,没有什么问题了。这种心情,套用《大话西游》里的一句话,就是“世界又清净了”。(不要说你不知道什么是《大话西游》)
我
想大家应该能明白这些规则只说明了数据包是如何恰当地被DNAT和SNAT的。除此之外,在
filter表中还需要其他的规则(在FORWARD链里),以允许特定的包也能经过前面写的(在POSTROUTING链和
OUTPUT链里的)规则。千万不要忘了,那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了,也就是说它们的目的地址已被
改写,在写规则时要注意这一点。
========================================================
DNAT的真正用法
可
以说是拍脑瓜子想到的,我不知道别人本来就是做对的,但是google上似乎从来都是用DNAT和SNAT配合来实现端口转发功能。首先用DNAT来修改
包的目的地址,然后用SNAT修改源地址,两者结合来显示最终的端口转发。然而这样做有一个弊病,包到达最终主机时,来源IP都只有一个,无法对来源的真
是IP进行判断,因为都被SNAT修改了。今天突然想到,既然内网的机器最后还是通过网关路由到外网,那么为什么一定要做SNAT来实现端口转发呢,如果
不做SNAT,那么来源IP是外网的IP,但是到达最终主机后,最终主机会通过路由把返回包发回网关,再由网关来伪装IP路由到外网。
其
实最大的毛病就是,一般网关都会做代理路由服务,即SNAT,也就是一般说到多机上网,那么nat表POSTROUTING链里必然有SNAT规则,如果
不对POSTROUTING链做特殊端口的接受(ACCEPT)或者跳过(RETURN)处理,那么自然包会最终被伪装成网关的IP,而把原来的外网IP
覆盖。
所需做的就是在原来的DNAT基础上,不作SNAT,或者跳过将要做的SNAT即可。
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 12345 -j DNAT --to-destination 1.2.3.4:23456
iptables -t nat -I POSTROUTING -d 1.2.3.4 -p tcp --dport 23456 -o eth0 -j RETURN
阅读(4673) | 评论(1) | 转发(0) |