netfilter/iptables 原理

用户头像
为为
关注
发布于: 2020 年 10 月 14 日
netfilter/iptables 原理

iptables在Docker和kubernetes网络中应用甚广。例如Docker容器和宿主机端口映射、Kubernetes Service默认模式、CNI中的portmap插件、Kubernetes网络策略都是通过iptables来实现的。iptables是与linux内核集成的包过滤防火墙系统,几乎所有的linux发行版本都会包含iptables功能。如果linux系统连接到因特网或LAN、服务器或连接LAN和Internet的代理服务器,则iptables有利于在linux系统上更好的控制IP信息包过滤和防火墙配置。

netfilter/iptables过滤防火墙系统是一种功能强大的工具,可用于添加、编辑和删除规则,这些规则信息是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在linux内核。在信息包过滤表中,规则被分组放在链(chain)中。虽然netfilter/iptables被称为单个实体,但实际上由两个组件netfilter和iptable组成。

  • netfilter 组件也被称为内核组件,是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。

  • iptables 组件是一种用户空间工具,它使插入、修改和除去信息包过滤表中的规则变得容易。



什么是netfilter/iptables



netfilter 是指整个项目,官网地址是 www.netfilter.org。在这个项目里面,netfilter指特定内核中的netfilter框架。而iptables指用户空间中的配置工具。

netfilter在协议栈中添加了5个钩子,允许内核模块在这些钩子上注册回调函数,这样经过钩子的所有数据都会被注册在相应钩子上的函数处理,包括修改数据包内容,给数据包打标记或者丢弃数据包等。netfilter框架负责维护处理钩子上的函数或者模块,以及他们之间的优先级。netfilter框架负责在需要的时候动态加载其它的内核模块比如ip_conntrack 、 nf_conntrack、 NAT subsystem等。



在应用者角度,可能iptables代表了整个项目,代表了防火墙,但在开发者眼里,可能netfilter更能代表这个项目。



原理

netfilter Hooks

在内核协议栈中由5个与netfilter有关的Hooks,数据包经过每个hooks时,都会检查上面是否有注册函数,它们的位置见下图。



|
| Incoming
+-------------------+
| NF_IP_PRE_ROUTING |
+-------------------+
|
|
+------------------+
| | +----------------+
| routing decision |-------->| NF_IP_LOCAL_IN |
| | +----------------+
+------------------+ |
| |
| ↓
| +-----------------+
| | local processes |
| +-----------------+
| |
| |
↓ ↓
+---------------+ +-----------------+
| NF_IP_FORWARD | | NF_IP_LOCAL_OUT |
+---------------+ +-----------------+
| |
| |
↓ |
+------------------+ |
| | |
| routing decision |<----------------+
| |
+------------------+
|
|
+--------------------+
| NF_IP_POST_ROUTING |
+--------------------+
|
| Outgoing
  • NF_IP_PRE_ROUTING 系统接收的数据包刚进来,即未经过路由,不知道需要将数据包发送到本机还是其它机器。

  • NF_IP_LOCAL_IN 已经经过路由选择,并且该数据包的目的IP是本机,进入本地数据包处理流程。

  • NF_IP_FORWARD 已经经过路由选择,但该数据包的目的IP不是本机,进而是其它机器,进入forward流程。

  • NF_IP_LOCAL_OUT 本地程序要发出的数据包刚到IP层,还未进行路由选择。

  • NF_IP_POST_ROUTING 本地程序发出/转发的数据包已经过了路由选择,即将交由下层发送。



关于这些Hooks更具体的位置,请参考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配置的rules只会影响IPv4的数据包,而IPv6相关的配置需要使用ip6tables。



iptables 中的表

iptables用表(table)来分类管理它的规则(rule),根据rule的作用分成了好几个表,比如用来过滤数据包的rule就会放到filter表中,用于处理地址转换的rule就会放到nat表中,其中rule就是应用在netfilter钩子上的函数,用来修改数据包的内容或过滤数据包。

规则、表和链

rules

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



rule存放在特定表的特定chain上,每条rule包含下面两部分信息:

Matching

Matching就是如何匹配一个数据包,匹配条件很多,比如协议类型、源/目的IP、源/目的端口、in/out接口、包头里面的数据以及连接状态等,这些条件可以任意组合从而实现复杂情况下的匹配。详情请参考Iptables matches

