netfilter/iptables简介

netfilter和iptables是什么关系?常说的iptables里面的表(table)、链(chain)、规则(rule)都是什么东西?本篇将带着这些疑问介绍netfilter/iptables的结构和相关概念,帮助有须要的同窗更好的理解netfilter/iptables,为进一步学习使用iptables作准备。html

什么是netfilter和iptables

用通俗点的话来说:git

  • netfilter指整个项目,否则官网就不会叫www.netfilter.org了。segmentfault

  • 在这个项目里面,netfilter特指内核中的netfilter框架,iptables指用户空间的配置工具。网络

  • netfilter在协议栈中添加了5个钩子,容许内核模块在这些钩子的地方注册回调函数,这样通过钩子的全部数据包都会被注册在相应钩子上的函数所处理,包括修改数据包内容、给数据包打标记或者丢掉数据包等。框架

  • netfilter框架负责维护钩子上注册的处理函数或者模块,以及它们的优先级。函数

  • iptables是用户空间的一个程序,经过netlink和内核的netfilter框架打交道,负责往钩子上配置回调函数。工具

  • netfilter框架负责在须要的时候动态加载其它的内核模块,好比 ip_conntrack、nf_conntrack、NAT subsystem等。学习

在应用者的眼里,可能iptables表明了整个项目,表明了防火墙,但在开发者眼里,可能netfilter更能表明这个项目。.net

netfilter钩子(hooks)

在内核协议栈中,有5个跟netfilter有关的钩子,数据包通过每一个钩子时,都会检查上面是否注册有函数,若是有的话,就会调用相应的函数处理该数据包,它们的位置见下图:计算机网络

|
         | 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: 本地程序发出去的数据包,或者转发(forward)的数据包已经通过了路由选择,即将交由下层发送出去。

关于这些钩子更具体的位置,请参考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中的表(tables)

iptables用表(table)来分类管理它的规则(rule),根据rule的做用分红了好几个表,好比用来过滤数据包的rule就会放到filter表中,用于处理地址转换的rule就会放到nat表中,其中rule就是应用在netfilter钩子上的函数,用来修改数据包的内容或过滤数据包。目前iptables支持的表有下面这些:

Filter

从名字就能够看出,这个表里面的rule主要用来过滤数据,用来控制让哪些数据能够经过,哪些数据不能经过,它是最经常使用的表。

NAT

里面的rule都是用来处理网络地址转换的,控制要不要进行地址转换,以及怎样修改源地址或目的地址,从而影响数据包的路由,达到连通的目的,这是家用路由器必备的功能。

Mangle

里面的rule主要用来修改IP数据包头,好比修改TTL值,同时也用于给数据包添加一些标记,从而便于后续其它模块对数据包进行处理(这里的添加标记是指往内核skb结构中添加标记,而不是往真正的IP数据包上加东西)。

Raw

在netfilter里面有一个叫作connection tracking的功能(后面会介绍到),主要用来追踪全部的链接,而raw表里的rule的功能是给数据包打标记,从而控制哪些数据包不被connection tracking所追踪。

Security

里面的rule跟SELinux有关,主要是在数据包上设置一些SELinux的标记,便于跟SELinux相关的模块来处理该数据包。

chains

上面咱们根据不一样功能将rule放到了不一样的表里面以后,这些rule会注册到哪些钩子上呢?因而iptables将表中的rule继续分类,让rule属于不一样的链(chain),由chain来决定何时触发chain上的这些rule。

iptables里面有5个内置的chains,分别对应5个钩子:

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

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

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

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

  • POSTROUTING: 数据包通过NF_IP_POST_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。

每一个表(table)都包含哪些chain,表之间的优先级是怎样的?

下图在上面那张图的基础上,详细的标识出了各个表的rule能够注册在哪一个钩子上(即各个表里面支持哪些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
                                    ↓
  • 以NF_IP_PRE_ROUTING为例,数据包到了这个点以后,会先执行raw表中PREROUTING(chain)里的rule,而后执行connection tracking,接着再执行mangle表中PREROUTING(chain)里的rule,最后执行nat (DNAT)表中PREROUTING(chain)里的rule。

  • 以filter表为例,它只能注册在NF_IP_LOCAL_IN、NF_IP_FORWARD和NF_IP_LOCAL_OUT上,因此它只支持INPUT、FORWARD和OUTPUT这三个chain。

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

iptables中的规则(Rules)

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

除了iptables预约义的5个chain以外,用户还能够在表中定义本身的chain,用户自定义的chain中的rule和预约义chain里的rule没有区别,不过因为自定义的chain没有和netfilter里面的钩子进行绑定,因此它不会自动触发,只能从其它chain的rule中跳转过来。

链接追踪(Connection Tracking)

Connection Tracking发生在NF_IP_PRE_ROUTING和NF_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。

结束语

本篇介绍了netfilter/iptables的基本结构和一些相关概念,了解这些只是一个开始,要想熟练的配置iptables规则,还须要对计算机网络知识很是熟悉,下次有机会的话再介绍如何使用iptables。

参考