云计算AlmaLinux

20230101-nftables入门及使用

2022-12-31  本文已影响0人  負笈在线

Linux firewalld简介

Linux内核提供iptables、ip6tables、ebtables和nftables几种防火墙,它们其实并不具备防火墙功能,它们的作用都是在用户空间中管理和维护规则,不过它们的规则结构和使用方法不一样,真正利用规则进行数据包过滤是由内核中的netfilter子系统负责。


Linux firewalld整体架构.png

从Linux Kernel 3.13开始防火墙子系统 / 包过滤引擎 Nftables将取代 iptables

Linux Kernel 3.13推出Nftables的第一个正式版本,Nftables目标在取代包括iptables,ip6tables,arptables,ebtables的iptables项目,3.13版本中Nftables并不完整,还有重要的功能缺失,在3.15中应该可以提供完整的支持。
Nftables附带一个名为nft的命令行工具。

kernel 3.10的内核为iptables
# uname -a
Linux chefserver 3.10.0-693.11.6.el7.x86_64 #1 SMP Thu Jan 4 01:06:37 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
# lsmod |grep tables
ebtables               35009  1 ebtable_filter
ip6_tables             26901  1 ip6table_filter
ip_tables              27115  3 iptable_filter,iptable_mangle,iptable_nat

kerner 4.18的内核为nftables
# uname -a
Linux pxe 4.18.0-372.9.1.el8.x86_64 #1 SMP Tue May 10 08:57:35 EDT 2022 x86_64 x86_64 x86_64 GNU/Linux
# c
nf_tables_set          49152  0
nf_tables             180224  14 nft_ct,nft_reject_inet,nft_chain_nat,nf_tables_set,nft_reject
nfnetlink              16384  2 nf_tables,ip_set
libcrc32c              16384  4 nf_conntrack,nf_nat,nf_tables,xfs

firewalld、nftables、iptables如何选?

要防止不同的防火墙服务相互影响,在 RHEL 主机中只有一个服务,并禁用其他服务。

# dnf install -y nftables
# systemctl start nftables.service 
# systemctl enable nftables.service

确认并关闭firewalld和iptables服务

# systemctl status firewalld.service
# systemctl stop firewalld.service
# systemctl disable firewalld.service

# systemctl status iptables.service
# systemctl stop iptables.service
# systemctl disable iptables.service

当前firewall服务主要还是firewalld,主流的Linux 7和8默认服务都是firewalld。

nftables的使用

使用 nftables 设置表、链、规则

nftables由表,链,规则组成,其中规则又由match,target组成。如下面的结构所示:

Table{
Chain[
Rule
(match,match,match,...)
->target,
Rule
(match,match,match,...)
->target,
...
],
Chain[
...
],
...
}

nftables 中的表是一个包含链、规则、集合和其他对象集合的名字空间。
每个表都必须分配一个地址系列。地址系列定义了此表进程的数据包类型。在创建表时,您可以设置以下地址系列之一:
ip :仅匹配 IPv4 数据包。如果没有指定地址系列,这是默认设置。
ip6 :仅匹配 IPv6 数据包。
inet :匹配 IPv4 和 IPv6 数据包。
ARP : 匹配 IPv4 地址解析协议(ARP)数据包。
网桥 :匹配通过网桥设备的数据包。
netdev :匹配来自入口的数据包。

如果要添加表,要使用的格式取决于您的防火墙脚本:
在原生语法的脚本中,使用:
table <table_address_family> <table_name> {
}
在 shell 脚本中,使用:
nft add table <table_address_family> <table_name>

使用 inet 地址系列创建一个名为 nftables_svc 的表,以便表可以处理 IPv4 和 IPv6 数据包:
# nft add table inet nftables_svc

表由链组成,后者是规则的容器。存在以下两种规则类型:
基本链 :您可以使用基本链作为来自网络堆栈的数据包的入口点。
常规链 :您可以使用常规链作为 跳板 目标来更好地组织规则。
如果要在表中添加基本链,要使用的格式取决于您的防火墙脚本:

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

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 将分号解释为命令的结尾,请在分号的前面放置 \ 转义字符。 
将名为 INPUT 的基本链(用于处理传入的网络流量)添加到 inet nftables_svc 表中:
# nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy accept \; }

为了避免 shell 将分号解释为命令的结尾,请使用 \ 字符转义分号。
规则定义要在传递包含此规则的链的数据包上执行操作。如果规则还包含匹配的表达式,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。 
向 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 命令,而不是手动删除独立命令中的所有规则、链和表
使用 nftables 配置NAT

伪装和源 NAT(SNAT)
使用以上 NAT 类型之一更改数据包的源 IP 地址。例如,互联网服务提供商不路由私有 IP 范围,如 10.0.0.0/8。如果您在网络中使用私有 IP 范围,并且用户应该能够访问 Internet 上的服务器,请将这些范围内的数据包的源 IP 地址映射到公共 IP 地址。

伪装和 SNAT 相互类似。不同之处是:
伪装自动使用传出接口的 IP 地址。因此,如果传出接口使用了动态 IP 地址,则使用伪装。
SNAT 将数据包的源 IP 地址设置为指定的 IP 地址,且不会动态查找传出接口的 IP 地址。因此,SNAT 要比伪装更快。如果传出接口使用了固定 IP 地址,则使用 SNAT。

目标 NAT(DNAT)
使用此 NAT 类型重写传入数据包的目标地址和端口。例如,如果您的 Web 服务器使用私有 IP 范围内的 IP 地址,那么无法直接从互联网访问它,您可以在路由器上设置 DNAT 规则,以便将传入的流量重定向到此服务器。

重定向
这个类型是 IDT 的特殊示例,它根据链 hook 将数据包重定向到本地机器。例如,如果服务运行在与其标准端口不同的端口上,您可以将传入的流量从标准端口重定向到此特定端口。

使用 nftables 配置伪装
伪装使路由器动态地更改通过接口到接口 IP 地址发送的数据包的源 IP。这意味着,如果接口被分配了一个新 IP,nftables 会在替换源 IP 时自动使用新的 IP。
将通过 ens3 接口离开主机的数据包源 IP 替换为 ens3 上设置的 IP。

创建一个表:
# nft add table nat
向表中添加 prerouting 和 postrouting 链:
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要:即使您没有向 prerouting 链中添加规则,nftables 框架也会要求此链与传入的数据包回复匹配。
请注意,您必须将 -- 选项传递给 nft 命令,以防止 shell 将负优先级值解释为 nft 命令的选项。
向 postrouting 链中添加一条规则,来匹配 ens3 接口上传出的数据包:
# nft add rule nat postrouting oifname "ens3" masquerade

使用 nftables 配置源 NAT

在路由器中,源 NAT(SNAT)可让您将通过接口发送的数据包 IP 改为专门的 IP 地址。

以下流程描述了如何替换数据包的源 IP ,使其通过 ens3 接口离开路由器到达192.0.2.1。

创建一个表:
# nft add table nat
向表中添加 prerouting 和 postrouting 链:
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要:即使您没有向 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

使用 nftables 配置目标 NAT

目标 NAT 可让您将路由器中的流量重新指向无法直接从互联网访问的主机。

以下流程描述了如何将发送到路由器上端口 80 和 443 的流量重定向到 IP 地址为 192.0.2.1 的 web 服务器。

创建一个表:
# nft add table nat
向表中添加 prerouting 和 postrouting 链:
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要:即使您没有向 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
根据您的环境,添加 SNAT 或伪装规则,将从 Web 服务器返回的数据包的源地址改为发送者:
如果 ens3 接口使用动态 IP 地址,请添加一条伪装规则:
# nft add rule nat postrouting oifname "ens3" masquerade
如果 ens3 接口使用静态 IP 地址,请添加一条 SNAT 规则。例如,如果 ens3 使用 198.51.100.1 IP 地址:
# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
启用数据包转发:
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

使用 nftables 配置重定向

重定向 功能是目标网络地址转换(DNAT)的一种特殊情况,它根据链 hook 将数据包重定向到本地计算机。

以下流程描述了如何将发送到本地主机端口 22 的流量重定向到端口 2222。

创建一个表:
# nft add table nat
向表中添加 prerouting 链:
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
请注意,您必须将 -- 选项传递给 nft 命令,以防止 shell 将负优先级值解释为 nft 命令的选项。
向 prerouting 链中添加一条规则,其将端口 22 上的传入流量重定向到端口 2222 :
# nft add rule nat prerouting tcp dport 22 redirect to 2222

参考URL:

https://www.netfilter.org/
https://www.linux.com/news/linux-kernel-313-why-you-will-love-nftables/
https://blog.51cto.com/u_847102/5169457
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/8/html/securing_networks/index
https://www.jianshu.com/p/eec25be9c5be

上一篇下一篇

猜你喜欢

热点阅读