Targets

Targets就是找到匹配的数据包之后怎么办,常见的有下面几种:



  • DROP:直接将数据包丢弃,不再进行后续的处理

  • RETURN: 跳出当前chain,该chain里后续的rule不再执行

  • QUEUE: 将数据包放入用户空间的队列,供用户空间的程序处理

  • ACCEPT: 同意数据包通过,继续执行后续的rule

  • 跳转到其它用户自定义的chain继续执行



当然iptables包含的targets很多很多,但并不是每个表都支持所有的targets,rule所支持的target由它所在的表和chain以及所开启的扩展功能来决定,具体每个表支持的targets请参考Iptables targets and jumps



chains

链(chains)是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。

iptables 里有5个内置的chains,分别对应5个Hooks



  • PREROUTING: 数据包经过NFIPPRE_ROUTING时会触发该chain上的rule.

  • INPUT: 数据包经过NFIPLOCAL_IN时会触发该chain上的rule.

  • FORWARD: 数据包经过NFIPFORWARD时会触发该chain上的rule.

  • OUTPUT: 数据包经过NFIPLOCAL_OUT时会触发该chain上的rule.

  • POSTROUTING: 数据包经过NFIPPOST_ROUTING时会触发该chain上的rule.



每个表里面都可以包含多个chains,但并不是每个表都能包含所有的chains,因为某些表在某些chain上没有意义或者有些多余,比如说raw表,它只有在connection tracking之前才有意义,所以它里面包含connection tracking之后的chain就没有意义。(connection tracking的位置会在后面介绍到)

多个表里面可以包含同样的chain,比如在filter和raw表里面,都有OUTPUT chain,那应该先执行哪个表的OUTPUT chain呢?这就涉及到后面会介绍的优先级的问题。

提示:可以通过命令iptables -L -t nat|grep policy|grep Chain查看到nat表所支持的chain,其它的表也可以用类似的方式查看到,比如修改nat为raw即可看到raw表所支持的chain。



image



用户自定义Chains

除了iptables预定义的5个chain之外,用户还可以在表中定义自己的chain,用户自定义的chain中的rule和预定义chain里的rule没有区别,不过由于自定义的chain没有和netfilter里面的钩子进行绑定,所以它不会自动触发,只能从其它chain的rule中跳转过来。



tables

表(tables)提供特定的功能,iptables主要内置了4个表,即raw表、filter表、nat表和mangle表,分别用于实现包过滤,网络地址转换和包重构的功能。



image



RAW表

只使用在PREROUTING链和OUTPUT链上,因为优先级最高,从而可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,在 某个链上,RAW表处理完后,将跳过NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了.

filter表

主要用于过滤数据包,该表根据系统管理员预定义的一组规则过滤符合条件的数据包。对于防火墙而言,主要利用在filter表中指定的规则来实现对数据包的过滤。Filter表是默认的表,如果没有指定哪个表,iptables 就默认使用filter表来执行所有命令,filter表包含了INPUT链(处理进入的数据包),RORWARD链(处理转发的数据包),OUTPUT链(处理本地生成的数据包)在filter表中只能允许对数据包进行接受,丢弃的操作,而无法对数据包进行更改

nat表

主要用于网络地址转换NAT,该表可以实现一对一,一对多,多对多等NAT 工作,iptables就是使用该表实现共享上网的,NAT表包含了PREROUTING链(修改即将到来的数据包),POSTROUTING链(修改即将出去的数据包),OUTPUT链(修改路由之前本地生成的数据包)

mangle表

主要用于对指定数据包进行更改,在内核版本2.4.18 后的linux版本中该表包含的链为:INPUT链(处理进入的数据包),RORWARD链(处理转发的数据包),OUTPUT链(处理本地生成的数据包)POSTROUTING链(修改即将出去的数据包),PREROUTING链(修改即将到来的数据包)



表的优先级

下图在上图的基础上标识了各个表的rule可以注册到哪个Hooks上(即表支持哪些chain),以及他们的优先级。

  1. 图中每个钩子关联的表按照优先级高低,从上到下排列;

  2. 图中将nat分成了SNAT和DNAT,便于区分;

  3. 图中标出了connection tracking(可以简单的把connection tracking理解成一个不能配置chain和rule的表,它必须放在指定位置,只能enable和disable)。



