第 8 章 nftables 入门
nftables
框架对数据包进行分类,它是 iptables
、ip6tables
、arptables
、ebtables
和 ipset
实用程序的后续者。与之前的数据包过滤工具相比,它在方便、特性和性能方面提供了大量改进,最重要的是:
- 内置查找表而不是线性处理
-
IPv4
和IPv6
协议的单一框架 - 规则会以一个整体被应用,而不是分为抓取、更新和存储完整的规则集的步骤
-
支持在规则集(
nftrace
)和监控追踪事件(nft
)中调试和追踪 - 更加一致和压缩的语法,没有特定协议的扩展
- 用于第三方应用程序的 Netlink API
nftables
框架使用表来存储链。链包含执行动作的独立规则。nft
工具替换了之前数据包过滤框架中的所有工具。您可以使用 libnftnl
库通过 libmnl
库来处理 nftables
Netlink API 的低级别交互。
要显示规则集变化的影响,请使用 nft list ruleset
命令。由于这些工具向 nftables
规则集添加表、链、规则、集合和其他对象,请注意 nftables
规则集的操作(如 nft flush ruleset
命令)可能会影响使用 iptables
命令安装的规则集。
8.1. 创建和管理 nftables 表、链和规则
您可以显示 nftables
规则集并管理它们。
8.1.1. nftables 表的基础知识
nftables
中的表是一个包含链、规则、集合和其他对象集合的名字空间。
每个表都必须分配一个地址系列。地址系列定义了此表进程的数据包类型。在创建表时,您可以设置以下地址系列之一:
-
ip
:仅匹配 IPv4 数据包。如果没有指定地址系列,这是默认设置。 -
ip6
:仅匹配 IPv6 数据包。 -
inet
:匹配 IPv4 和 IPv6 数据包。 -
arp
:匹配 IPv4 地址解析协议(ARP)数据包。 -
bridge
:匹配通过网桥设备的数据包。 -
netdev
:匹配来自入口的数据包。
如果要添加表,要使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
table <table_address_family> <table_name> { }
在 shell 脚本中,使用:
nft add table <table_address_family> <table_name>
8.1.2. nftables 链的基础知识
表由链组成,后者是规则的容器。存在以下两种规则类型:
- 基本链 :您可以使用基本链作为来自网络堆栈的数据包的入口点。
-
常规链 :您可以使用常规链作为
跳板
目标来更好地组织规则。
如果要在表中添加基本链,要使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
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 将分号解释为命令的结尾,请在分号的前面放置
\
转义字符。
这两个示例都创建了 基本链。要创建 常规链,请不要在大括号中设置任何参数。
链类型
以下是链类型以及您可以使用的地址系列和 hook 概述:
类型 | 地址系列 | Hook | 描述 |
---|---|---|---|
| all | all | 标准链类型 |
|
|
| 这个类型的链根据连接跟踪条目执行原生地址转换。只有第一个数据包遍历此链类型。 |
|
|
| 如果 IP 标头的相关部分已更改,则遍历此链类型的数据包会导致新的路由查找。 |
链优先级
priority 参数指定数据包使用相同的 hook 值遍历链的顺序。您可以将此参数设置为整数值,或使用标准优先级名称。
以下列表概述了标准优先级名称及其数字值,您可以使用哪个地址系列和 hook:
文本值 | 数字值 | 地址系列 | Hook |
---|---|---|---|
|
|
| all |
|
|
| all |
|
|
|
|
|
|
| |
|
|
| all |
|
| all | |
|
|
| all |
|
|
|
|
|
|
| |
|
|
|
|
链策略
链策略定义 nftables
是否应该接受或丢弃数据包(如果此链中的规则没有指定任何操作)。您可以在链中设置以下策略之一:
-
accept
(默认) -
drop
8.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
。
8.1.4. 使用 nft 命令管理表、链和规则
要在命令行或 shell 脚本中管理 nftables
防火墙,请使用 nft
工具。
此流程中的命令不代表典型的工作流,且不会被优化。此流程演示了如何使用 nft
命令管理表、链和规则。
流程
使用
inet
地址系列创建一个名为nftables_svc
的表,以便表可以处理 IPv4 和 IPv6 数据包:# nft add table inet nftables_svc
将名为
INPUT
的基本链(用于处理传入的网络流量)添加到inet nftables_svc
表中:# nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }
为了避免 shell 将分号解释为命令的结尾,请使用
\
字符转义分号。向
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
会将规则按与运行命令相同的顺序添加规则。显示包括句柄的当前规则集:
# 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 } }
在带有句柄 3 的现有规则前面插入规则。例如,要插入一个允许端口 636 上 TCP 流量的规则,请输入:
# nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept
使用句柄 3 在现有规则后面附加规则。例如,要插入一个允许端口 80 上 TCP 流量的规则,请输入:
# nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept
再次使用 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 } }
删除带有句柄 6 的规则:
# nft delete rule inet nftables_svc INPUT handle 6
要删除规则,您必须指定句柄。
显示规则集,并验证删除的规则不再存在:
# 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 } }
从
INPUT
链中删除所有剩余的规则:# nft flush chain inet nftables_svc INPUT
显示规则集,并验证
INPUT
链是否为空:# nft list table inet nftables_svc table inet nftables_svc { chain INPUT { type filter hook input priority filter; policy accept } }
删除
INPUT
链:# nft delete chain inet nftables_svc INPUT
您还可以使用此命令删除仍然包含规则的链。
显示规则集,并验证
INPUT
链已被删除:# nft list table inet nftables_svc table inet nftables_svc { }
删除
nftables_svc
表:# nft delete table inet nftables_svc
您还可以使用此命令删除仍然包含链的表。
注意要删除整个规则集,请使用
nft flush ruleset
命令,而不是手动删除独立命令中的所有规则、链和表。
其他资源
您系统上的 nft (8)
手册页