引言

防火墙是一个重要的工具,可以配置它来保护您的服务器和基础设施。 在 Linux 生态系统中,iptables 是一个广泛使用的防火墙工具,它与内核的 netfilter 包过滤框架进行交互。 对于不了解这些系统体系结构的用户和管理员来说,创建可靠的防火墙策略可能会让人望而却步,不仅是因为具有挑战性的语法,还因为框架中存在大量相互关联的部分。

在本指南中,我们将深入研究 iptables 体系结构,目的是让需要构建自己的防火墙策略的用户更容易理解它。 我们将讨论 iptables 如何与 netfilter 交互,以及各个组件如何组合在一起,以提供一个全面的过滤和管理系统。

什么是 IPTables 和 Netfilter?

Linux 中最常用的基本防火墙软件称为 iptables。 Iptables 防火墙通过与 Linux 内核网络堆栈中的包过滤钩子进行交互来工作。 这些内核钩子被称为 netfilter 框架。

每个进入网络系统(传入或传出)的数据包在通过堆栈时都会触发这些钩子,允许用这些钩子注册的程序在关键点与流量进行交互。 内核模块与这些钩子上的 iptables 寄存器相关联,以确保流量符合防火墙规则规定的条件。

Netfilter Hooks

有五个 netfilter 钩子程序可以注册。 当数据包在堆栈中移动时,它们将触发在这些钩子中注册的内核模块。 数据包触发的钩子取决于数据包是传入的还是传出的,数据包的目的地,以及数据包在前一个点是否被丢弃或拒绝。

下面的钩子表示网络堆栈中各种定义良好的点:

  • Nfippre 路由: 在进入网络堆栈后不久,任何传入通信量都会触发这个钩子。 在作出任何路由决定之前,这个钩子被处理关于在哪里发送数据包。
  • Nf ip local in: 如果数据包的目的地是本地系统,则在传入数据包被路由之后触发该挂钩。
  • Nf ip forward: 如果要将数据包转发到另一台主机,则在传入数据包被路由之后触发该挂钩。
  • Nf ip local out: 这个钩子是由任何本地创建的出站流量触发的,只要它到达网络堆栈。
  • Nf ip post routing: 这个钩子是在路由发生之后以及在线路上发出之前由任何出发或转发的流量触发的。

希望在这些钩子上注册的内核模块必须提供一个优先级号,以帮助确定钩子被触发时它们被调用的顺序。 这为多个模块(或同一模块的多个实例)以确定性顺序连接到每个钩子提供了方法。 每个模块将依次被调用,并在处理完数据包后向 netfilter 框架返回一个决策,这个决策指出了应该对数据包做什么。

表和链

Iptables 防火墙使用表来组织它的规则。 这些表根据它们所做决定的类型对规则进行分类。 例如,如果一个规则处理网络地址转换,它将被放到 nat 表中。 如果使用规则来决定是否允许数据包继续到达目的地,那么它可能会被添加到过滤器表中。

在每个 iptables 表中,规则进一步组织在单独的“链”中。 虽然表是根据它们所持有的规则的一般目标来定义的,但是内置链表示触发它们的 netfilter 钩子。 链基本上决定了规则何时被评估。

正如你所看到的,内置链的名称反映了与它们相关联的 netfilter 钩子的名称:

  • Prerouting: 由 NF ip pre routing 钩子触发。
  • 输入: 由 NF ip local in 钩子触发。
  • Forward: 由 NF ip FORWARD 钩子触发。
  • 输出: 由 NF ip local out 钩子触发。
  • Postrouting: 由 NF ip post 路由钩子触发。

链允许管理员控制在数据包的传送路径中哪些地方需要评估规则。 由于每个表具有多个链,因此在处理过程中可以在多个点施加表的影响。 因为某些类型的决策只有在网络堆栈的某些点上才有意义,所以每个表不会为每个内核钩子注册一个链。

只有五个 netfilter 内核钩子,因此来自多个表的链在每个钩子处注册。 例如,三个表有 PREROUTING 链。 当这些链在相关的 NF ip pre routing 钩子上注册时,它们指定一个优先级,指定调用每个表的 PREROUTING 链的顺序。 在移动到下一个 PREROUTING 链之前,按顺序对最高优先级 PREROUTING 链中的每个规则进行评估。 我们一会儿就来看看每个链条的具体顺序。

哪些表格是可用的?

让我们回过头来看看 iptables 提供的不同表。 这些表示不同的规则集,按照关注区域组织,用于评估数据包。

过滤表

过滤器表是 iptables 中使用最广泛的表之一。 过滤器表用于决定是否让数据包继续到达其预期目的地或拒绝其请求。 用防火墙的说法,这就是所谓的“过滤”数据包。 这个表提供了人们在讨论防火墙时想到的大量功能。

