LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: ttyrone

用iptables发布内部服务的问题

[复制链接]
 楼主| 发表于 2005-5-24 15:01:14 | 显示全部楼层
是不是应该加条forward的规则呢?
晕4了
回复 支持 反对

使用道具 举报

发表于 2005-5-24 18:13:36 | 显示全部楼层
$IPT -t nat -A POSTROUTING -o $inet_iface -j SNAT --to $inet_ip
我所看到的资料上没有 --to $inet_ip 部分。我认为可以这样想,你的一个客户端发出的报文被重定向到 $inet_ip,但却得不到回复的报文,所以你看不到效果(我想你应该是在自己的内部网络上测试的吧)。把 --to $inet_ip 部分去掉试试,也可以在网关上试试。

记得要正确配置路由,如果用域名不行,先用 IP 试试,也许是 DNS 的问题呢。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-27 12:35:41 | 显示全部楼层
我晕,是http服务器的问题,规则没问题

多谢chowroc
回复 支持 反对

使用道具 举报

发表于 2005-5-27 14:08:17 | 显示全部楼层
是到哪一步的规则没有问题?我也想知道得更清楚一点,所谓互相交流麻。--to $inet_ip 没有问题吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-31 08:35:24 | 显示全部楼层
这是完整的脚本,最好用这个脚本,进行简化后,发布的web,论坛进不去,图片也打不开
#!/bin/bash
echo "Starting Iptables Rules..."
echo "1" > /proc/sys/net/ipv4/ip_forward
inet_iface="eth1"
inet_ip="218.107.130.52"
lan_iface="eth0"
lan_ip="192.168.35.1"
lan_ip_range="192.18.35.0/24"
ipt="/sbin/iptables"

http_server="192.168.35.7"
http="80"
sql_server="192.168.35.201"
sql="1433"
ftp_server="192.168.35.7"
ftp="21"

/sbin/depmod -a
/sbin/modprobe ip_tables
/sbin/modprobe iptable_nat
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ipt_LOG


$ipt -P INPUT ACCEPT
$ipt -P FORWARD ACCEPT
$ipt -P OUTPUT ACCEPT
$ipt -t nat -P PREROUTING ACCEPT
$ipt -t nat -P POSTROUTING ACCEPT
$ipt -t nat -P OUTPUT ACCEPT

for TABLE in filter nat mangle ; do
$ipt -t $TABLE -F
$ipt -t $TABLE -X
done

$ipt -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
for DNS in $(grep ^n /etc/resolv.conf|awk '{print $2}') ; do
$ipt -A INPUT -p udp -s $DNS --sport domain -j ACCEPT
done

#$ipt -N LOGDENY
#$ipt -A LOGDENY -j LOG --log-prefix "iptables:"
#$ipt -A LOGDENY -j DROP
#$ipt -A INPUT -i ! lo -m state --state NEW,INVALID -j LOGDENY

#共享上网
$ipt -t nat -A POSTROUTING -o $inet_iface -j SNAT --to $inet_ip

#发布内部http服务器给外网用户
$ipt -t nat -A PREROUTING --dst $inet_ip -p tcp --dport $http -j DNAT --to-destination

$http_server
#发布内部http服务器给内网用户
$ipt -t nat -A POSTROUTING -p tcp --dst $http_server --dport $http -j SNAT --to-source

$lan_ip
#发布内部http服务器给iptables服务器本身
$ipt -t nat -A OUTPUT --dst $inet_ip -p tcp --dport $http -j DNAT --to-destination

$http_server

$ipt -t nat -A PREROUTING --dst $inet_ip -p tcp --dport $sql -j DNAT --to-destination

$sql_server
$ipt -t nat -A POSTROUTING -p tcp --dst $sql_server --dport $sql -j SNAT --to-source $lan_ip

$ipt -t nat -A PREROUTING --dst $inet_ip -p tcp --dport $ftp -j DNAT --to-destination

$ftp_server
$ipt -t nat -A POSTROUTING -p tcp --dst $ftp_server --dport $ftp -j SNAT --to-source $lan_ip
$ipt -t nat -A OUTPUT --dst $inet_ip -p tcp --dport $ftp -j DNAT --to-destination

$ftp_server

echo "done"
回复 支持 反对

使用道具 举报

发表于 2005-5-31 15:39:14 | 显示全部楼层
有几个问题:

  1. #发布内部http服务器给外网用户
  2. $ipt -t nat -A PREROUTING --dst $inet_ip -p tcp --dport $http -j DNAT --to-destination $http_server
  3. #发布内部http服务器给内网用户
  4. $ipt -t nat -A POSTROUTING -p tcp --dst $http_server --dport $http -j SNAT --to-source $lan_ip
  5. #发布内部http服务器给iptables服务器本身
  6. $ipt -t nat -A OUTPUT --dst $inet_ip -p tcp --dport $http -j DNAT --to-destination $http_server
复制代码


首先,那个 OUTPUT 链是否有必要?http 的报文并不是从本地产生的呀。

你说第二句是发布给内网用户,这样说似乎不妥,我觉得还是发给外网的呀,因为 $lan_ip 是网关的局域网地址呀。我觉得应该是:第一句使外部请求可以到达,第二句使内部响应可以发出。

因为我自己只有一块网卡,所以做共享的时候用 MASQUERADE,在测试时我也用过 SNAT,因为是单网卡,所以用 $inet_ip 这样的值,而你的情况是双网卡,所以在第二句使用 $lan_ip。不知道如果你使用 $inet_ip 是不是也可以?
回复 支持 反对

