iptables扩展模块state

1,085 阅读4分钟

netfilter/iptables(下文中简称为iptables)组成Linux平台下的软件防火墙,netfilter是Linux操作系统核心层内部的一个数据包处理模块,位于内核空间,iptables是一个命令行工具,位于用户空间,可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全规则设定执行到内核空间的netfilter模块中,netfilter模块根据规则来过滤网络包。

规则(rules)其实就是网络管理员预定义的条件,规则一般的定义为“如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息 包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。iptables会根据链中的规则,从上往下匹配,当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。

为了服务器A的安全,在服务器A的入方向限制了只有目的端口为36000才能进入,其他都拒绝。在服务器A通过ssh连接到服务器B(sshd的监听端口为36000)时,A作为客户端发起了到B的连接1,源端口随机,目标端口为36000,当B收到消息后会向A回包,发起连接2,源端口为36000,目标端口为11234,按照之前设定的防火墙规则,这个包就被防火墙拒绝了,ssh连接失败了。

那怎么办了?似乎只能放通某些端口,回包的目的端口有随机性不好放通,如果放通源端口为36000的包,上面的回包就能通过,ssh连接就能成功,但显然这是不安全的,攻击者可以从他自己机器的36000端口向A的任意端口发送报文。你心里可能会这样想:我知道哪些主机是安全的,只要针对这些安全的主机放行对应的端口就行了,其他IP一律拒绝,比如,我知道B是安全的,所以对B开放了36000端口,以便B能够通过36000端口响应A的ssh请求。只有两台机器,这是一个很好的办法,如果有20台或者200台机器呢?总不能新增一台机器就去刷一遍iptables,这个时候state模块就派上用场了。

造成上述问题的"根源"在于,我们为了让"提供服务方"能够正常的"响应"我们的请求,在主机上开放了对应的端口,开放这些端口的同时,也出现了问题,别人利用这些开放的端口,"主动"的攻击我们,他们发送过来的报文并不是为了响应我们,而是为了主动攻击我们。所以解决问题核心在于如何判断报文是为了回应我们之前发出的报文,还是主动向我们发送的报文。

iptables的state扩展模块可以让iptables实现"连接追踪"机制,对于state模块的连接而言,"连接"其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。

NEW:连接中的第一个包,状态就是NEW

ESTABLISHED:NEW状态包后面的包的状态为ESTABLISHED,表示连接已建立

RELATED:表示这个封包是与我们主机发送出去的封包有关, 可能是响应封包或者是联机成功之后的传送封包!这个状态很常被设定,因为设定了他之后,只要未来由本机发送出去的封包,即使我们没有设定封包的 INPUT 规则,该有关的封包还是可以进入我们主机, 可以简化相当多的设定规则。

INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。

UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。

那问题的答案就有了,就是放通状态为ESTABLISHED和RELATED的包

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT