23.6. 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
命令安装的规则集。
23.6.1. 创建和管理 nftables 表、链和规则 复制链接链接已复制到粘贴板!
您可以显示 nftables
规则集并管理它们。
23.6.1.1. nftables 表的基础知识 复制链接链接已复制到粘贴板!
nftables
中的表是一个包含链、规则、集合和其他对象集合的名字空间。
每个表都必须分配一个地址系列。地址系列定义此表处理的数据包类型。在创建表时,您可以设置以下地址系列之一:
-
ip
:仅匹配 IPv4 数据包。如果没有指定地址系列,这是默认设置。 -
ip6
:仅匹配 IPv6 数据包. -
inet
:匹配 IPv4 和 IPv6 数据包。 -
arp
:匹配 IPv4 地址解析协议(ARP)数据包。 -
bridge
:匹配通过网桥设备的数据包。 -
netdev
:匹配来自 ingress 的数据包。
如果要添加表,所使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
table <table_address_family> <table_name> { }
table <table_address_family> <table_name> { }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在 shell 脚本中,使用:
nft add table <table_address_family> <table_name>
nft add table <table_address_family> <table_name>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.1.2. nftables 链的基础知识 复制链接链接已复制到粘贴板!
表由链组成,链又是规则的容器。存在以下两种规则类型:
- 基本链 :您可以使用基本链作为来自网络堆栈的数据包的入口点。
-
常规链 :您可以将常规链用作
jump
目标来更好地组织规则。
如果要向表中添加基本链,所使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在 shell 脚本中,使用:
nft add chain <table_address_family> <table_name> <chain_name> { type <type> hook <hook> priority <priority> \; policy <policy> \; }
nft add chain <table_address_family> <table_name> <chain_name> { type <type> hook <hook> priority <priority> \; policy <policy> \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 为了避免 shell 将分号解释为命令的结尾,请将
\
转义字符放在分号前面。
这两个示例都创建 基本链。要创建 常规链,请不要在大括号中设置任何参数。
链类型
以下是链类型以及您可以使用的地址系列和钩子的概述:
类型 | 地址系列 | 钩子 | 描述 |
---|---|---|---|
| all | all | 标准链类型 |
|
|
| 这个类型的链根据连接跟踪条目执行原生地址转换。只有第一个数据包会遍历此链类型。 |
|
|
| 如果 IP 头的相关部分已更改,则接受的遍历此链类型的数据包会导致新的路由查找。 |
链优先级
priority 参数指定数据包遍历具有相同 hook 值的链的顺序。您可以将此参数设为整数值,或使用标准优先级名称。
以下列表是标准优先级名称及其数字值的一个概述,以及您可以使用它们的哪个地址系列和钩子:
文本值 | 数字值 | 地址系列 | 钩子 |
---|---|---|---|
|
|
| all |
|
|
| all |
|
|
|
|
|
|
| |
|
|
| all |
|
| all | |
|
|
| all |
|
|
|
|
|
|
| |
|
|
|
|
链策略
链策略定义 nftables
是否应该接受或丢弃数据包(如果此链中的规则没有指定任何操作)。您可以在链中设置以下策略之一:
-
accept
(默认) -
drop
23.6.1.3. nftables 规则的基础知识 复制链接链接已复制到粘贴板!
规则定义要在传递包含此规则的链的数据包上执行操作。如果规则还包含匹配的表达式,nftables
仅在所有之前的表达式都应用时才执行操作。
如果要在链中添加规则,要使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在 shell 脚本中,使用:
nft add rule <table_address_family> <table_name> <chain_name> <rule>
nft add rule <table_address_family> <table_name> <chain_name> <rule>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 此 shell 命令在链末尾附加新规则。如果要在链开始时添加规则,请使用
nft insert
命令而不是nft add
。
23.6.1.4. 使用 nft 命令管理表、链和规则 复制链接链接已复制到粘贴板!
要在命令行或 shell 脚本中管理 nftables
防火墙,请使用 nft
工具。
此流程中的命令不代表典型的工作流,且不会被优化。此流程演示了如何使用 nft
命令管理表、链和规则。
流程
使用
inet
地址系列创建一个名为nftables_svc
的表,以便表可以处理 IPv4 和 IPv6 数据包:nft add table inet nftables_svc
# nft add table inet nftables_svc
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 将名为
INPUT
的基本链(用于处理传入的网络流量)添加到inet nftables_svc
表中:nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }
# nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 为了避免 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 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
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果您输入
nft add rule
命令,nft
会将规则按与运行命令相同的顺序添加规则。显示包括句柄的当前规则集:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在带有句柄 3 的现有规则前面插入规则。例如,要插入一个允许端口 636 上 TCP 流量的规则,请输入:
nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept
# nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用句柄 3 在现有规则后面附加规则。例如,要插入一个允许端口 80 上 TCP 流量的规则,请输入:
nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept
# nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 再次使用 handle 显示规则集。验证后续添加的规则是否已添加到指定位置:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 删除带有句柄 6 的规则:
nft delete rule inet nftables_svc INPUT handle 6
# nft delete rule inet nftables_svc INPUT handle 6
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 要删除规则,您必须指定句柄。
显示规则集,并验证删除的规则不再存在:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 从
INPUT
链中删除所有剩余的规则:nft flush chain inet nftables_svc INPUT
# nft flush chain inet nftables_svc INPUT
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示规则集,并验证
INPUT
链是否为空:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 删除
INPUT
链:nft delete chain inet nftables_svc INPUT
# nft delete chain inet nftables_svc INPUT
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 您还可以使用此命令删除仍然包含规则的链。
显示规则集,并验证
INPUT
链已被删除:nft list table inet nftables_svc
# nft list table inet nftables_svc table inet nftables_svc { }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 删除
nftables_svc
表:nft delete table inet nftables_svc
# nft delete table inet nftables_svc
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 您还可以使用此命令删除仍然包含链的表。
注意要删除整个规则集,请使用
nft flush ruleset
命令,而不是手动删除独立命令中的所有规则、链和表。
23.6.2. 从 iptables 迁移到 nftables 复制链接链接已复制到粘贴板!
如果您的防火墙配置仍然使用 iptables
规则,则您可以将 iptables
规则迁移到 nftables
。
23.6.2.1. 使用 firewalld、nftables 或者 iptables 时 复制链接链接已复制到粘贴板!
以下是您应该使用以下工具之一的概述:
-
firewalld
:使用firewalld
实用程序进行简单防火墙用例。此工具易于使用,并涵盖了这些场景的典型用例。 -
nftables
:使用nftables
实用程序设置复杂和高性能的防火墙,如为整个网络设置。 -
iptables
:Red Hat Enterprise Linux 上的iptables
工具使用nf_tables
内核 API 而不是传统的
后端。Thenf_tables
API 提供向后兼容性,因此使用iptables
命令的脚本仍可在 Red Hat Enterprise Linux 上工作。对于新的防火墙脚本,红帽建议使用nftables
。
要防止不同的与防火墙相关的服务(firewalld
、nftables
或 iptables
)相互影响,请在 RHEL 主机上仅运行其中一个服务,并禁用其他服务。
23.6.2.2. nftables 框架中的概念 复制链接链接已复制到粘贴板!
与 iptables
框架相比,nftables
提供了更加现代化、高效且更灵活的替代选择。与 iptables
相比,有几个提供高级功能和改进的概念和功能。这些增强功能简化了规则管理,并改进性能,使 nftables
成为复杂和高性能网络环境的现代替代方案。
nftables
框架包含以下组件:
- 表和命名空间
-
在
nftables
中,表代表组织单元或命名空间,它们将相关的防火墙链、集合、流tables 和其他对象分组在一起。在nftables
中,表提供了一种更灵活的方法来结构防火墙规则和相关组件。在iptables
中,表更严格地定义在特定目的。 - 表系列
-
nftables
中的每个表都与特定系列关联(ip
、ip6
、inet
、arp
、bridge
或netdev
)。此关联决定了表可以处理哪些数据包。例如,ip
系列中的一个表只处理 IPv4 数据包。另一方面,inet
是表系列的特殊案例。它提供了跨协议的统一方法,因为它可以处理 IPv4 和 IPv6 数据包。特殊表系列的另一个情况是netdev
,因为它用于直接应用到网络设备的规则,从而在设备级别上启用过滤。 - 基本链
nftables
中的基本链是数据包处理管道中高度可配置的入口点,允许用户指定以下内容:- 链的类型,如 "filter"
- 数据包处理路径中的 hook 点,如 "input", "output", "forward"
- 链的优先级
通过这种灵活性,可以精确控制规则在通过网络堆栈时应用到数据包的时间和方式。链的一种特殊情况是
路由
链,用于根据数据包标头影响内核提出的路由决策。- 用于规则处理的虚拟机
-
nftables
框架使用内部虚拟机来处理规则。此虚拟机执行与装配语言操作类似的指令(将数据加载到寄存器中,执行比较等)。这种机制可以实现高度灵活、高效的规则处理。
nftables
中的增强功能可以作为该虚拟机的新指令引入。这通常需要一个新的内核模块,并对 libnftnl
库和 nft
命令行工具进行更新。
或者,您可以通过将现有指令以创新方式结合来引进新功能,而无需进行内核修改。nftables
规则的语法反映了底层虚拟机的灵活性。例如:规则 meta mark set tcp dport map { 22:1, 80:2 }
将数据包的防火墙标记设置为 1 (如果 TCP 目的地端口为 22),如果端口为 80,则设置为 2。这展示了如何简洁地表达复杂逻辑。
- 实践课程学习和增强
-
nftables
框架集成并扩展ipset
工具的功能,用于iptables
在 IP 地址、端口、其他数据类型上批量匹配,最重要的是,其中的组合。此集成可让您在nftables
中直接管理大量和动态数据集。接下来,nftables
原生支持基于任何数据类型的多个值或范围匹配的数据包,这增强了其处理复杂过滤要求的能力。使用nftables
,您可以操作数据包中的任何字段。
在 nftables
中,集合可以命名为 或 anonymous。命名的集合可由多个规则引用并动态修改。匿名集合在规则内内联定义,并且是不可变的。集合可以包含组合不同类型的元素,如 IP 地址和端口号对。此功能在匹配复杂标准方面提供了更大的灵活性。要管理集合,内核可以根据特定要求(性能、内存效率等)选择最合适的后端。设置也可以使用键值对作为映射。value 部分可用作数据点(写入数据包标头的值),或者作为要跳到的链的值。这可启用复杂和动态规则行为,称为"verdict 映射"。
- 灵活的规则格式
-
nftables
规则的结构非常简单。条件和操作从左到右应用。这种直观的格式简化了创建和故障排除的规则。
规则中的条件在逻辑上连接(与 AND 运算符)一起,这意味着所有条件都必须评估为 "true" 才能匹配的规则。如果有任何条件失败,评估将移到下一个规则。
nftables
中的操作可以是最终的操作,如 drop
或 accept
,这样可停止对数据包进行进一步处理。非终端操作,如 计数器日志元标记设置 0x3
,执行特定的任务(计算数据包、日志记录、设置标记等),但允许评估后续规则。
23.6.2.3. 弃用的 iptables 框架中的概念 复制链接链接已复制到粘贴板!
与主动维护的 nftables
框架类似,弃用的 iptables
框架允许您执行各种数据包过滤任务、日志记录和审计、与 NAT 相关的配置任务等。
iptables
框架由多个表组成,每个表都为特定目的设计:
filter
- 默认表确保常规数据包过滤
nat
- 对于网络地址转换(NAT),包括更改数据包的源和目标地址
mangle
- 对于特定的数据包更改,您可以针对高级路由决策对数据包标头进行修改
raw
- 对于在连接跟踪前需要发生的配置
这些表作为单独的内核模块实施,其中每个表都提供一组固定的内置链,如 INPUT
、OUTPUT
和 FORWARD
。链是指对数据包进行评估的规则序列。这些将 hook 链在内核中数据包处理流中的特定点。链在不同的表中具有相同的名称,但它们的执行顺序由相应的 hook 优先级决定。优先级由内核在内部管理,以确保规则以正确的序列应用。
最初,iptables
旨在处理 IPv4 流量。但是,由于 IPv6 协议的出现,需要引入 ip6tables
工具来提供可比较功能(作为 iptables
),并允许用户创建和管理 IPv6 数据包的防火墙规则。使用相同的逻辑,创建了 arptables
工具来处理地址解析协议(ARP),并且为处理以太网桥接帧而开发了 ebtables
工具。这些工具可确保您可以在各种网络协议中应用 iptables
的数据包过滤功能,并提供全面的网络覆盖。
为增强 iptables
的功能,可以开始开发的扩展。功能扩展通常作为与用户空间动态共享对象(DSO)配对的内核模块实现。扩展引入了"匹配"和"目标",您可以在防火墙规则中使用它们来执行更复杂的操作。扩展可以启用复杂的匹配和目标。例如,您可以匹配或操作特定的第 4 层协议标头值,执行速率限制、强制实施配额等。某些扩展旨在解决默认的 iptables
语法中的限制,如"多端口"匹配扩展。此扩展允许单个规则与多个非安全端口匹配,以简化规则定义,从而减少所需的单个规则数量。
ipset
是 iptables
的特殊功能扩展。这是一个内核级别的数据结构,它与 iptables
一起使用来创建与数据包匹配的 IP 地址、端口号和其他与网络相关的元素集合。这些设置可显著简化、优化并加快编写和管理防火墙规则的过程。
23.6.2.4. 将 iptables 和 ip6tables 规则集转换为 nftables 复制链接链接已复制到粘贴板!
使用 iptables-restore-translate
和 ip6tables-restore-translate
实用程序将 iptables
和 ip6tables
规则集转换为 nftables
。
先决条件
-
已安装
nftables
和iptables
软件包。 -
系统配置了
iptables
和ip6tables
规则。
流程
将
iptables
和ip6tables
规则写入一个文件:iptables-save >/root/iptables.dump ip6tables-save >/root/ip6tables.dump
# iptables-save >/root/iptables.dump # ip6tables-save >/root/ip6tables.dump
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 将转储文件转换为
nftables
指令:iptables-restore-translate -f /root/iptables.dump > /etc/nftables/ruleset-migrated-from-iptables.nft ip6tables-restore-translate -f /root/ip6tables.dump > /etc/nftables/ruleset-migrated-from-ip6tables.nft
# iptables-restore-translate -f /root/iptables.dump > /etc/nftables/ruleset-migrated-from-iptables.nft # ip6tables-restore-translate -f /root/ip6tables.dump > /etc/nftables/ruleset-migrated-from-ip6tables.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
检查,如果需要,手动更新生成的
nftables
规则。 要启用
nftables
服务来加载生成的文件,请在/etc/sysconfig/nftables.conf
文件中添加以下内容:include "/etc/nftables/ruleset-migrated-from-iptables.nft" include "/etc/nftables/ruleset-migrated-from-ip6tables.nft"
include "/etc/nftables/ruleset-migrated-from-iptables.nft" include "/etc/nftables/ruleset-migrated-from-ip6tables.nft"
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 停止并禁用
iptables
服务:systemctl disable --now iptables
# systemctl disable --now iptables
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果您使用自定义脚本加载
iptables
规则,请确保脚本不再自动启动并重新引导以刷新所有表。启用并启动
nftables
服务:systemctl enable --now nftables
# systemctl enable --now nftables
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
验证
显示
nftables
规则集:nft list ruleset
# nft list ruleset
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.2.5. 将单个 iptables 和 ip6tables 规则转换为 nftables 复制链接链接已复制到粘贴板!
Red Hat Enterprise Linux 提供了 iptables-translate
和 ip6tables-translate
工具来将 iptables
或 ip6tables
规则转换为与 nftables
相同的规则。
先决条件
-
已安装
nftables
软件包。
流程
使用
iptables-translate
或ip6tables-translate
程序而不是iptables
或ip6tables
显示对应的nftables
规则,例如:iptables-translate -A INPUT -s 192.0.2.0/24 -j ACCEPT
# iptables-translate -A INPUT -s 192.0.2.0/24 -j ACCEPT nft add rule ip filter INPUT ip saddr 192.0.2.0/24 counter accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 请注意,一些扩展可能缺少响应的转换支持。在这些情况下,实用程序会输出以
#
符号为前缀的未转换规则,例如:iptables-translate -A INPUT -j CHECKSUM --checksum-fill
# iptables-translate -A INPUT -j CHECKSUM --checksum-fill nft # -A INPUT -j CHECKSUM --checksum-fill
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.2.6. 常见的 iptables 和 nftables 命令的比较 复制链接链接已复制到粘贴板!
以下是常见 iptables
和 nftables
命令的比较:
列出所有规则:
Expand iptables nftables iptables-save
nft list ruleset
列出某个表和链:
Expand iptables nftables iptables -L
nft list table ip filter
iptables -L INPUT
nft list chain ip filter INPUT
iptables -t nat -L PREROUTING
nft list chain ip nat PREROUTING
nft
命令不会预先创建表和链。只有当用户手动创建它们时它们才会存在。列出 firewalld 生成的规则:
nft list table inet firewalld nft list table ip firewalld nft list table ip6 firewalld
# nft list table inet firewalld # nft list table ip firewalld # nft list table ip6 firewalld
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.3. 使用 nftables 配置 NAT 复制链接链接已复制到粘贴板!
有了 nftables
,您就可以配置以下网络地址转换(NAT)类型:
- 伪装
- 源 NAT(SNAT)
- 目标 NAT(DNAT)
- 重定向
不支持在 iifname
和 oifname
参数中使用实际接口名称,以及备用名称(altname
)。
23.6.3.1. NAT 类型 复制链接链接已复制到粘贴板!
这些是不同的网络地址转换(NAT)类型:
- 伪装和源 NAT(SNAT)
使用以上 NAT 类型之一更改数据包的源 IP 地址。例如,互联网服务提供商(ISP)不会路由私有 IP 范围,如
10.0.0.0/8
。如果您在网络中使用私有 IP 范围,用户应该能够访问互联网上的服务器,请将来自这些范围的数据包的源 IP 地址映射为公共 IP 地址。伪装和 SNAT 相互类似。不同之处是:
- 伪装自动使用传出接口的 IP 地址。因此,如果传出接口使用了动态 IP 地址,则使用伪装。
- SNAT 将数据包的源 IP 地址设置为指定的 IP 地址,且不会动态查找传出接口的 IP 地址。因此,SNAT 要比伪装更快。如果传出接口使用了固定 IP 地址,则使用 SNAT。
- 目标 NAT(DNAT)
- 使用此 NAT 类型重写传入数据包的目标地址和端口。例如,如果您的 Web 服务器使用来自私有 IP 范围的 IP 地址,因此无法直接从互联网访问,您可以在路由器上设置 DNAT 规则,来将传入的流量重定向到此服务器。
- 重定向
- 这个类型是 IDT 的特殊示例,它根据链 hook 将数据包重定向到本地机器。例如,如果服务运行在与其标准端口不同的端口上,您可以将传入的流量从标准端口重定向到此特定端口。
23.6.3.2. 使用 nftables 配置伪装 复制链接链接已复制到粘贴板!
伪装使路由器动态地更改通过接口到接口 IP 地址发送的数据包的源 IP。这意味着,如果接口被分配了一个新 IP,nftables
会在替换源 IP 时自动使用新的 IP。
将通过 ens3
接口离开主机的数据包源 IP 替换为 ens3
上设置的 IP。
流程
创建一个表:
nft add table nat
# nft add table nat
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向表中添加
prerouting
和postrouting
链:nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要即使您没有向
prerouting
链中添加规则,nftables
框架也会要求此链与传入的数据包回复匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
postrouting
链中添加一条规则,来匹配ens3
接口上传出的数据包:nft add rule nat postrouting oifname "ens3" masquerade
# nft add rule nat postrouting oifname "ens3" masquerade
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.3.3. 使用 nftables 配置源 NAT 复制链接链接已复制到粘贴板!
在路由器中,源 NAT(SNAT)可让您将通过接口发送的数据包 IP 改为专门的 IP 地址。然后,路由器会替换传出数据包的源 IP。
流程
创建一个表:
nft add table nat
# nft add table nat
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向表中添加
prerouting
和postrouting
链:nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要即使您没有向
postrouting
链添加规则,nftables
框架也会要求此链与传出数据包回复相匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
postrouting
链中添加一条规则,该规则将使用192.0.2.1
替换通过ens3
的传出数据包的源 IP :nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1
# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.3.4. 使用 nftables 配置目标 NAT 复制链接链接已复制到粘贴板!
目标 NAT (DNAT)可让您将路由器上的流量重定向到无法直接从互联网访问的主机。
例如,有了 DNAT,路由器将发送给端口 80
和 443
的传入流量重定向到 IP 地址为 192.0.2.1
的 Web 服务器。
流程
创建一个表:
nft add table nat
# nft add table nat
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向表中添加
prerouting
和postrouting
链:nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要即使您没有向
postrouting
链添加规则,nftables
框架也会要求此链与传出数据包回复相匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
prerouting
链中添加一条规则,该规则将路由器的ens3
接口上端口80
和443
的传入流量重定向到 IP 地址为192.0.2.1
的 web 服务器:nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 根据您的环境,添加 SNAT 或伪装规则,将从 Web 服务器返回的数据包的源地址改为发送者:
如果
ens3
接口使用动态 IP 地址,请添加一条伪装规则:nft add rule nat postrouting oifname "ens3" masquerade
# nft add rule nat postrouting oifname "ens3" masquerade
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果
ens3
接口使用静态 IP 地址,请添加一条 SNAT 规则。例如,如果ens3
使用198.51.100.1
IP 地址:nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
启用数据包转发:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.3.5. 使用 nftables 配置重定向 复制链接链接已复制到粘贴板!
重定向
功能是目标网络地址转换(DNAT)的一种特殊情况,它根据链 hook 将数据包重定向到本地计算机。
例如,您可以将发送到本地主机端口 22
的流量重定向到端口 2222
。
流程
创建一个表:
nft add table nat
# nft add table nat
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向表中添加
prerouting
链:nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
prerouting
链中添加一条规则,其将端口22
上的传入流量重定向到端口2222
:nft add rule nat prerouting tcp dport 22 redirect to 2222
# nft add rule nat prerouting tcp dport 22 redirect to 2222
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.4. 编写和执行 nftables 脚本 复制链接链接已复制到粘贴板!
使用 nftables
框架的主要优点是脚本的执行是原子的。这意味着,系统会应用整个脚本,或者在出现错误时防止执行。这样可保证防火墙始终处于一致状态。
另外,使用 nftables
脚本环境时,您可以:
- 添加评论
- 定义变量
- 包括其他规则集文件
安装 nftables
软件包时,Red Hat Enterprise Linux 会在 /etc/nftables/
目录中自动创建 *.nft
脚本。这些脚本包含为不同目的创建表和空链的命令。
23.6.4.1. 支持的 nftables 脚本格式 复制链接链接已复制到粘贴板!
您可以使用以下格式在 nftables
脚本环境中编写脚本:
与
nft list ruleset
命令相同的格式显示规则集:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 与
nft
命令的语法相同:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.4.2. 运行 nftables 脚本 复制链接链接已复制到粘贴板!
您可以通过将脚本传递给 nft
实用程序或直接执行脚本来运行 nftables
脚本。
流程
要通过将其传给
nft
工具来运行nftables
脚本,请输入:nft -f /etc/nftables/<example_firewall_script>.nft
# nft -f /etc/nftables/<example_firewall_script>.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 要直接运行
nftables
脚本:在进行这个时间时:
确保脚本以以下 shebang 序列开头:
#!/usr/sbin/nft -f
#!/usr/sbin/nft -f
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要如果省略
-f
参数,nft
实用程序不会读取脚本并显示:Error: syntax error, unexpected newline, expecting string
。可选:将脚本的所有者设置为
root
:chown root /etc/nftables/<example_firewall_script>.nft
# chown root /etc/nftables/<example_firewall_script>.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使脚本可以被其所有者执行:
chmod u+x /etc/nftables/<example_firewall_script>.nft
# chmod u+x /etc/nftables/<example_firewall_script>.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
运行脚本:
/etc/nftables/<example_firewall_script>.nft
# /etc/nftables/<example_firewall_script>.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果没有输出结果,系统将成功执行该脚本。
即使 nft
成功地执行了脚本,在脚本中错误放置的规则、缺失的参数或其他问题都可能会导致防火墙的行为不符合预期。
23.6.4.3. 使用 nftables 脚本中的注释 复制链接链接已复制到粘贴板!
nftables
脚本环境将 #
字符右侧的所有内容解释为行尾。
注释可在行首或命令旁边开始:
23.6.4.4. 使用 nftables 脚本中的变量 复制链接链接已复制到粘贴板!
要在 nftables
脚本中定义一个变量,请使用 define
关键字。您可以在变量中存储单个值和匿名集合。对于更复杂的场景,请使用 set 或 verdict 映射。
- 只有一个值的变量
以下示例定义了一个名为
INET_DEV
的变量,其值为enp1s0
:define INET_DEV = enp1s0
define INET_DEV = enp1s0
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 您可以通过输入
$
符号后再输入变量名称来使用脚本中的变量:... add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept ...
... add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 包含匿名集合的变量
以下示例定义了一个包含匿名集合的变量:
define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }
define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 您可以通过在
$
符号后跟变量名称来在脚本中使用变量:add rule inet example_table example_chain ip daddr $DNS_SERVERS accept
add rule inet example_table example_chain ip daddr $DNS_SERVERS accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注意当您在规则中使用大括号时具有特殊的语义,因为它们表示变量代表一个集合。
23.6.4.5. 在 nftables 脚本中包含文件 复制链接链接已复制到粘贴板!
在 nftables
脚本环境中,您可以使用 include
语句包含其他脚本。
如果您只指定了文件名,而没有绝对路径或相对路径,那么 nftables
将包含默认搜索路径中的文件,在 Red Hat Enterprise Linux 上,该路径设为 /etc
。
例 23.1. 包含默认搜索目录中的文件
从默认搜索目录中包含一个文件:
include "example.nft"
include "example.nft"
例 23.2. 包含目录中的所有 *.nft 文件
要包括所有存储在 /etc/nftables/rulesets/
目录中、以 *.nft
结尾的文件:
include "/etc/nftables/rulesets/*.nft"
include "/etc/nftables/rulesets/*.nft"
请注意,include
语句不匹配以点开头的文件。
23.6.4.6. 系统引导时自动载入 nftables 规则 复制链接链接已复制到粘贴板!
nftables
systemd 服务加载包含在 /etc/sysconfig/nftables.conf
文件中的防火墙脚本。
先决条件
-
nftables
脚本存储在/etc/nftables/
目录中。
流程
编辑
/etc/sysconfig/nftables.conf
文件。-
如果您使用
nftables
软件包的安装修改了在/etc/nftables/
中创建的*.nft
脚本,请取消对这些脚本的include
语句的注释。 如果您编写了新脚本,请添加
include
语句以包含这些脚本。例如,要在nftables
服务启动时加载/etc/nftables/example.nft
脚本,请添加:include "/etc/nftables/_example_.nft"
include "/etc/nftables/_example_.nft"
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
-
如果您使用
可选:启动
nftables
服务以在不重启系统的情况下加载防火墙规则:systemctl start nftables
# systemctl start nftables
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 启用
nftables
服务。systemctl enable nftables
# systemctl enable nftables
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.5. 使用 nftables 命令中的设置 复制链接链接已复制到粘贴板!
nftables
框架原生支持集合。您可以使用一个集合,例如,规则匹配多个 IP 地址、端口号、接口或其他匹配标准。
23.6.5.1. 在 nftables 中使用匿名集合 复制链接链接已复制到粘贴板!
匿名集合包含用逗号分开的值,如 { 22、80、443 }
,它们直接在规则中使用。您还可以将匿名集合用于 IP 地址以及任何其他匹配标准。
匿名集合的缺陷是,如果要更改集合,则需要替换规则。对于动态解决方案,使用命名集合,如 在 nftables 中使用命名集合 中所述。
先决条件
-
inet
系列中的example_chain
链和example_table
表存在。
流程
例如,要向
example_table
中的example_chain
添加一条规则,其允许传入流量到端口22
、80
和443
:nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept
# nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 可选:在
example_table
中显示所有链及其规则:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.5.2. 在 nftables 中使用命名集 复制链接链接已复制到粘贴板!
nftables
框架支持可变命名集合。命名集是一个列表或一组元素,您可以在表中的多个规则中使用。匿名集合的另外一个好处在于,您可以更新命名的集合而不必替换使用集合的规则。
当您创建一个命名集时,必须指定集合包含的元素类型。您可以设置以下类型:
-
包含 IPv4 地址或范围的集合的
ipv4_addr
,如192.0.2.1
或192.0.2.0/24
。 -
包含 IPv6 地址或范围的集合的
ipv6_addr
,如2001:db8:1::1
或2001:db8:1::1/64
。 -
包含介质访问控制(MAC)地址列表的集合的
ether_addr
,如52:54:00:6b:66:42
。 -
包含互联网协议类型列表的集合的
inet_proto
,如tcp
。 -
包含互联网服务列表的集合的
inet_service
,如ssh
。 -
包含数据包标记列表的集合的
mark
。数据包标记可以是任意正 32 位整数值(0
到2147483647
)。
先决条件
-
example_chain
链和example_table
表存在。
流程
创建一个空集。以下示例为 IPv4 地址创建了一个集合:
要创建可存储多个独立 IPv4 地址的集合:
nft add set inet example_table example_set { type ipv4_addr \; }
# nft add set inet example_table example_set { type ipv4_addr \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 要创建可存储 IPv4 地址范围的集合:
nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
重要要防止 shell 将分号解释为命令结尾,您必须使用反斜杠转义分号。
可选:创建使用集合的规则。例如,以下命令向
example_table
中的example_chain
中添加一条规则,该规则将丢弃example_set
中来自 IPv4 地址的所有数据包。nft add rule inet example_table example_chain ip saddr @example_set drop
# nft add rule inet example_table example_chain ip saddr @example_set drop
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 由于
example_set
仍为空,所以该规则目前不起作用。向
example_set
中添加 IPv4 地址:如果您创建存储单个 IPv4 地址的集合,请输入:
nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
# nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果您创建存储 IPv4 范围的集合,请输入:
nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }
# nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 当您指定 IP 地址范围时,您可以使用无类别域间路由(CIDR)表示法,如上例中的
192.0.2.0/24
。
23.6.5.3. 使用动态集添加来自数据包路径的条目 复制链接链接已复制到粘贴板!
nftables
框架中的动态设置允许自动添加来自数据包数据的元素。例如,IP 地址、目标端口、MAC 地址等。通过此功能,您可以实时收集这些元素,并使用它们创建拒绝列表、禁止列表等,以便您能够立即响应安全威胁。
先决条件
-
inet
系列中的example_chain
链和example_table
表存在。
流程
创建一个空集。以下示例为 IPv4 地址创建了一个集合:
要创建可存储多个独立 IPv4 地址的集合:
nft add set inet example_table example_set { type ipv4_addr \; }
# nft add set inet example_table example_set { type ipv4_addr \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 要创建可存储 IPv4 地址范围的集合:
nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要要防止 shell 将分号解释为命令结尾,您必须使用反斜杠转义分号。
创建一条规则,将传入数据包的源 IPv4 地址添加到
example_set
组中:nft add rule inet example_table example_chain set add ip saddr @example_set
# nft add rule inet example_table example_chain set add ip saddr @example_set
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 命令在
example_chain
规则链中创建了一个新规则,并使用example_table
将数据包的源 IPv4 地址动态添加到example_set
中。
验证
确保添加了规则:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 命令显示
nftables
中当前载入的整个规则集。它显示 IP 正在主动触发规则,并且使用相关地址更新example_set
。
后续步骤
有动态 IP 集后,您可以将它用于各种安全性、过滤和流量控制目的。例如:
- 块、限制或记录网络流量
- 与允许列表结合使用,以避免禁止可信用户
- 使用自动超时来防止过度阻塞
23.6.6. 在 nftables 命令中使用 verdict 映射 复制链接链接已复制到粘贴板!
判决映射(也称为字典),使 nft
能够通过将匹配条件映射到某个操作来根据数据包信息执行操作。
23.6.6.1. 在 nftables 中使用匿名映射 复制链接链接已复制到粘贴板!
匿名映射是直接在规则中使用的 { match_criteria : action }
语句。这个语句可以包含多个用逗号分开的映射。
匿名映射的缺点是,如果要修改映射,则必须替换规则。对于动态解决方案,请使用命名映射,如 在 nftables 中使用命名映射 中所述。
例如,您可以使用匿名映射将 IPv4 和 IPv6 协议的 TCP 和 UDP 数据包路由到不同的链,以分别计算传入的 TCP 和 UDP 数据包。
流程
创建新表:
nft add table inet example_table
# nft add table inet example_table
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在
example_table
中创建tcp_packets
链:nft add chain inet example_table tcp_packets
# nft add chain inet example_table tcp_packets
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向统计此链中流量的
tcp_packets
中添加一条规则:nft add rule inet example_table tcp_packets counter
# nft add rule inet example_table tcp_packets counter
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在
example_table
中创建udp_packets
链nft add chain inet example_table udp_packets
# nft add chain inet example_table udp_packets
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向统计此链中流量的
udp_packets
中添加一条规则:nft add rule inet example_table udp_packets counter
# nft add rule inet example_table udp_packets counter
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 为传入的流量创建一个链。例如,要在过滤传入的流量的
example_table
中创建一个名为incoming_traffic
的链:nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
# nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 添加一条带有到
incoming_traffic
匿名映射的规则 :nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 匿名映射区分数据包,并根据它们的协议将它们发送到不同的计数链。
要列出流量计数器,请显示
example_table
:Copy to Clipboard Copied! Toggle word wrap Toggle overflow tcp_packets
和udp_packets
链中的计数器显示两者接收的数据包和字节数。
23.6.6.2. 在 nftables 中使用命名映射 复制链接链接已复制到粘贴板!
nftables
框架支持命名映射。您可以在表中的多个规则中使用这些映射。匿名映射的另一个好处在于,您可以更新命名映射而不比替换使用它的规则。
在创建命名映射时,您必须指定元素的类型:
-
匹配部分包含 IPv4 地址的映射的
ipv4_addr
,如192.0.2.1
。 -
匹配部分包含 IPv6 地址的映射的
ipv6_addr
,如2001:db8:1::1
。 -
匹配部分包含介质访问控制(MAC)地址的映射的
ether_addr
,如52:54:00:6b:66:42
。 -
匹配部分包含互联网协议类型的映射的
inet_proto
,如tcp
。 -
匹配部分包含互联网服务名称端口号的映射的
inet_service
,如ssh
或22
。 -
匹配部分包含数据包的映射的
mark
。数据包标记可以是任意正 32 位整数值(0
到2147483647
)。 -
匹配部分包含计数器值的映射的
counter
。计数器值可以是任意正 64 位整数值。 -
匹配部分包含配额值的映射的
quota
。配额值可以是任意正 64 位整数值。
例如,您可以根据其源 IP 地址允许或丢弃传入的数据包。使用命名映射时,您只需要一条规则来配置这种场景,而 IP 地址和操作被动态存储在映射中。
流程
创建表。例如,要创建一个处理 IPv4 数据包的、名为
example_table
的表:nft add table ip example_table
# nft add table ip example_table
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 创建链。例如,要在
example_table
中创建一个名为example_chain
的链:nft add chain ip example_table example_chain { type filter hook input priority 0 \; }
# nft add chain ip example_table example_chain { type filter hook input priority 0 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要要防止 shell 将分号解释为命令结尾,您必须使用反斜杠转义分号。
创建一个空的映射。例如,要为 IPv4 地址创建映射:
nft add map ip example_table example_map { type ipv4_addr : verdict \; }
# nft add map ip example_table example_map { type ipv4_addr : verdict \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 创建使用该映射的规则。例如,以下命令向
example_table
中的example_chain
添加了一条规则,该规则将操作应用到在example_map
中定义的 IPv4 地址:nft add rule example_table example_chain ip saddr vmap @example_map
# nft add rule example_table example_chain ip saddr vmap @example_map
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向
example_map
添加 IPv4 地址和相应的操作:nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }
# nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 这个示例定义了 IPv4 地址到操作的映射。与以上创建的规则相结合,防火墙接受来自
192.0.2.1
的数据包,丢弃来自192.0.2.2
的数据包。可选:通过添加另一个 IP 地址和 action 语句来增强映射:
nft add element ip example_table example_map { 192.0.2.3 : accept }
# nft add element ip example_table example_map { 192.0.2.3 : accept }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 可选:从映射中删除条目:
nft delete element ip example_table example_map { 192.0.2.1 }
# nft delete element ip example_table example_map { 192.0.2.1 }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 可选:显示规则集:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.7. 例如:使用 nftables 脚本保护 LAN 和 DMZ 复制链接链接已复制到粘贴板!
使用 RHEL 路由器上的 nftables
框架来编写和安装防火墙脚本,该脚本可保护内部 LAN 中的网络客户端,以及 DMZ 中的 Web 服务器,不受互联网和其他网络的未授权访问。
这个示例仅用于演示目的,并描述了具有特定要求的场景。
防火墙脚本高度依赖于网络基础架构和安全要求。当您为自己的环境编写脚本时,请使用此示例了解 nftables
防火墙的概念。
23.6.7.1. 网络状况 复制链接链接已复制到粘贴板!
本例中的网络具有以下条件:
路由器连接到以下网络:
-
互联网通过接口
enp1s0
-
内部 LAN 通过接口
enp7s0
-
DMZ through
enp8s0
-
互联网通过接口
-
路由器的互联网接口分配了静态 IPv4 地址(
203.0.113.1
)和 IPv6 地址(2001:db8:a::1
)。 -
内部 LAN 中的客户端仅使用范围
10.0.0.0/24
中的专用 IPv4 地址。因此,从 LAN 到互联网的流量需要源网络地址转换(SNAT)。 -
内部 LAN 中的管理员 PC 使用 IP 地址
10.0.0.100
和10.0.0.200
。 -
DMZ 使用范围
198.51.100.0/24
和2001:db8:b::/56
的公共 IP 地址。 -
DMZ 中的 Web 服务器使用 IP 地址
198.51.100.5
和2001:db8:b::5
。 - 路由器充当 LAN 和 DMZ 中的主机的缓存 DNS 服务器。
23.6.7.2. 防火墙脚本的安全要求 复制链接链接已复制到粘贴板!
以下是示例网络中 nftables
防火墙的要求:
路由器必须能够:
- 递归解析 DNS 查询。
- 在回环接口上执行所有连接。
内部 LAN 中的客户端必须能够:
- 查询运行在路由器上的缓存 DNS 服务器。
- 访问 DMZ 中的 HTTPS 服务器。
- 访问互联网上的任何 HTTPS 服务器。
- 管理员的 PC 必须能够使用 SSH 访问 DMZ 中的路由器以及每个服务器。
DMZ 中的 Web 服务器必须能够:
- 查询运行在路由器上的缓存 DNS 服务器。
- 访问互联网上的 HTTPS 服务器以下载更新。
互联网上的主机必须能够:
- 访问 DMZ 中的 HTTPS 服务器。
另外,存在以下安全要求:
- 应丢弃未明确允许的连接尝试。
- 应记录丢弃的数据包。
23.6.7.3. 配置将丢弃的数据包记录到文件 复制链接链接已复制到粘贴板!
默认情况下,systemd
会将内核消息如,丢弃的数据包,记录到日志中。另外,您可以配置 rsyslog
服务,来将此类条目记录到单独的文件中。为确保日志文件不会无限增长,请配置轮转策略。
先决条件
-
rsyslog
软件包已安装。 -
rsyslog
服务正在运行。
流程
使用以下内容创建
/etc/rsyslog.d/nftables.conf
文件::msg, startswith, "nft drop" -/var/log/nftables.log & stop
:msg, startswith, "nft drop" -/var/log/nftables.log & stop
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用这个配置,
rsyslog
服务会将丢弃的数据包记录到/var/log/nftables.log
文件,而不是/var/log/messages
。重启
rsyslog
服务:systemctl restart rsyslog
# systemctl restart rsyslog
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用以下内容创建
/etc/logrotate.d/nftables
文件,以便在大小超过 10 MB 时轮转/var/log/nftables.log
:Copy to Clipboard Copied! Toggle word wrap Toggle overflow maxage 30
设置定义了logrotate
在下一次轮转操作过程中删除超过 30 天的轮转日志。
23.6.7.4. 编写并激活 nftables 脚本 复制链接链接已复制到粘贴板!
本例是运行在 RHEL 路由器上的一个 nftables
防火墙脚本,其保护内部 LAN 中的客户端以及 DMZ 中的 Web 服务器。有关示例中使用的防火墙的网络和要求的详情,请参阅 网络条件 和 对防火墙脚本的安全要求 。
此 nftables
防火墙脚本仅用于演示目的。不要在未经调整为适合您环境和安全要求的情况下使用它。
前提条件
- 网络已配置,如 网络状况 中所述。
流程
使用以下内容创建
/etc/nftables/firewall.nft
脚本:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在
/etc/sysconfig/nftables.conf
文件中包括/etc/nftables/firewall.nft
脚本:include "/etc/nftables/firewall.nft"
include "/etc/nftables/firewall.nft"
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 启用 IPv4 转发:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 启用并启动
nftables
服务:systemctl enable --now nftables
# systemctl enable --now nftables
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
验证
可选:验证
nftables
规则集:nft list ruleset
# nft list ruleset ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 尝试执行防火墙阻止的访问。例如,尝试使用 SSH 从 DMZ 访问路由器:
ssh router.example.com
# ssh router.example.com ssh: connect to host router.example.com port 22: Network is unreachable
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 根据您的日志记录设置,搜索:
阻塞的数据包的
systemd
日志:journalctl -k -g "nft drop"
# journalctl -k -g "nft drop" Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 阻塞的数据包的
/var/log/nftables.log
文件:Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...
Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.8. 使用 nftables 限制连接的数量 复制链接链接已复制到粘贴板!
您可以使用 nftables
来限制连接数或限制到建立给定数量连接的块 IP 地址,以防止它们使用太多的系统资源。
23.6.8.1. 使用 nftables 限制连接的数量 复制链接链接已复制到粘贴板!
通过使用 nft
工具的 ct count
参数,您可以限制每个 IP 地址的同时连接的数量。例如,您可以使用此功能配置每个源 IP 地址只能建立两个到主机的并行 SSH 连接。
流程
创建带有
inet
地址系列的filter
表:nft add table inet filter
# nft add table inet filter
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 将
input
链添加到inet filter
表中:nft add chain inet filter input { type filter hook input priority 0 \; }
# nft add chain inet filter input { type filter hook input priority 0 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 为 IPv4 地址创建动态集合:
nft add set inet filter limit-ssh { type ipv4_addr\; flags dynamic \;}
# nft add set inet filter limit-ssh { type ipv4_addr\; flags dynamic \;}
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在
input
链中添加一条规则,该规则只允许从 IPv4 地址到 SSH 端口(22)的两个同时的传入连接,并拒绝来自同一 IP 的所有进一步的连接:nft add rule inet filter input tcp dport ssh ct state new add @limit-ssh { ip saddr ct count over 2 } counter reject
# nft add rule inet filter input tcp dport ssh ct state new add @limit-ssh { ip saddr ct count over 2 } counter reject
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
验证
- 建立从同一 IP 地址到主机的两个以上的同时的 SSH 连接。如果已经建立了两个连接,则 nftables 会拒绝到 SSH 端口的连接。
显示
limit-ssh
动态集:Copy to Clipboard Copied! Toggle word wrap Toggle overflow elements
条目显示当前与该规则匹配的地址。在本例中,elements
列出了与 SSH 端口有活动连接的 IP 地址。请注意,输出不会显示活跃连接的数量,或者连接是否被拒绝。
23.6.8.2. 在一分钟内尝试超过十个进入的 TCP 连接的 IP 地址 复制链接链接已复制到粘贴板!
您可以临时阻止在一分钟内建立十个 IPv4 TCP 连接的主机。
流程
创建具有
ip
地址系列的filter
表:nft add table ip filter
# nft add table ip filter
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 向
filter
表中添加input
链:nft add chain ip filter input { type filter hook input priority 0 \; }
# nft add chain ip filter input { type filter hook input priority 0 \; }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 添加一条规则,其丢弃来自源地址的所有数据包,并尝试在一分钟内建立十个 TCP 连接:
nft add rule ip filter input ip protocol tcp ct state new, untracked meter ratemeter { ip saddr timeout 5m limit rate over 10/minute } drop
# nft add rule ip filter input ip protocol tcp ct state new, untracked meter ratemeter { ip saddr timeout 5m limit rate over 10/minute } drop
Copy to Clipboard Copied! Toggle word wrap Toggle overflow timeout 5m
参数定义nftables
在五分钟后自动删除条目,以防止计量被过时的条目填满。
验证
要显示 meter 的内容,请输入:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.9. 调试 nftables 规则 复制链接链接已复制到粘贴板!
nftables
框架为管理员提供了不同的选项来调试规则,以及数据包是否匹配。
23.6.9.1. 创建带有计数器的规则 复制链接链接已复制到粘贴板!
在识别规则是否匹配时,可以使用计数器。
-
有关在现有规则中添加计数器的流程的更多信息,请参阅
配置和管理网络
中的 向现有规则中添加计数器
先决条件
- 您要添加该规则的链已存在。
流程
向链中添加一条带有
counter
参数的新规则。以下示例添加一个带有计数器的规则,它允许端口 22 上的 TCP 流量,并计算与这个规则匹配的数据包和网络数据的数量:nft add rule inet example_table example_chain tcp dport 22 counter accept
# nft add rule inet example_table example_chain tcp dport 22 counter accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示计数器值:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.9.2. 在现有规则中添加计数器 复制链接链接已复制到粘贴板!
在识别规则是否匹配时,可以使用计数器。
-
有关添加带有计数器的新规则的流程的更多信息,请参阅
配置和管理网络
中的 创建带有计数器的规则
先决条件
- 您要添加计数器的规则已存在。
流程
在链中显示规则及其句柄:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 通过使用
counter
参数替换规则来添加计数器。以下示例替换了上一步中显示的规则并添加计数器:nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept
# nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示计数器值:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.9.3. 监控与现有规则匹配的数据包 复制链接链接已复制到粘贴板!
nftables
中的追踪功能与 nft monitor
命令相结合,使管理员能够显示与某一规则匹配的数据包。您可以为规则启用追踪,用它来监控匹配此规则的数据包。
先决条件
- 您要添加计数器的规则已存在。
流程
在链中显示规则及其句柄:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 通过使用
meta nftrace set 1
参数替换规则来添加追踪功能。以下示例替换了上一步中显示的规则并启用追踪:nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept
# nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用
nft monitor
命令来显示追踪。以下示例过滤了命令的输出,来只显示包含inet example_table example_chain
的条目:nft monitor | grep "inet example_table example_chain"
# nft monitor | grep "inet example_table example_chain" trace id 3c5eb15e inet example_table example_chain packet: iif "enp1s0" ether saddr 52:54:00:17:ff:e4 ether daddr 52:54:00:72:2f:6e ip saddr 192.0.2.1 ip daddr 192.0.2.2 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 49710 ip protocol tcp ip length 60 tcp sport 56728 tcp dport ssh tcp flags == syn tcp window 64240 trace id 3c5eb15e inet example_table example_chain rule tcp dport ssh nftrace set 1 accept (verdict accept) ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 警告根据启用了追踪的规则数量以及匹配流量的数量,
nft monitor
命令可以显示很多输出。使用grep
或其他工具来过滤输出。
23.6.10. 备份和恢复 nftables 规则集 复制链接链接已复制到粘贴板!
您可以将 nftables
规则备份到文件,并稍后恢复它们。此外,管理员可以使用带有规则的文件,来将规则传给其他服务器。
23.6.10.1. 将 nftables 规则集备份到文件 复制链接链接已复制到粘贴板!
您可以使用 nft
工具将 nftables
规则集备份到文件。
流程
要备份
nftables
规则:以
nft list ruleset
格式生成的格式:nft list ruleset > file.nft
# nft list ruleset > file.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow JSON 格式:
nft -j list ruleset > file.json
# nft -j list ruleset > file.json
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
23.6.10.2. 从文件中恢复 nftables 规则集 复制链接链接已复制到粘贴板!
您可以从文件恢复 nftables
规则集。
流程
要恢复
nftables
规则:如果要恢复的文件是
nft list ruleset
生成的格式,或直接包含nft
命令:nft -f file.nft
# nft -f file.nft
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果要恢复的文件采用 JSON 格式:
nft -j -f file.json
# nft -j -f file.json
Copy to Clipboard Copied! Toggle word wrap Toggle overflow