netfilter和iptables有什么关系?常说的iptables中的表、链、规则是什么?本文将带着这些疑问介绍netfilter/iptables的结构和相关概念,帮助有需要的同学更好的理解netfilter/iptables,为进一步学习使用iptables做准备。什么是netfilter和iptables?通俗地说:netfilter指的是整个项目,不然官网也不会叫www.netfilter.org。本项目中netfilter特指内核中的netfilter框架,iptables指的是用户空间的配置工具。Netfilter在协议栈中增加了5个钩子,允许内核模块在这些钩子中注册回调函数,这样所有通过钩子的数据包都会被对应钩子上注册的函数处理,包括修改数据包的内容,给数据包被标记或丢弃等。netfilter框架负责维护挂钩上注册的处理程序或模块,以及它们的优先级。iptables是用户空间的一个程序。它通过netlink与内核的netfilter框架通信,负责配置hook上的回调函数。netfilter框架负责在需要的时候动态加载其他内核模块,比如ip_conntrack、nf_conntrack、NAT子系统等。在用户眼中,iptables可能代表了整个项目和防火墙,但在开发者眼中,netfilter可能是更能代表这个项目。netfilterhooks(钩子)在内核协议栈中,有5个与netfilter相关的钩子。当一个数据包通过每个钩子时,它会检查是否有一个函数注册在它上面。如果是,它会调用相应的函数来处理数据。包,它们的位置如下图所示:||传入↓+--------------------+|NF_IP_PRE_ROUTING|+------------------+||↓+-----------------+||+----------------+|路由决定|-------->|NF_IP_LOCAL_IN|||+----------------++--------------+||||↓|+--------------+||本地流程||+------------------+||||↓↓+-------------++-----------------+|NF_IP_FORWARD||NF_IP_LOCAL_OUT|+----------------++----------------+||||↓|+-----------------+|||||路由决策|<----------------+||+-----------------+||↓+--------------------+|NF_IP_POST_ROUTING|+------------------+||outgoing↓NF_IP_PRE_ROUTING:接收到的数据包刚进来,还没有路由,也就是还不知道这个数据包是发往本机还是其他机器NF_IP_LOCAL_IN:已经选择了路由,目的地数据包的IP为本机,进入本地数据包处理流程。NF_IP_FORWARD:已经选择了路由,但是数据包的目的IP不是本机,而是其他机器,进入转发流程。NF_IP_LOCAL_OUT:本地程序要发出的数据包刚刚到达IP层,还没有路由。NF_IP_POST_ROUTING:本地程序发送的数据包,或者转发的数据包已经路由,将由下层发送。这些钩子更具体的位置可以参考Linux网络数据包的接收流程和数据包的发送流程。从上面的过程我们也可以看出,无论特殊情况,一个数据包只会经过以下三种路径中的一种:本机收到目的IP为本机的数据包:NF_IP_PRE_ROUTING->NF_IP_LOCAL_IN本机收到目的IP不是本机的数据包:NF_IP_PRE_ROUTING->NF_IP_FORWARD->NF_IP_POST_ROUTING本机发送的数据包:NF_IP_LOCAL_OUT->NF_IP_POST_ROUTING注意:所有的netfilter钩子(hooks)都在IP层内核协议栈。由于IPv4和IPv6使用不同的IP层编码,iptables配置的规则只会影响IPv4数据包,IPv6相关配置需要使用ip6tables。iptables(表)中的表iptables使用表对其规则(rules)进行分类和管理。它根据规则的作用分为几个表。例如,用于过滤数据包的规则将放在过滤表中。Use地址转换的规则会放在nat表中,这里的规则就是作用在netfilterhook上的函数,用来修改数据包的内容或者过滤数据包。目前iptables支持的表有以下几种:Filter从名字就可以看出,这个表中的规则主要是用来过滤数据,控制哪些数据可以通过,哪些数据不能通过。这是最常用的表。NAT中的规则用于处理网络地址转换,控制是否进行地址转换,以及如何修改源地址或目的地址,从而影响数据包的路由选择,达到连通的目的。这是家用路由器必备的功能。.Mangle中的rule主要是用来修改IP包头的,比如修改TTL值,也可以给数据包添加一些标记,以便后面其他模块可以对数据包进行处理(这里添加的标记是指内核skb结构添加标记而不是向真实IP数据包添加内容)。raw在netfilter(后面会介绍)中有一个叫做connectiontracking的功能,主要用来跟踪所有的连接,raw表中rule的作用是标记数据包,从而控制哪些数据包是未通过连接跟踪跟踪连接。Security中的规则是和SELinux相关的,主要是在数据包上设置一些SELinux标记,让SELinux相关的模块可以对数据包进行处理。我们把规则按照链中不同的功能放到不同的表中后,这些规则会注册到哪些钩子上呢?于是iptables继续对表中的规则进行分类,让规则属于不同的链(chain),由链决定什么时候触发链上的这些规则。iptables内置了5条链,分别对应5个钩子:PREROUTING:当数据包经过NF_IP_PRE_ROUTING时,会触发链上的规则。INPUT:当数据包经过NF_IP_LOCAL_IN时,会触发规则FORWARD:数据包经过NF_IP_FORWARD会触发链上规则。OUTPUT:数据包经过NF_IP_LOCAL_OUT时会触发链上规则。POSTROUTING:数据包经过NF_IP_POST_ROUTING时会触发链上的规则。每个表可以包含多个链,但不是每个表都可以包含所有链,因为有些表在某些链上是无意义的或者是冗余的,比如raw表,只有在connectiontracking之前才有意义,所以包含了connectiontracking,后面的chain是没有意义的.(后面会介绍connectiontracking的位置。)多个表可以包含同一个链。例如,过滤表和原始表都有OUTPUT链。那么应该先执行哪个表的OUTPUT链呢?这就涉及到后面会介绍的优先级问题。提示:可以通过命令iptables-L-tnat|greppolicy|grepChain查看nat表支持的链,其他表也可以类似方式查看。比如修改nat为raw,可以看到raw表支持的链。支持链。每个表包括哪些链,表之间的优先级是什么?在上图的基础上,下图详细标识了各表的规则可以注册到哪些hook上(即各表支持哪些链),以及它们的优先级。图中每个钩子关联的表按照优先级从上到下排列;nat在图中分为SNAT和DNAT,方便区分;图中标出了connectiontracking(你可以简单的把connectiontracking理解为一个不可配置的chain和rule的表,它必须放在指定的位置,只能enable和disable)。||传入++--------------------++↓||生||+--------------------+||连接跟踪|||NF_IP_PRE_ROUTING|======||粉碎||+--------------------+||自然(DNAT)|||++--------------------++|↓++------------+++----------------+||粉碎||||+----------------+||过滤器|||路由决定|-------->|NF_IP_LOCAL_IN|=======||安全||||+----------------+||纳特(SNAT)||+--------------------+|++------------++|||↓|+----------------+||本地流程||+----------------+||||++--------------------++++------------++↓↓||生||||粉碎||+----------------++----------------+||连接器关于追踪||||过滤器||======|NF_IP_FORWARD||NF_IP_LOCAL_OUT|======||粉碎||||安全||+----------------++----------------+||自然(DNAT)||++------------++||||过滤器||||||安全||↓|++--------------------+++----------------+|||||路由决策|<----------------+||+--------------------+||↓+--------------------+++------------++|NF_IP_POST_ROUTING|======||粉碎||+--------------------+||纳特(SNAT)|||++------------++|Outgoing↓以NF_IP_PRE_ROUTING为例,数据包到达该点后,会先执行原始表中PREROUTING(chain)中的规则,然后执行连接跟踪,再执行原始表中PREROUTING(chain)中的规则mangletable会被执行,最后nat(DNAT)表中的PREROUTING(chain)中的规则以filter表为例。它只能注册到NF_IP_LOCAL_IN、NF_IP_FORWARD和NF_IP_LOCAL_OUT上,所以只支持INPUT、FORWARD和OUTPUT这三个链。以目的IP为本机的数据包为例,其传输路径为:NF_IP_PRE_ROUTING->NF_IP_LOCAL_IN,则首先需要经过在NF_IP_PRE_ROUTING上注册的raw、connectiontracking、mangle和nat(DNAT),再经过NF_IP_LOCAL_IN在上注册的mangle、filter、security和nat(SNAT)。iptables中的规则(Rules)存储在特定表的特定链上。每条规则包含以下两部分信息:Matching匹配是如何匹配一个数据包。匹配条件有很多,比如协议类型、源/目的IP、源/目的端口、入/出接口、包头中的数据、连接状态等,这些条件可以任意组合,实现复杂情况下的匹配。具体可以参考IptablesmatchesTargetsTargets是找到匹配包后做什么。常见的有以下几种:DROP:直接丢弃数据包,不做进一步处理RETURN:跳出当前链,链中后续规则不再执行QUEUE:将数据包放入用户空间的队列中,对于用户空间程序处理ACCEPT:同意传递数据包,继续执行后续规则,跳转到其他用户自定义链继续执行当然iptables包含的target很多,但不是每个表都支持所有target.规则支持的目标由它所在的表和链以及启用的扩展功能决定。具体各个表支持的目标,请参考Iptables目标和跳转。用户自定义链除了iptables中的5条预定义链外,用户还可以在表中定义自己的链。自定义链中的规则和预定义链中的规则没有区别,但是由于自定义链没有绑定netfilter中的hook,所以不会自动触发,只能从中跳转其他链的规则。连接跟踪(ConnectionTracking)连接跟踪发生在NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT中。启用该功能后,ConnectionTracking模块将跟踪每个数据包(原始表中规则标记的除外)并维护所有连接状态,然后这些状态可以被其他表中的规则和用户空间中的程序引用也可以通过/proc/net/ip_conntrack获取连接信息。以下是所有的连接状态:这里的连接不仅是TCP连接,两个设备通过UDP和ICMP通信的过程(ping)也会被认为是一个连接NEW:当检测到一个与任何现有的连接都不相关的连接时connection发送新数据包时,如果该数据包是合法的连接建立数据包(例如TCP同步数据包或任何UDP数据包),则将保存一个新连接并标记为NEW状态。ESTABLISHED:对于状态为NEW的连接,当检测到相反方向的数据包时,连接的状态会由NEW变为ESTABLISHED,表示连接建立成功。对于TCP连接,这意味着已收到SYN/ACK数据包。对于UDP和ICMP,相反方向的任何数据包都可以。RELATED:数据包不属于任何现有连接,但与状态为ESTABLISHED的现有连接相关。对于这种数据包,将创建一个新的连接,并将状态标记为RELATED。这种连接一般是辅助连接,比如FTP数据传输连接(FTP有两个连接,一个是控制连接),或者是一些连接相关的ICMP报文。INVALID:该数据包不与任何现有连接相关联,不是建立连接的合法数据包。对于这种连接,它将被标记为INVALID。一般这种数据包都是垃圾数据包,比如收到一个TCPRST包,但是实际上没有相关的TCP连接,或者是别处误发的ICMP包。UNTRACKED:被原始表中的规则标记为不需要跟踪的数据包,此连接将被标记为UNTRACKED。结论本文介绍了netfilter/iptables的基本结构和一些相关概念。了解这些只是一个开始。要想熟练配置iptables规则,还需要非常熟悉计算机网络知识。下次有机会再介绍iptables的使用方法。参考IptablesTutorialADeepDiveintoIptablesandNetfilterArchitecture
