LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 4607|回复: 14

用iptables设置有状态防火墙

[复制链接]
发表于 2005-10-15 08:58:17 | 显示全部楼层 |阅读模式
如果你是新手,请先看我写的《用iptables设置静太防火墙》 ,本文在此基础上写的,很多细节上的问题用它作参考。


########################

版权所有,转载请注明来自www.linuxsir.cn 并写明作者

########################

在这里我必须要解释一下防火墙的状态(state)

比如,你用ssh远程访问,你的主机和远程主机会进行通信。
静态的防火墙会这样处理:
检查时入机器的数据包,发现数据是来源是22端口,当允许时入,连接之后相互通信的数据也一样,检查每个数据,发现数据来源于22端口,允许通过!

如果用有状态的防火墙如何处理呢?
当你连接远程主机成功之后,你的主机会把这个连接记录下来,当有数据从远程ssh服务器再进入你的机器时
检查自己连接状态表,发现这个数据来源于一个已经建立的连接,允许这个数据包进入。

以上两种处理,我们明显的发现static firewall比较生硬,而有状态的防火墙则显得要智能一些!

现在我们来解释一下状态
NEW:如果你的主机向远程机器发时一个连接请求,这个数据包状态是NEW.
ESTABLISHED:当联接建立之后,远程主机和你主机通信数据状态为ESTABLISHED
RELATED: 像ftp这样的服务,用21端口传送命令,而用20端口(port模式)或其他端口(PASV模式)传送数据。在已有21端口上建立好连接后发送命令,用20传送的数据,状态是RELATED

有了以上知识后,接下来时行我们的step by step 吧
首先,我们还是来设置默认规则
iptables -P INPUT DROP
这样你的机器将对所有进入你主机的数据都丢弃

如果你有一台主机只是用于个人桌面应用,那么你的主机不提供任何服务,那么,我们就禁止其他的机器向你的机器发送任何连接请求
iptables -A INPUT -m state --state NEW -j DROP

这个规则将所有发送到你的机器数据包,状态是NEW的包丢弃。这样,也就是不允许其他的机器主动发起对你机器的连接,但是你却可以主动的连接其他的机器,不过仅仅只是连接而已,连接之后的数据就是ESTABLISHED状态的了,我们再加上一条。

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
所有已经建立联接,或者与之相关的数据允许通过


好了,们们来总结一下三条语句,因为它是一个很好的个人桌面主机的防火墙。
iptables -P INPUT DROP
#iptables -A INPUT -m state --state NEW -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
我们看到,第二条被注释掉了,因为那一规则完全可以省去,让默认规则处理就行了。
是不是显得很简单呢,对于个人桌面应用来说,只用刚才那两条语句,就能让你接入internet网的主机足够安全。而且你随意访问internet,但是外部却不能主动发起对你机器的连接,真是爽啊!
当然,如是你的IE有漏洞的话,iptables还是无济于事的,这也不是iptables的工作范围。
我们可看到有状态的防火墙比静态防火墙要"智能"一些,当然规则容易设置一些。

如果你的主机是服务器,接下来的问题就简单了。这里假如我们开了www 和ftp服务。注意ftp的pasv模式,会使用动态的端口来传送数据,而并非20端口。这些对有状态的防火墙来说,轻易做到,甚至不用知道pasv模式的ftp用哪些端口,因为你的主机会认识到ftp给别人主机传送文件时,认识到这些数据是RELATED

在后面加下
iptables -A INPUT -i ppp0 -p tcp -dport 21 -j ACCEPT
iptables -A INPUT -i ppp0 -p udp -dport 21 -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp -dport 80 -j ACCEPT
iptables -A INPUT -i ppp0 -p udp -dport 80 -j ACCEPT
好了,至此我们的工作就全部完成了,仿照我上一文的方法,最后给出一个脚本,有详细的注释


 
!/bin/bash
#define const here
Accept_Ports="80 20 21" #允许internet访问的自己服务端口

# init
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X

# set default ruler here
iptables -P INPUT DROP

# Allow inner Network access
iptables -A INPUT -i !ppp0 -j ACCEPT

# set stated ruler here,this is the most important ruler
iptables -A INPUT -i ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# set ruler so that other can access service on your server
for Port in "$Accept_Ports" ; do
        iptables -A INPUT -i ppp0 -p udp --dport ${Port} -j ACCEPT
        iptables -A INPUT -i ppp0 -p tpc --dport ${Port} -j ACCEPT
