星期三, 七月 04, 2007

prev: iptables DNAT/SNAT 的概念问题

先看下面的脚本:
#!/bin/bash
# [/usr/local/sbin/]ipt08_nat_DS.sh

/sbin/modprobe ipt_MASQUERADE
/sbin/modprobe iptable_nat
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp

iptables -F
iptables -t nat -F

# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE # [5]
echo 1 > /proc/sys/net/ipv4/ip_forward

inet=220.168.98.221
ihttpd=192.168.0.2

iptables -t nat -A PREROUTING -d $inet -p tcp --dport 80 -j DNAT --to-destination $ihttpd # [1]
iptables -t nat -A POSTROUTING -s $ihttpd -p tcp --sport 80 -j SNAT --to-source $inet # [2]
iptables -t nat -A POSTROUTING -d $ihttpd -p tcp --dport 80 -j SNAT --to-source $inet # [3]
iptables -t nat -A OUTPUT -d $inet -p tcp --dport 80 -j DNAT --to-destination $ihttpd # [4]


iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -i lo -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! ppp0 -j ACCEPT

iptables -A INPUT -p tcp --dport 3313 -j ACCEPT # FOR: skype
iptables -A INPUT -j REJECT

iptables -A OUTPUT -j ACCEPT

iptables -A FORWARD -j ACCEPT
[1] 定义了外部的主机访问内部 http 服务器的目标地址转换规则,而 [2] 定义了该服务器的源地址转换规则。我之前一直认为有 [1] 就必须有 [2],两者必须匹配。但实际情况是,只需要有 [1],就可以让外部主机正常访问内部飞的服务器了!这是因为,当服务器响应了 iptables 所在的网关主机后,报文到达防火墙,iptables 会根据 DNAT 规则自动做 r-DNAT 操作(照着DNAT的步骤反过来做一遍),所以不再需要 SNAT 了。事实上,只要考虑一下 MASQUERADE 的工作,就可以明白──你只需要定义一个相当于 SNAT 的 转换,而不需要反过来做一次。

[2] 的作用,就是对 server 回复的报文改装源地址,从而可以对 Internet 隐藏内部网络的真实组成情况。注意,在防火墙上用 tcpdump 嗅探不会发现源地址进行了改变,因为从 server 到防火墙的报文只会经过 PREROUTING 和 INPUT 链,而 SNAT 必须到 POSTROUTING 链才生效。

设置了 [1] 后,在内部网络和防火墙主机上使用 $inet 访问服务器,会被拒绝!为什么呢?

先来看本地网络的情况:本地 $local 发送的到 $ihttpd(http server)的请求报文,因为使用 $inet,所以会经过防火墙,于是做 DNAT 操作,但没有做 SNAT 把源地址转换成防火墙的地址。http server 接到这个请求,发现源地址就在本地网络,于是把回复包直接发送到请求包的源地址 $local。

客户机 $local 接到回复报文,但它会感到“困惑”,因为它并没有向 $ihttpd 发送报文,它只好把这个包 DROP 掉,再去等待从防火墙主机 $inet 返回的“真正”的回复包,只是这个回复永远不会到达。

[3] 就是为了解决这个问题。当然,如果内部网络的主机直接使用 $ihttpd 访问 http server,就不会有上面的问题。

对于防火墙主机本身,直接用 $inet 访问 http server,也会被拒绝,因为本地产生的报文不会经过 nat 的 PREROUTING 链,而直接从 nat 的 OUTPUT 链出去,所以 [1] 定义的 DNAT 没有作用,所以,对本地报文,OUTPUT 链相当域 PREROUTING 链。

没有评论: