iptables 原理概述

References

在这里插入图片描述

一、iptables 和 netfilter

iptables 是 Linux 上最常用的防火墙工具。其底层是基于与 Linux 内核网络协议栈所提供的包过滤 hook 从而实现的。而负责提供这些 hook 的就是 Netfilter 框架。

每个进入网络系统的包(接收或发送)在经过协议栈时都会触发这些 hook,程序可以通过注册 hook 函数的方式在一些关键路径上处理网络流量。而 Linux 上的防火墙功能正是基于 iptables 所提供的接口,在这些 hook 点上注册了处理函数,从而可以实现对应的防火墙规则。

综上所述,即 Netfilter 是 Linux 内核提供的一个框架,而 iptables 是基于此框架实现的一个内核模块,同时我们也应该注意到,iptables 并不是唯一基于 Netfilter 实现的内核模块,同样基于 Netfilter 实现的还有例如 IPVS 模块等。

二、Network Hook

netfilter 提供了 5 个 hook 点。包经过这些点时会触发内核模块在这里注册的处理函数。触发哪个 hook 取决于包的方向(ingress/egress)、包的目的地址、包在上一个 hook 点是被丢弃还是拒绝等。

下面几个 hook 是内核协议栈中已经定义好的:

  • NF_IP_PRE_ROUTING:接收到的包进入协议栈后立即触发此 hook,在进行任何路由判断(将包发往哪里)之前;
  • NF_IP_LOCAL_IN:接收到的包经过路由判断,如果目的是本机,将触发此 hook;
  • NF_IP_FORWARD:接收到的包经过路由判断,如果目的是其他机器,将触发此 hook;
  • NF_IP_LOCAL_OUT:本机产生的准备发送的包,在进入协议栈之后立即触发此 hook;
  • NF_IP_POST_ROUTING:本机产生的准备发送的包或者转发的包,在经过路由判断之后,将触发此 hook。

在 hook 点上注册处理函数时必须提供优先级,以便 hook 被触发时能按照优先级顺序调用处理函数。这使得多个模块(或者同一模块的多个实例)可以在同一 hook 点注册,并且有确定的处理顺序。

三、iptables 表和链

iptables 使用表(tables)来组织规则,根据规则的应用场景从而划分到不同的表中。例如某条规则是用来做网络地址转换的,那这条规则会被划分到 nat 表中,如果某条规则是用来判断过滤数据包,那么这条规则则是属于 filter 表的。

同时,在每个表内部,规则被进一步组织成链(chains)。表是由它们所持有的规则的应用场景定义的,而内置链表示触发它们的 netfilter 钩子,即链决定何时触发这些规则。

下面可以看出,内置的 chain 名字和 netfilter hook 名字是一一对应的:

  • PREROUTING:由 NF_IP_PRE_ROUTING hook 触发;
  • INPUT:由 NF_IP_LOCAL_IN hook 触发;
  • FORWARD:由 NF_IP_FORWARD hook 触发;
  • OUTPUT:由 NF_IP_LOCAL_OUT hook 触发;
  • POSTROUTING:由 NF_IP_POST_ROUTING hook 触发。

四、table 类型

先来看看 iptables 提供的 table 类型,这些 tables 是按规则类型区分的。

4.1 filter table:过滤(放行/拒绝)

filter table 是最常用的表之一,用于判断是否允许一个包通行。

在防火墙的概念中,这通常被称作包“过滤”(“filtering” packets),这个 table 提供了防火墙的一些常见功能。

4.2 nat table:网络地址转换

nat 表用于实现网络地址转换规则。

当包进入协议栈的时候,这些规则决定是否以及如何修改包的源/目的地址,以改变包被路由时的行为。nat 表通常用于将包修改后路由到原先的包无法直接访问的网络。

4.3 mangle table:修改 IP 头

mangle 表用来对 IP 包的 IP 头进行修改,例如可以修改包的 TTL,增加或减少可以经过的跳数。

这个表还可以用来对包打上内核内置的标记,以便后续的表或其他网络工具根据标记进行处理。这个标记不会修改 IP 包本身,只是做了个标签,而且只在内核处理过程中有效。