Nat 表

Nat 表用于实现网络地址转换规则。 当数据包进入网络栈时,该表中的规则将决定是否以及如何修改数据包的源地址或目的地址,以便影响数据包和任何响应流量的路由方式。 当无法直接访问时,这通常用于将数据包路由到网络。

热轧工作台

Mangle 表用于以各种方式修改数据包的 IP 报头。 例如,您可以调整数据包的 TTL (生存时间)值,可以延长或缩短数据包可以维持的有效网络跃点数。 其他 IP 头也可以以类似的方式修改。

该表还可以在数据包上放置内核“标记” ,以便在其他表和其他网络工具中进行进一步处理。 这个标记并不接触实际的数据包,而是将这个标记添加到数据包的内核表示中。

原始表格

Iptables 防火墙是有状态的,这意味着根据数据包与前一个数据包的关系对数据包进行评估。 建立在 netfilter 框架之上的连接跟踪功能允许 iptables 将数据包视为正在进行的连接或会话的一部分,而不是一连串离散的、不相关的数据包。 连接跟踪逻辑通常在数据包到达网络接口后不久就应用。

原始表有一个非常狭义的定义函数。 它的唯一目的是提供一种标记数据包的机制,以便选择退出连接跟踪。

保安表

安全表用于在数据包上设置内部 SELinux 安全上下文标记,这将影响 SELinux 或其他可以解释 SELinux 安全上下文的系统处理数据包的方式。 这些标记可以应用于每个包或每个连接的基础上。

每个表中实现了哪些链?

我们已经分别讨论了表和链。 让我们来看一下每个表中有哪些链可用。 在这个讨论中隐含的是对注册到同一钩子上的链的求值顺序的进一步讨论。 如果三个表有 PREROUTING 链,它们按照哪个顺序进行评估?

下表显示了每个 iptable 中从左向右读取时可用的链。 例如,我们可以知道原始表同时具有 PREROUTING 和 OUTPUT 链。 当从上到下读取时,它还显示在触发相关的 netfilter 钩子时调用每个链的顺序。

有几件事应该注意。 在下面的表示中,nat 表被分为 DNAT 操作(那些改变数据包目的地址的操作)和 SNAT 操作(那些改变源地址的操作) ,以便更清楚地显示它们的排序。 我们还包括表示路由选择和连接跟踪的点的行,以便对正在发生的进程提供更全面的观点:

Tables↓/Chains→ PREROUTING INPUT FORWARD OUTPUT POSTROUTING
(routing decision)
raw
(connection tracking enabled)
mangle
nat (DNAT)
(routing decision)
filter
security
nat (SNAT)

作为一个数据包触发一个 netfilter 钩子,相关的链将被处理,因为它们从上到下列出在上面的表中。 信息包触发的钩子(列)取决于信息包是传入的还是传出的、所做的路由决定以及信息包是否通过过滤标准。

某些事件会导致在处理过程中跳过表链。 例如,只有连接中的第一个数据包将根据 NAT 规则进行计算。 为第一个数据包所做的任何自然决策都将应用于连接中的所有后续数据包,而不需要进行额外的计算。 对 NAT 连接的响应将自动将反向 NAT 规则应用于正确的路由。

链遍历顺序

假设服务器知道如何路由一个数据包,并且防火墙规则允许它的传输,下面的流代表了在不同情况下要经过的路径:

  • 前往本地系统的传入数据包: PREROUTING-INPUT
  • 前往另一台主机的传入数据包: PREROUTING-FORWARD-POSTROUTING
  • 本地生成的数据包: OUTPUT-POSTROUTING

如果我们将上面的信息与前面表格中的排序结合起来,我们可以看到一个发往本地系统的传入数据包将首先根据原始表、冲压表和 nat 表的 PREROUTING 链进行评估。 然后,它将遍历 mangle、 filter、 security 和 nat 表的 INPUT 链,最后将其传递到本地套接字。

Iptables 规则

规则放置在特定表的特定链中。 当调用每个链时,将按顺序根据链中的每个规则检查所涉及的包。 每个规则都有一个匹配的组件和一个操作组件。

配对

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

匹配系统非常灵活,可以使用系统上可用的 iptables 扩展进行显著扩展。 规则可以根据协议类型、目的地或源地址、目的地或源端口、目的地或源网络、输入或输出接口、报头或连接状态等标准进行构造。 这些可以组合起来创建相当复杂的规则集,以区分不同的流量。

目标