done


# the ruler can make you firewall betterd
iptables -A INPUT -i ppp0 -p tcp -j REJECT --reject-with tcp-reset
iptables -A INPUT -i ppp0 -p udp -j REJECT --reject-with icmp-port-unreachable




注:
有状态防火墙需要内核的支持,幸好,多数的发行版都支持这一特征
发表于 2005-10-15 09:40:09 | 显示全部楼层
兄弟又出力作,辛苦了。

防火墙的是基础,通过兄弟的两篇文档,能让新手对防火墙有个由简单到深入。

加为精华,与弟兄们共享。

谢谢。

北南 呈上
回复 支持 反对

使用道具 举报

发表于 2005-10-16 09:11:58 | 显示全部楼层
${Port} 这语句什么意思啊? 不是Accept_Ports 么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-10-16 15:53:47 | 显示全部楼层
for Port in "$Accept_Ports" ; do
iptables -A INPUT -i ppp0 -p udp --dport ${Port} -j ACCEPT
iptables -A INPUT -i ppp0 -p tpc --dport ${Port} -j ACCEPT
done

shell循环语句,每次循环,${Port}分别取"$Accept_Ports"中的一个值


这次写的脚本并没有在并没有测试过,不过,我仔细看过,脚本没有问题!
回复 支持 反对

使用道具 举报

发表于 2005-10-18 16:17:02 | 显示全部楼层
我觉得
# Allow inner Network access
iptables -A INPUT -i !ppp0 -j ACCEPT[QUOTE]

这一条
好像有点怪
我觉得应把这条写在最后并改为
iptables -A INPUT -i ppp0 -j DROP
这样应该比较易看懂一点
不知觉得如何
回复 支持 反对

使用道具 举报

发表于 2005-10-21 00:24:14 | 显示全部楼层
Post by vyouzhi
我觉得
[QUOTE]
# Allow inner Network access
iptables -A INPUT -i !ppp0 -j ACCEPT
这一条
好像有点怪
我觉得应把这条写在最后并改为
iptables -A INPUT -i ppp0 -j DROP
这样应该比较易看懂一点
不知觉得如何

两条是不同的
按规则来看,你这条应该是不需要的。
回复 支持 反对

使用道具 举报

发表于 2005-10-21 14:14:57 | 显示全部楼层
第一条我的解理是:除了ppp0,所有的都accept
我的那一条是:只drop ppp0
那样这两条意思都应该是相同的
我之所以想放在后面是:对更大的范围限定和更模糊限定应该放在最后为好
楼上你又觉得如何呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-10-23 09:34:12 | 显示全部楼层
Post by vyouzhi

# Allow inner Network access
iptables -A INPUT -i !ppp0 -j ACCEPT
这一条
好像有点怪
我觉得应把这条写在最后并改为
iptables -A INPUT -i ppp0 -j DROP是不是写错了?
这样应该比较易看懂一点
不知觉得如何  


两条意思是不同的
第一条: iptables -A INPUT -i !ppp0 -j ACCEPT
除了ppp0,所有的都accept。也就是接受了内网数据

你的那一条是:iptables -A INPUT  ppp0 -j DROP(仔细检查你写的,应该像这里这样写才对)
只drop ppp0,但是没有规定内网是否可以访问,内网数据将会被后面的规则处理,后面规则会丢弃数据,这样内网无法访问

本人觉得自己规则顺序是最优化的了
我定义规则的顺序是:
1 所有内网(不是ppp0接口)数据可以进入
2 所有已建立连接或与连接相关数据可以进入
3 允许自己所打开服务对应端口数据可以进入(如:打开了www服务,则开放ppp0上的80端口)
4 拒绝所有不是上面所列的数据进入
回复 支持 反对

使用道具 举报

发表于 2005-10-24 12:44:10 | 显示全部楼层
能控制访问外网的80端口吗?
回复 支持 反对

使用道具 举报

发表于 2005-10-31 14:03:52 | 显示全部楼层
我觉得还是改为直接指明接口的好
如 eth0
比 !ppp0好
更清楚,位置在这应行,不过最好也要加以控制,内部也不完全安全,这样一省略会留下不少安全隐患。
回复 支持 反对

使用道具 举报

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

本版积分规则

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