4.4 raw table:contrack 相关

iptables 是有状态的,即 iptables 对数据包有连接追踪(connection tracking)机制(对于 contrack 的进一步探讨看第七小节),而 raw 是用来去除这种最终机制的,主要是为了提高效率使用的。

raw本身的含义是指“原生的”、“未经过加工 的”,符合 raw 表所对应规则的数据包将会跳过一些检查,这样就可以提高效率;

4.5 security table:打 SELinux 标记

最不常用的表(通常,我们说 iptables 只有 4 张表,security 表是后面新加入的特性),用于在数据包上应用 SELiunx。

五、表与链之间的关联

前面已经讨论了 table 和 chain,接下来我们探讨每个 table 里都有哪些 chain。同时,我们还将关注注册到同一 hook 上的不同 chain 的优先级。例如:mangle、raw、nat 这三个表中都有 PREROUTING chain,那么应该按照什么顺序调用它们呢?

5.1 表关联的链以及链的执行顺序

下面的表格展示了 table 和 chain 的关系。横向是 table,纵向是 chain,Y 表示这个 table 里面有这个 chain。例如,第二行表示 raw table 有 PRETOUTINGOUTPUT 两 个 chain。具体到每列,从上倒下的顺序就是 netfilter hook 触发的时候,(对应 table 的)chain 被调用的顺序。

有几点需要说明一下。在下面的图中,nat 表被细分成了 DNAT (修改目的地址) 和 SNAT(修改源地址),以更方便地展示他们的优先级。另外,我们添加了路由决策点 和连接跟踪点,以使得整个过程更完整全面:

Tables↓/Chains→PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING
(routing decision)
raw
(connection tracking enabled)
mangle
nat (DNAT)
(routing decision)
filter
security
nat (SNAT)

当一个包触发 netfilter hook 时,处理过程将沿着列从上向下执行。 触发哪个 hook(列)和包的方向(ingress/egress)、路由判断、过滤条件等相关。

在这里插入图片描述

特定事件会导致 table 的 chain 被跳过。例如,只有每个连接的第一个包会去匹配 NAT 规则,对这个包的动作会应用于此连接后面的所有包。到这个连接的应答包会被自动应用反方向的 NAT 规则。

5.2 自定义 chain

除了上述我们提到的 chain 外,iptables 也支持创建自定义的链。用户定义的 chain 可以看作是对调用它的 chain 的扩展。例如,用户定义的 chain 在结 束的时候,可以返回 netfilter hook,也可以继续跳转到其他自定义 chain。

向用户自定义 chain 添加规则和向内置的 chain 添加规则的方式是相同的。不同的地方在于, 用户定义的 chain 只能通过从另一个规则跳转(jump)到它,因为它们没有注册到 netfilter hook

用户自定义的链中的规则和系统预定义的 5 条链里的规则没有区别。犹豫自定义的链没有与 netfilter 里的 hook 进行绑定,所以它不会自定触发,只能从其他链的规则中跳转过来,也就是后续 iptables 规则中提到的 JUMP 动作。

这种设计使框架具有强大的分支功能,使得管理员可以组织更大更复杂的网络规则。

六、iptables 规则

每一条 iptables 规则都包涵匹配和动作两部分。

6.1 匹配

规则的匹配部分指定数据包必须满足的条件,以便执行相关的操作(或“目标”)。

匹配系统非常灵活,可以通过附加的 iptables 接口进行定义。规则可以根据协议类型、目标或源地址、目标或源端口、目标或源网络、输入或输出接口、报头或连接状态等条件进行匹配。可以将这些规则组合起来创建复杂的规则集,以区分不同的流量。

6.2 动作

那么数据包匹配完之后该怎么办,常见的有以下几种操作:

  • DROP:直接将数据丢弃,不再进行后续的处理;
  • REJECT:给客户端发挥一个 connection refused 或 destination unreachable 包文;
  • QUEUE:将数据包放入用户空间的队列,供用户空间的程序处理;
  • RETURN:跳出当前链,该链里的后续规则不再执行;
  • ACCEPT:同意数据包通过,继续执行后续的规则;
  • JUMP:跳转到其他用户自定义的链继续执行。

