第 2 章 nftables 入门


nftables 框架对数据包进行分类,它是 iptablesip6tablesarptablesebtablesipset 实用程序的后续者。与之前的数据包过滤工具相比,它在方便、特性和性能方面提供了大量改进,最重要的是:

  • 内置查找表而不是线性处理
  • IPv4IPv6 协议的单一框架
  • 规则会以一个整体被应用,而不是分为抓取、更新和存储完整的规则集的步骤
  • 支持在规则集(nftrace)和监控追踪事件(nft)中调试和追踪
  • 更加一致和压缩的语法,没有特定协议的扩展
  • 用于第三方应用程序的 Netlink API

nftables 框架使用表来存储链。链包含执行动作的独立规则。nft 工具替换了之前数据包过滤框架中的所有工具。您可以使用 libnftnl 库通过 libmnl 库来处理 nftables Netlink API 的低级别交互。

要显示规则集变化的影响,请使用 nft list ruleset 命令。由于这些工具向 nftables 规则集添加表、链、规则、集合和其他对象,请注意 nftables 规则集的操作(如 nft flush ruleset 命令)可能会影响使用 iptables 命令安装的规则集。

2.1. 创建和管理 nftables 表、链和规则

您可以显示 nftables 规则集并管理它们。

2.1.1. nftables 表的基础知识

nftables 中的表是一个包含链、规则、集合和其他对象集合的名字空间。

每个表都必须分配一个地址系列。地址系列定义此表处理的数据包类型。在创建表时,您可以设置以下地址系列之一:

  • ip:仅匹配 IPv4 数据包。如果没有指定地址系列,这是默认设置。
  • ip6 :仅匹配 IPv6 数据包.
  • inet:匹配 IPv4 和 IPv6 数据包。
  • arp:匹配 IPv4 地址解析协议(ARP)数据包。
  • bridge:匹配通过网桥设备的数据包。
  • netdev:匹配来自 ingress 的数据包。

如果要添加表,所使用的格式取决于您的防火墙脚本:

  • 在原生语法的脚本中,使用:

    table <table_address_family> <table_name> {
    }
  • 在 shell 脚本中,使用:

    nft add table <table_address_family> <table_name>

2.1.2. nftables 链的基础知识

表由链组成,链又是规则的容器。存在以下两种规则类型:

  • 基本链 :您可以使用基本链作为来自网络堆栈的数据包的入口点。
  • 常规链 :您可以将常规链用作 jump 目标来更好地组织规则。

如果要向表中添加基本链,所使用的格式取决于您的防火墙脚本:

  • 在原生语法的脚本中,使用:

    table <table_address_family> <table_name> {
      chain <chain_name> {
        type <type> hook <hook> priority <priority>
        policy <policy> ;
      }
    }
  • 在 shell 脚本中,使用:

    nft add chain <table_address_family> <table_name> <chain_name> { type <type> hook <hook> priority <priority> \; policy <policy> \; }

    为了避免 shell 将分号解释为命令的结尾,请将 \ 转义字符放在分号前面。

这两个示例都创建 基本链。要创建 常规链,请不要在大括号中设置任何参数。

链类型

以下是链类型以及您可以使用的地址系列和钩子的概述:

类型地址系列钩子描述

filter

all

all

标准链类型

nat

ip,ip6,inet

preroutinginputoutputpostrouting

这个类型的链根据连接跟踪条目执行原生地址转换。只有第一个数据包会遍历此链类型。

route

ip,ip6

output

如果 IP 头的相关部分已更改,则接受的遍历此链类型的数据包会导致新的路由查找。

链优先级

priority 参数指定数据包遍历具有相同 hook 值的链的顺序。您可以将此参数设为整数值,或使用标准优先级名称。

以下列表是标准优先级名称及其数字值的一个概述,以及您可以使用它们的哪个地址系列和钩子:

文本值数字值地址系列钩子

raw

-300

ip,ip6,inet

all

mangle

-150

ip,ip6,inet

all

dstnat

-100

ip,ip6,inet

prerouting

-300

bridge

prerouting

filter

0

ip,ip6,inet,arp,netdev

all

-200

bridge

all

安全

50

ip,ip6,inet

all

srcnat

100

ip,ip6,inet

postrouting

300

bridge

postrouting

out

100

bridge

output

链策略