|
| Incoming ++---------------------++
↓ || raw ||
+-------------------+ || connection tracking ||
| NF_IP_PRE_ROUTING |= = = = = =|| mangle ||
+-------------------+ || nat (DNAT) ||
| ++---------------------++
|
↓ ++------------++
+------------------+ || mangle ||
| | +----------------+ || filter ||
| routing decision |-------->| NF_IP_LOCAL_IN |= = = = = =|| security ||
| | +----------------+ || nat (SNAT) ||
+------------------+ | ++------------++
| |
| ↓
| +-----------------+
| | local processes |
| +-----------------+
| |
| | ++---------------------++
++------------++ ↓ ↓ || raw ||
|| mangle || +---------------+ +-----------------+ || connection tracking ||
|| filter ||= = = = = =| NF_IP_FORWARD | | NF_IP_LOCAL_OUT |= = = = = =|| mangle ||
|| security || +---------------+ +-----------------+ || nat (DNAT) ||
++------------++ | | || filter ||
| | || security ||
↓ | ++---------------------++
+------------------+ |
| | |
| routing decision |<----------------+
| |
+------------------+
|
|
+--------------------+ ++------------++
| NF_IP_POST_ROUTING |= = = = = =|| mangle ||
+--------------------+ || nat (SNAT) ||
| ++------------++
| Outgoing



  • 以NFIPPRE_ROUTING为例,数据包到了这个点之后,会先执行raw表中PREROUTING(chain)里的rule,然后执行connection tracking,接着再执行mangle表中PREROUTING(chain)里的rule,最后执行nat (DNAT)表中PREROUTING(chain)里的rule。

  • 以filter表为例,它只能注册在NFIPLOCALIN、NFIP_FORWARD和NF_IPLOCALOUT上,所以它只支持INPUT、FORWARD和OUTPUT这三个chain。

  • 以收到目的IP是本机的数据包为例,它的传输路径为:NFIPPRE_ROUTING -> NF_IPLOCALIN,那么它首先要依次经过NFIPPRE_ROUTING上注册的raw、connection tracking 、mangle和nat (DNAT),然后经过NF_IPLOCALIN上注册的mangle、filter、security和nat (SNAT)。



总体来说,规则表之间的之间的优先顺序是:Raw——mangle——nat——filter

Connection Tracking

连接追踪(Connection Tracking) 发生在NF_IP_PRE_ROUTINGNF_IP_LOCAL_OUT这两个地方,一旦开启该功能,Connection Tracking模块将会追踪每个数据包(被raw表中的rule标记过的除外),维护所有的连接状态,然后这些状态可以供其它表中的rule引用,用户空间的程序也可以通过/proc/net/ip_conntrack来获取连接信息。下面是所有的连接状态:

这里的连接不仅仅是TCP的连接,两台设备的进程用UDP和ICMP(ping)通信也会被认为是一个连接



  • NEW: 当检测到一个不和任何现有连接关联的新包时,如果该包是一个合法的建立连接的数据包(比如TCP的sync包或者任意的UDP包),一个新的连接将会被保存,并且标记为状态NEW。

  • ESTABLISHED: 对于状态是NEW的连接,当检测到一个相反方向的包时,连接的状态将会由NEW变成ESTABLISHED,表示连接成功建立。对于TCP连接,意味着收到了一个SYN/ACK包, 对于UDP和ICMP,任何反方向的包都可以。

  • RELATED: 数据包不属于任何现有的连接,但它跟现有的状态为ESTABLISHED的连接有关系,对于这种数据包,将会创建一个新的连接,且状态被标记为RELATED。这种连接一般是辅助连接,比如FTP的数据传输连接(FTP有两个连接,另一个是控制连接),或者和某些连接有关的ICMP报文。

  • INVALID: 数据包不和任何现有连接关联,并且不是一个合法的建立连接的数据包,对于这种连接,将会被标记为INVALID,一般这种都是垃圾数据包,比如收到一个TCP的RST包,但实际上没有任何相关的TCP连接,或者别的地方误发过来的ICMP包。

  • UNTRACKED: 被raw表里面的rule标记为不需要tracking的数据包,这种连接将会标记成UNTRACKED。



总结

下面一张图总结了iptables的工作原理





用户头像

为为

关注

还未添加个人签名 2020.02.25 加入

还未添加个人简介

评论

发布
暂无评论
netfilter/iptables 原理