七、iptables 和 conntrack

在讨论 raw 表和匹配连接状态的时候,我们介绍了构建在 netfilter 之上的 连接跟踪(conntrack)系统。conntrack 系统使得 iptables 基于连接上下文而不是单个包来做出规则判断, 给 iptables 提供了有状态操作的功能。

conntrack 系统将包和已有的连接进行比较,如果包所属的连接已经存在就更新连接状态, 否则就创建一个新连接。如果 raw 表的某个 chain 对包标记为目标是 NOTRACK, 那这个包会跳过连接跟踪系统。

7.1 什么是 conntrack

Connection tracking(“contrack”)是 Linux 内核提供的一个重要特性,用来支持 Linux 内核对逻辑网络连接或流进行跟踪,识别组成每个流的所有数据包,从而能够对这些数据包进行一致性的处理。

Contrack 是 Linux 上一些功能的底层技术支撑:

  • NAT 就依赖着 Contrack 技术,所以在做 NAT 时,才能将同一连接上的所有包打到同一目标网络去。例如:在 Kubernetes 中,当一个 Pod 访问 Service 时,kube-proxy 的负载均衡会利用 NAT 将请求转发到特定的 Pod 上去。这个时候就需要 contrack 保证来自同一请求的所有包都转发到特定的 Pod 上,也不会被转发到 Service 所代理的其他 Pod 上。

  • 有状态防火墙。比如 calico 就依赖 connection tracking 提供的信息精准地将本机允许通过的流量列入放行名单中,而只阻止那些来自不允许通过的流量。如果没有这个,就无法区分连接的状态。例如现在一个 Pod 不允许主动对外访问,但是允许外部的 Pod 访问它,这个时候如果没有 conntrack,就无法识别哪些数据包是该 Pod 响应的,哪些数据包是该 Pod 主动对外访问的。

此外,conntrack 通常可以提高性能(减少CPU和数据包延迟),因为只有连接中的第一个数据包需要经过完整的网络堆栈处理才能确定如何处理它。

7.2 连接的状态

conntrack 系统中的状态有以下几种:

  • NEW:如果到达的包关联不到任何已有的连接,但包是合法的,就为这个包创建一个新的连接。对面向连接(connection-aware)的协议如 TCP 以及非面向连接的(connectionless)的协议例如 UDP 都适用;
  • ESTABLISHED:当一个连接收到应答方向的合法包时,状态就从 NEW 变成 ESTABLISHED 。对于 TCP,这个合法包就是 SYN/ACK 包;对于 UDP/ICMP 来说,则是原地址与目的地址的 IP 与原包相反的包;
  • RELATED:包不属于已有的连接,但是和已有的连接有一定关系。这可能是辅助连接(helper connection),例如 FTP 数据传输连接,活着是其他协议试图建立连接时的 ICMP 应答包;
  • INVALID:包不属于已有连接,并且因为某些原因不能用来创建一个新连接,例如无法识别、无法路由等;
  • UNTRACKED:如果在 raw 表中标记为目标是 UNTRACKED,这个包将不会进入 contrack 系统;
  • SNAT:包的源地址被 NAT 修改之后会进入的虚拟状态,conntrack 系统根据此在收到反向包时对地址做反向转换;
  • DNAT:包的目的地址被 NAT 修改之后会进入的虚拟状态,conntrack 系统根据此在收到反向包时对地址做反向转换。

这些状态可以定位到连接生命周期内部,程序员可以据此编写出更加细粒度、适用范围更大、更安全的规则。

八、总结

Netfilter 包过滤框架和 iptables 防火墙是 Linux 服务器上大部分防火墙解决方案的基础。Netfilter 的内核 hook 和协议栈之间联系紧密,提供了对数据包经过系统时的强大控制功能。 iptables 基于这些功能提供了一个灵活的、可扩展的、将策略需求应用到内核的方案。理解了这些不同模块是如何联系到一起的,就可以更高效地对数据包进行控制。篇文章,了解一下Markdown的基本语法知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值