如果此链中的规则没有指定任何操作,则链策略定义 nftables 是否应该接受或丢弃数据包。您可以在链中设置以下策略之一:

  • accept (默认)
  • drop

2.1.3. nftables 规则的基础知识

规则定义对通过包含此规则的链的数据包执行的操作。如果规则还包含匹配表达式,则 nftables 仅在所有之前的表达式都应用时才执行操作。

如果要在链中添加一条规则,所使用的格式取决于您的防火墙脚本:

  • 在原生语法的脚本中,使用:

    table <table_address_family> <table_name> {
      chain <chain_name> {
        type <type> hook <hook> priority <priority> ; policy <policy> ;
          <rule>
      }
    }
  • 在 shell 脚本中,使用:

    nft add rule <table_address_family> <table_name> <chain_name> <rule>

    此 shell 命令在链的末尾附加新规则。如果要在链的开头添加一条规则,请使用 nft insert 命令而不是 nft add

2.1.4. 使用 nft 命令管理表、链和规则

要在命令行上或 shell 脚本中管理 nftables 防火墙,请使用 nft 工具。

重要

此流程中的命令不代表典型的工作流,且没有被优化。此流程只演示了如何使用 nft 命令来管理表、链和规则。

流程

  1. 创建一个带有 inet 地址系列的名为 nftables_svc 的表,以便表可以处理 IPv4 和 IPv6 数据包:

    # nft add table inet nftables_svc
  2. 将处理传入网络流量的、名为 INPUT 的基本链添加到 inet nftables_svc 表中:

    # nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }

    为了避免 shell 将分号解释为命令的结尾,请使用 \ 字符转义分号。

  3. INPUT 链添加规则。例如,允许端口 22 和 443 上的传入 TCP 流量,并作为 INPUT 链的最后一条规则,拒绝其他传入的流量,并伴有互联网控制消息协议(ICMP)端口无法访问的消息:

    # nft add rule inet nftables_svc INPUT tcp dport 22 accept
    # nft add rule inet nftables_svc INPUT tcp dport 443 accept
    # nft add rule inet nftables_svc INPUT reject with icmpx type port-unreachable

    如果您输入 nft add rule 命令,则nft 会将按与运行命令相同的顺序将规则添加到链。

  4. 显示包括句柄的当前规则集:

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 443 accept # handle 3
        reject # handle 4
      }
    }
  5. 在句柄为 3 的现有规则前面插入一条规则。例如,要插入一个允许端口 636 上 TCP 流量的规则,请输入:

    # nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept
  6. 在句柄为 3 的现有规则后面附加一条规则。例如,要插入一个允许端口 80 上 TCP 流量的规则,请输入:

    # nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept
  7. 再次显示带有 handle 的规则集。验证是否后添加的规则已添加到指定位置:

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 636 accept # handle 5
        tcp dport 443 accept # handle 3
        tcp dport 80 accept # handle 6
        reject # handle 4
      }
    }
  8. 删除 handle 为 6 的规则:

    # nft delete rule inet nftables_svc INPUT handle 6

    要删除规则,您必须指定 handle。

  9. 显示规则集,并验证删除的规则是否不再存在:

    # nft -a list table inet nftables_svc
    table inet nftables_svc { # handle 13
      chain INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        tcp dport 22 accept # handle 2
        tcp dport 636 accept # handle 5
        tcp dport 443 accept # handle 3
        reject # handle 4
      }
    }
  10. INPUT 链中删除所有剩余的规则:

    # nft flush chain inet nftables_svc INPUT
  11. 显示规则集,并验证 INPUT 链是否为空:

    # nft list table inet nftables_svc
    table inet nftables_svc {
      chain INPUT {
        type filter hook input priority filter; policy accept
      }
    }
  12. 删除 INPUT 链:

    # nft delete chain inet nftables_svc INPUT

    您还可以使用此命令删除仍然包含规则的链。

  13. 显示规则集,并验证 INPUT 链是否已被删除:

    # nft list table inet nftables_svc
    table inet nftables_svc {
    }
  14. 删除 nftables_svc 表:

    # nft delete table inet nftables_svc

    您还可以使用此命令删除仍然包含链的表。

    注意

    要删除整个规则集,请使用 nft flush ruleset 命令,而不是在单独的命令中手动删除所有规则、链和表。

其他资源

您系统上的 nft (8) 手册页

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.