目标是当数据包满足规则的匹配条件时触发的动作。 目标一般分为两类:

  • 终止目标: 终止目标执行一个操作,该操作终止链中的计算,并将控制权返回给 netfilter 钩子。 根据所提供的返回值,钩子可能会丢弃数据包或允许数据包继续进行下一个处理阶段。
  • 非终止目标: 非终止目标在链中执行操作并继续评估。 虽然每个链最终必须传回最终终止决策,但是可以预先执行任意数量的非终止目标。

规则中每个目标的可用性将取决于上下文。 例如,表和链类型可能规定可用的目标。 规则中激活的扩展和匹配子句也会影响目标的可用性。

跳转到用户自定义链

我们应该提到一类特殊的非终止目标: 跳转目标。 跳转目标是导致评估移动到不同链以进行额外处理的操作。 我们已经讨论了很多关于内置链,它们紧密地绑在叫它们的网过滤钩上。 但是,iptables 还允许管理员为组织目的创建自己的链。

规则可以放置在用户定义的链中,就像它们可以放置在内置链中一样。 不同之处在于,用户定义的链只能通过从规则“跳转”到它们(它们本身没有用 netfilter hook 注册)。

用户定义链作为调用它们的链的简单扩展。 例如,在用户定义的链中,如果到达规则列表的末尾,或者如果一个 RETURN 目标被匹配的规则激活,则计算将返回到调用链。 评估还可以跳转到其他用户定义的链。

这个结构允许更好的组织,并且为更健壮的分支提供了必要的框架。

Iptables 和连接跟踪

在讨论原始表和连接状态匹配准则时,介绍了在 netfilter 框架上实现的连接跟踪系统。 连接跟踪允许 iptable 对正在进行的连接上下文中查看的数据包做出决定。 连接跟踪系统为 iptables 提供了执行“有状态”操作所需的功能。

连接跟踪是在数据包进入网络堆栈后很快应用的。 原始表链和一些基本的健全性检查是在将数据包与连接关联之前对数据包执行的唯一逻辑。

系统根据一组现有连接检查每个数据包。 如果需要,它将更新其存储中的连接状态,并在必要时添加到系统的新连接。 在一个原始链中用 NOTRACK 目标标记的数据包将绕过连接跟踪例程。

可用国家

连接跟踪系统跟踪的连接将处于以下状态之一:

  • 新: 当一个数据包到达时并不与现有的连接相关联,但作为第一个数据包并不无效时,将使用这个标签向系统添加一个新的连接。 这种情况发生在连接感知的协议(如 TCP)和无连接的协议(如 UDP)中。
  • Established: 当连接接收到相反方向的有效响应时,将连接从 NEW 更改为 ESTABLISHED。 对于 TCP 连接,这意味着 syn / ack,对于 UDP 和 ICMP 流量,这意味着原始数据包的源和目的地被交换的响应。
  • 相关: 不是现有连接的一部分,但是与系统中已有的连接相关联的数据包被标记为 RELATED。 这可能意味着一个辅助连接,就像 FTP / 数据传输连接一样,或者它可能是 ICMP 对其他协议的连接尝试的响应。
  • 无效: 如果数据包与现有连接没有关联,不适合打开新连接,如果无法识别,或者由于其他原因数据包不可路由,则可以标记为无效。
  • Untracked: 如果数据包已经在原始表链中成为目标以绕过跟踪,则可以将其标记为 UNTRACKED。
  • Snat: 源地址被 NAT 操作改变时的虚拟状态集。 这是连接跟踪系统使用的,因此它知道在应答数据包中更改源地址。
  • Dnat: 当目的地址被 NAT 操作改变时的虚拟状态设置。 这是连接跟踪系统使用的,以便它知道在路由应答数据包时将目标地址更改回来。

连接跟踪系统中跟踪的状态允许管理员制定针对连接生命周期中特定点的规则。 这为更彻底和安全的规则提供了所需的功能。

总结

Netfilter 包过滤框架和 iptables 防火墙是 Linux 服务器上大多数防火墙解决方案的基础。 Netfilter 内核钩子离网络堆栈足够近,可以在数据包被系统处理时提供强大的控制。 Iptables 防火墙利用这些功能提供一种灵活的、可扩展的方法,将策略需求传递给内核。 通过了解这些部分如何组合在一起,您可以更好地利用它们来控制和保护您的服务器环境。

如果您想更多地了解如何选择有效的 iptables 策略,请查看本指南。

这些指南可以帮助你开始实现你的 iptables 防火墙规则:

  • 如何在 Ubuntu 14.04上使用 Iptables 建立防火墙
  • Iptables 要点: 通用防火墙规则和命令
  • 如何在 Ubuntu 14.04上使用 Iptables 实现基本防火墙模板
  • 如何设置 Iptables 防火墙来保护服务器之间的通信