iptables历险记

背景

这几天在做开发联调的时候,出现了这样一种情况:我的应用本身开启的是24100端口,但别的应用却是调用我的80的端口。

本来我把端口重新配置一下,编译重启应用就OK的事情。但想想UED还在用我的24100端口,真是个棘手的事情。

由于时间紧急,所以就弄了一个最简单的方案:把 httpd 停掉,在配置文件中新增一个80端口的监听,重启 httpd。

事后想想,看有没有别的方法解决此问题,后来想了想,还有两种解决方案:

  1. 再新启一个httpd,监听80端口,并且在80端口做一个代理
  2. 使用 iptables 把端口从80 透明的改成 24100

由于第二种方案从来没有试过,之前对 iptables 也只是听说过,所以决定便决定研究一下。

iptables是什么

之前隐隐约约知道iptables是一个防火墙,到防火墙到底是个什么东西,能做什么,iptables又是怎么会是,我还是一知半解的。

借着这个机会,也简单的查找了一下:

写道
iptabels应用程序,被认为是Linux中实现包过滤功能的第四代应用程序。
iptables包含在 2.4以后的内核中,它可以实现防火墙、NAT(网络地址翻译)和数据包的分割等功能。
 

说白了, iptables还不仅仅是个简单的防火墙,他还能进行NAT和数据包的分割。

iptables的工作机制

如下图:这是从51cto找到的图。

  • iptables是由表,链,规则,目标组成,每个表中有几条链,每条链有几条规则,每条规则如果被匹配,这可以指定到特定目标
  • iptables默认有三个表,分别是: mangle, nat, filter
  • mangle 默认有5条链,分别是: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
  • nat 默认有3条链,分别是:PREROUTING,  OUTPUT, POSTROUTING
  • filter默认有3条链,分别是: INPUT, FORWARD, OUTPUT

一个网络包在iptables旅游的过程:

  • 当一个包在网络中被网卡接受到的时候,会先经过iptables的mangle表的PREROUTING链
  • 然后再经过nat表的PREROUTING链
  • 然后经过路由判断,该包是进行转发,还是接受到本机。
  • 如果是转发,则经过 mangle表的FORWARD链,再经过 filter 表的 FORWARD 链,最后再经过 mangle表的 POSTROUTING链和nat的POSTROUTING链。
  • 如果不转发,则进入本机,再进入本机之前,要经过 filter表的INPUT链,和mangle的INPUT链。经过本机处理后,再进入 mangle,nat,filter表中的OUTPUT链(注意表的顺序)
  • 然后再路由该包,最后经过 mangle和nat的 POSTROUTING链条

有了上边的图和解释,对iptables就应该有大致的理解了:)

解决最初的问题

有了以上的概念,要解决最初的问题,就知道我们大概要在哪里“做手脚”了。呵呵

就是在 nat表的PREROUTING中加上一个规则,如果端口是80的话,就对该包做端口转发,就是把目标端口改为24100。

具体的命令如下:

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 24100

其中:

  • -t nat 指定表为nat
  • -A PREROUTING 是在PREROUTING中append一条规则
  • -p tcp 匹配tcp协议
  • --dport 80  表示匹配目标端口为80
  • -j REDIRECT 表示跳转(jump)到 REDIRECT这个目标,REDIRECT所作的事情,就是把做端口转向
  • --to-ports 24100 则是把端口号转到24100上

这样,在内网上的其他机器,使用80端口访问我应用的时候,就会被指向到24100这个端口上。

同时,iptables还是很聪明的把响应回来的包也相应做一次转换。

新的问题

虽然这解决内网上不同机器能够访问我的80端口,但我自己的机器却不能访问80端口,很郁闷……

在CU论坛上问了一下,发现时本机机器访问本地机器时,是不走PREROUTING的……

怪不得,连这条链都没有经过,怎么会做端口转发呢。

解决思路

取巧使用了如下方法:

  • 本地访问另外一个局域网IP,80端口。
  • 在iptables的nat表OUTPUT链中作DNAT转换,让目的IP变成本机IP,并且端口有80变成24100端口

命令如下:

iptables -t nat -A OUTPUT -p tcp -d 10.19.14.129 --dport 80 -j DNAT -to 10.19.14.128:24100

其中 10.19.14.129是其他内网IP, 10.19.14.128是本机IP。

经过实验,问题总算是解决了。

心得

linux系统中的工具真是强大,只有想不到,没有做不到。

附上iptables的一个学习网址:

猜你喜欢

转载自zavakid.iteye.com/blog/898559