使用道具 举报

发表于 2005-5-31 15:59:07 | 显示全部楼层
另外,iptables 到底是怎样工作的,数据报文的流入、流出的路线到底是怎样的?我其实还是有些不甚了了。

《Linux 系统安全──开发源码安全工具管理员指南》(Scott Mann, Ellen L. Mitchell, Mitchell Krell 著,电子工业出版社) 指出了报文通过各个表和链的情况,但并没有说明接口的问题──比如说,一个接口和两个接口有什么区别?

我曾经考虑报文的流入流出的实际路线应该是:
LAN ---> eth0(PREROUTING) ---> 路由算法 ---> eth0(FORWARD) ---> eth0(POSTROUTING) ---> ppp0(PREROUTING) ---> ppp0(FORWARD) ---> ppp0(POSTROUTING: NAT) ---> Internet

LAN <--- eth0(POSTROUTING) <--- eth0(FORWARD) <--- eth0(PREROUTING) <--- ppp0(POSTROUTING) <--- ppp0(FORWARD) <--- 路由算法 <--- ppp0(PREROUTING) <--- Internet

于是,写了一个脚本:

  1. #!/bin/bash

  2. iptables -F

  3. /sbin/modprobe ipt_MASQUERADE
  4. /sbin/modprobe iptable_nat
  5. /sbin/modprobe ipt_LOG
  6. /sbin/modprobe ip_conntrack

  7. # iptables -P INPUT -j ACCEPT
  8. # iptables -P FORWARD -j ACCEPT
  9. # iptables -P OUTPUT -j ACCEPT

  10. iptables -t nat -A PREROUTING -i eth0 -j LOG --log-level 0 --log-prefix "PREROUTING_i_eth0: "
  11. # iptables -t nat -A PREROUTING -o eth0 -j LOG --log-prefix "PREROUTING_o_eth0: "
  12. iptables -A FORWARD -i eth0 -j LOG --log-level 0 --log-prefix "FORWARD_i_eth0: "
  13. iptables -A FORWARD -o eth0 -j LOG --log-level 0 --log-prefix "FORWARD_o_eth0: "
  14. # iptables -t nat -A POSTROUTING -i eth0 -j LOG --log-prefix "POSTROUTING_i_eth0: "
  15. iptables -t nat -A POSTROUTING -o eth0 -j LOG --log-level 0 --log-prefix "POSTROUTING_o_eth0: "

  16. iptables -t nat -A PREROUTING -i ppp0 -j LOG --log-level 0 --log-prefix "PREROUTING_i_ppp0: "
  17. # iptables -t nat -A PREROUTING -o ppp0 -j LOG --log-prefix "PREROUTING_0_ppp0: "
  18. iptables -A FORWARD -i ppp0 -j LOG --log-level 0 --log-prefix "FORWARD_i_ppp0: "
  19. iptables -A FORWARD -o ppp0 -j LOG --log-level 0 --log-prefix "FORWARD_o_ppp0: "
  20. # iptables -t nat -A POSTROUTING -i ppp0 -j LOG --log-prefix "POSTROUTING_i_ppp0: "
  21. iptables -t nat -A POSTROUTING -o ppp0 -j LOG --log-level 0 --log-prefix "POSTROUTING_o_ppp0: "
  22. iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
  23. echo 1 > /proc/sys/net/ipv4/ip_forward

  24. iptables -A INPUT -j ACCEPT
  25. iptables -A FORWARD -j ACCEPT
  26. iptables -A OUTPUT -j ACCEPT
复制代码


通过查看 message 文件中的记录,我的结论是,使用 eth0 + ppp0 的 ADSL 共享上网,内网请求 Internet 服务,经过:
LAN ---> eth0(PREROUTING) ---> 路由算法 ---> eth0(FORWARD) ---> ppp0(FORWARD) ---> ppp0(POSTROUTING: NAT) ---> Internet
没有eth0(POSTROUTING) 和 ppp0(PREROUTING) 的环节。

而 Internet 服务返回的数据,只经过 eth0(FORWARD) 和 ppp0(FORWARDE)──我通过看到的记录只能得出这样的结论。

我知道:ppp0 是2063端口,eth0 是1027端口,当目的端口是2063的数据包从 Internet 返回时,Linux 知道要将该包重新传递到 eth0,并将其发送到原始客户机。

但是,为什么返回流入的数据没有经过 PREROUTING 和 POSTROUTING。如果是外部请求的本地服务又会是怎样的情况呢?

也不知道两块网卡共享上网的情况?

比如 ttyrone 兄自定义了一个链 LOGDENY,然后 INPUT 的一个规则跳转到这个链,那么如果我最后在增加:
iptables -A INPUT -j DROP
还会不会对这个已经跳转的规则起作用呢?这个我后面再试试。不过如果概念问题不弄清楚,就始终是知其然而不知其所以然,遇到新情况就不知道怎么变通了。
回复 支持 反对

使用道具 举报

发表于 2005-5-31 15:59:20 | 显示全部楼层
发重了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-31 16:37:14 | 显示全部楼层
我是看的iptables指南
http://iptables-tutorial.frozent ... rial-cn-1.1.19.html
其中提到
因为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
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-31 16:38:32 | 显示全部楼层
对上面的例子应该考虑再全面些,现在还有一个问题没解决,就是防火墙自己要访问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服务器不在同一个网的机子能正常访问服务了,和它在一个网内的机子也可以正常访问服务了,防火墙本身也能正常访问服务了,没有什么问题了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表