nftables入门

nftables框架提供了数据包分类功能,它是iptables,ip6tables,arptables和ebtables的后继产品。与以前的数据包过滤工具相比,它在便利性,功能和性能方面提供了许多改进,最值得注意的是:

  • 查找表而不是线性处理

  • 适用于IPv4和IPv6协议的单一框架

  • 所有规则原子级应用,而不是获取,更新和存储完整的规则集

  • 支持在规则集中(nftrace)进行调试和跟踪,并监视跟踪事件(在nft工具中)

  • 更一致,更紧凑的语法,没有特定于协议的扩展

  • 用于第三方应用程序的Netlink API

与iptables相似,nftables使用tables来存储chains。这些chains包含执行操作的各个规则。 nft工具取代了以前的数据包过滤框架中的所有工具。 libnftnl库可用于通过libmnl库与nftables Netlink API进行低级交互。

要显示规则集更改的效果,请使用nft list ruleset命令。

由于这些工具将tables,chains,rules,sets和其他对象添加到nftables规则集中,因此请注意,nftables规则集操作(例如nft flush ruleset命令)可能会影响使用以前单独的旧版命令安装的规则集。

一、将iptables规则转换为nftables规则

redhat提供了iptables-translate和ip6tables-translate工具,可将现有iptables或ip6tables规则转换为适用于nftable的规则。

请注意,某些扩展名缺少翻译支持。如果存在这样的扩展名,则该工具会打印以#号为前缀的未翻译规则。 例如:

# iptables-translate -A INPUT -j CHECKSUM --checksum-fill
nft # -A INPUT -j CHECKSUM --checksum-fill

此外,用户可以使用iptables-restore-translate和ip6tables-restore-translate工具来转换规则转储。

请注意,在此之前,用户可以使用iptables-save或ip6tables-save命令来打印当前规则的转储。 例如:

# iptables-save >/tmp/iptables.dump
# iptables-restore-translate -f /tmp/iptables.dump

# Translated by iptables-restore-translate v1.8.0 on Wed Oct 17 17:00:13 2018
add table ip nat
...

二、编写和执行nftables脚本

nftables框架提供了本机脚本编制环境,与使用shell脚本维护防火墙规则相比,它带来了主要的好处:脚本的执行是原子级的。 这意味着系统将应用整个脚本,或者在发生错误时阻止执行。这样可以确保防火墙始终处于一致状态。

此外,nftables脚本环境使管理员能够:

  • 添加注释

  • 定义变量

  • 包括其他规则集文件

2.1 nftables脚本中所需的脚本

与其他脚本相似,nftables脚本在设置解释器指令的脚本第一行中需要一个shebang序列。

nftables脚本必须以下行开头:

#!/usr/sbin/nft -f 

支持的nftables脚本格式

2.2 nftables脚本环境支持以下格式的脚本

1) 使用与nft list ruleset命令显示规则集相同的格式编写脚本:

#!/usr/sbin/nft -f
# Flush the rule set

flush ruleset

table inet example_table {
  chain example_chain {
    # Chain for incoming packets that drops all packets that
    # are not explicitly allowed by any rule in this chain
    type filter hook input priority 0; policy drop;

    # Accept connections to port 22 (ssh)
    tcp dport ssh accept

  }
}

2) 使用与nft命令相同的语法:

#!/usr/sbin/nft -f

# Flush the rule set
flush ruleset

# Create a table
add table inet example_table

# Create a chain for incoming packets that drops all packets
# that are not explicitly allowed by any rule in this chain

add chain inet example_table example_chain { type filter hook input priority 0 ; policy drop ; }

# Add a rule that accepts connections to port 22 (ssh)
add rule inet example_table example_chain tcp dport ssh accept

2.3 运行nftables脚本

要运行nftables脚本,该脚本必须是可执行的。仅当该脚本包含在另一个脚本中时,它才不需要是可执行的。该过程描述了如何使脚本可执行并运行该脚本。

在/etc/nftables/example_firewall.nft文件中存储了一个nftables脚本。

1) 仅需一次的步骤:

  • 可选,将脚本的所有者设置为root:

chown root /etc/nftables/example_firewall.nft
  • 使脚本对于所有者可执行:

chmod u+x /etc/nftables/example_firewall.nft

2) 运行脚本

/etc/nftables/example_firewall.nft

如果未显示任何输出,则系统成功执行了脚本

2.4 在nftables脚本中使用注释

nftables脚本环境将#字符右侧的所有内容解释为注释。

示例 nftables脚本中的注释

注释可以从一行的开头开始,也可以在命令旁边开始:

...

# Flush the rule set

flush ruleset

add table inet example_table  # Create a table
...

2.5 在nftables脚本中使用变量

要在nftables脚本中定义变量,请使用define关键字。 可以将单个值和匿名集存储在变量中。对于更复杂的方案,请使用集合或判定图。

1.具有单个值的变量

下面的示例定义一个名为INET_DEV的变量,其值为enp1s0:

define INET_DEV = enp1s0

在脚本中使用变量,方法是编写$符号,后跟变量名称:

...
add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept
...

2.包含匿名集的变量

以下示例定义了一个包含匿名集的变量:

define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }

在脚本中使用变量,方法是编写$符号,后跟变量名称:

add rule inet example_table example_chain ip daddr $DNS_SERVERS accept

2.6 在nftables脚本中包含文件

使用nftables脚本环境,管理员可以使用include语句来包含其他脚本。

如果仅指定没有绝对或相对路径的文件名,则nftables会包含来自默认搜索路径的文件,该默认搜索路径在/etc。

示例1 包括来自默认搜索目录的文件

要包括来自默认搜索目录的文件:

include "example.nft"

示例2 包括目录中的所有*.nft文件

要包括所有以*.nft结尾的文件,这些文件存储在/etc/nftables/rulesets/目录中:

include "/etc/nftables/rulesets/*.nft"

请注意,include语句与以点开头的文件不匹配

2.7 系统启动时自动加载nftables规则

nftables systemd服务将加载/etc/sysconfig/nftables.conf文件中包含的防火墙脚本,nftables脚本存储在/etc/nftables/目录中。

1) 编辑/etc/sysconfig/nftables.conf文件

  • 如果在安装nftables软件包时增强了在/etc/nftables/中创建的*.nft脚本,请取消注释这些脚本的include语句。

  • 如果从头开始编写脚本,请添加include语句以包含这些脚本。 例如,要在nftables服务启动时加载/etc/nftables/example.nft脚本,请添加:

include "/etc/nftables/example.nft"

2) 启用nftables服务,并启动服务

# systemctl enable nftables
# systemctl start nftables

三、创建和管理tables,chains和rules

3.1 标准chain优先级值和文本名称

创建chain时,可以设置整数值或标准名称来指定优先级,该标准名称指定具有相同挂钩值的chain遍历顺序。

名称和值是根据xtables在注册其默认链时使用的优先级定义的。

示例1.使用文本值设置优先级

以下命令使用标准优先级值50在example_table中创建一个名为example_chain的链:

nft add chain inet example_table example_chain { type filter hook input priority 50 \; policy accept \; }

因为优先级是一个标准值,所以也可以使用文本值:

nft add chain inet example_table example_chain { type filter hook input priority security \; policy accept \; }
  1. 标准优先级名称,族和挂钩兼容性矩阵

Name Value Families Hooks
raw -300 ip, ip6, inet all
mangle -150 ip, ip6, inet all
dstnat -100 ip, ip6, inet prerouting
filter 0 ip, ip6, inet, arp, netdev all
security 50 ip, ip6, inet all
srcnat 100 ip, ip6, inet postrouting

所有系列都使用相同的值,但是网桥系列使用以下值:

  1. 标准优先级名称,以及网桥系列的挂钩兼容性

Name Value Hooks
dstnat -300 prerouting
filter -200 all
out 100 output
srcnat 300 postrouting

3.2 显示nftables规则集

nftable的规则集包含tables, chains 和 rules。

# nft list ruleset
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    tcp dport http accept
    tcp dport ssh accept
  }
}

3.3 创建一个nftables表

nftables中的表是一个名称空间,其中包含chains,rules,sets和其他对象的集合。 每个表都必须定义一个地址族。 表的地址族定义了表处理的地址类型。 创建表时,可以设置以下地址族之一:

  • ip:仅匹配IPv4数据包。 如果未指定地址族,则为默认设置。

  • ip6:仅匹配IPv6数据包。

  • inet:匹配IPv4和IPv6数据包。

  • arp:匹配IPv4地址解析协议(ARP)数据包。

  • bridge:匹配通过网桥设备的数据包。

  • netdev:匹配入口的数据包。

1) 使用nft add table命令创建一个新表。 例如,创建一个名为example_table的表来处理IPv4和IPv6数据包:

# nft add table inet example_table

2) 可选,列出规则集中的所有表:

# nft list tables
table inet example_table

额外资源

  • 有关地址族的更多详细信息,请参见nft(8)手册页中的“Address families”部分。

  • 有关可以在表上运行的其他操作的详细信息,请参见nft(8)手册页中的“Tables”部分。

3.4 创建一个nftables链

链是规则的容器,存在以下两种规则类型:

  • Base chain:将基链用作来自网络堆栈的数据包的入口点。

  • Regular chain:将常规链用作跳转目标并更好地组织规则。

该过程将基链添加到现有表,添加新链的表必须存在。

1) 使用nft add chain命令创建一个新chain。

例如,要在example_table中创建名为example_chain的链:

# nft add chain inet example_table example_chain { type filter hook input priority 0 \; policy accept \; }

该链过滤传入的数据包。 priority参数指定nftables处理具有相同钩子值的链的顺序。 较低的优先级值优先于较高的优先级值。 policy参数为该链中的规则设置默认操作。

请注意,如果是远程登录服务器,并且将默认策略设置为“丢弃”,则在没有其他规则允许远程访问的情况下,连接会立即断开。

2) 显示所有chains

# nft list chains
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
  }
}

3.5 将规则附加到nftables链的末尾

1) 要添加新规则,请使用nft add rule命令。

例如,要将规则添加到example_table中的example_chain中,该规则允许端口22上的TCP通信:

# nft add rule inet example_table example_chain tcp dport 22 accept

除了端口号,还可以指定服务的名称。 在该示例中,可以使用ssh代替端口号22。

请注意,服务名称根据/etc/services文件中的条目解析为端口号。

2) 在example_table中显示所有链及其规则:

# nft list table inet example_table
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    ...
    tcp dport ssh accept
  }
}

3.6 在nftables链的开头插入规则

1) 要插入新规则,请使用nft insert rule命令

例如,要将规则插入到example_table中的example_chain中,该规则允许端口22上的TCP通信:

# nft insert rule inet example_table example_chain tcp dport 22 accept

2) 在example_table中显示所有链及其规则

# nft list table inet example_table
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    tcp dport ssh accept
    ...
  }
}

3.7 在nftables链的特定位置插入规则

在nftables链中的现有规则之前和之后插入规则,这样将新规则放在正确的位置

1) 使用nft -a list ruleset命令可在example_table中显示所有链及其规则,包括其句柄:

# nft -a list table inet example_table
table inet example_table { # handle 1
  chain example_chain { # handle 1
    type filter hook input priority filter; policy accept;
    tcp dport 22 accept # handle 2
    tcp dport 443 accept # handle 3
    tcp dport 389 accept # handle 4
  }
}

使用-a将显示句柄,需要此信息才能在下一步中放置新规则。

2) 将新规则插入到example_table中的example_chain链中:

  • 要插入允许规则3之前的端口636上的TCP流量的规则,请输入:

# nft insert rule inet example_table example_chain position 3 tcp dport 636 accept
  • 要添加规则以允许句柄3之后在端口80上进行TCP通信,请输入:

# nft add rule inet example_table example_chain position 3 tcp dport 80 accept

3) 在example_table中显示所有链及其规则:

# nft -a list table inet example_table
table inet example_table { # handle 1
  chain example_chain { # 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
    tcp dport 389 accept # handle 4
  }
}

四、使用nftables配置NAT

使用nftables,可以配置以下网络地址转换(NAT)类型:

  • Masquerading

  • Source NAT(SNAT)

  • Destination NAT(DNAT)

4.1 不同的NAT类型:Masquerading,Source NAT和Destination NAT

Masquerading和Source NAT(SNAT)

使用这些NAT类型之一来更改数据包的源IP地址。例如,Internet提供商不会路由保留的IP范围,例如10.0.0.0/8。如果在网络中使用保留的IP范围,并且用户应该能够访问Internet上的服务器,则将数据包的源IP地址从这些范围映射到公共IP地址。

Masquerading和SNAT都非常相似,不同之处在于:

  • Masquerading会自动使用传出接口的IP地址。因此,如果传出接口使用动态IP地址,请使用Masquerading。

  • SNAT将数据包的源IP地址设置为指定的IP,并且不会动态查找传出接口的IP。因此,SNAT比伪装要快。如果传出接口使用固定IP地址,请使用SNAT。

Destination NAT(DNAT)

使用此NAT类型将传入流量路由到其他主机。例如,如果Web服务器使用保留IP范围内的IP地址,因此不能直接从Internet访问,则可以在路由器上设置DNAT规则以将传入流量重定向到该服务器。

4.2 配置Masquerading

Masquerading使路由器能够将通过接口发送的数据包的源IP动态更改为接口的IP地址。 这意味着,如果接口分配了新的IP,则nftables在替换源IP时会自动使用新的IP。

以下示例将通过ens3接口离开主机的数据包的源IP替换为ens3上设置的IP

1) 创建table

# nft add table nat

2) 将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命令,以避免shell将负优先级值解释为nft命令的选项。

3) 将规则添加到与ens3接口上的传出数据包匹配的postrouting链中:

# nft add rule nat postrouting oifname "ens3" masquerade

4.3 配置Source NAT

在路由器上,Source NAT(SNAT)可以将通过接口发送的数据包的IP更改为特定的IP地址。

以下示例将通过ens3接口离开路由器的数据包的源IP替换为192.0.2.1

1) 创建表

# nft add table nat

2) 将prerouting和postrouting链添加到表中

# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

3) 在postrouting链中添加一条规则,该规则将通过ens3的传出数据包的源IP替换为192.0.2.1:

# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1

4.4 配置Destination NAT

通过Destination NAT,可以将路由器上的流量重定向到无法从Internet直接访问的主机。

以下示例将发送到路由器端口80和443的传入流量重定向到IP地址为192.0.2.1的主机

1) 创建表

# nft add table nat

2) 将prerouting和postrouting链添加到表中

# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

3) 在prerouting链中添加一条规则,该规则将ens3接口上发送到端口80和443的传入流量重定向到使用192.0.2.1的主机:

# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1

4) 根据环境,添加SNAT或masquerading规则以更改源地址:

  • 如果ens3接口使用了动态IP地址,请添加masquerading规则:

# nft add rule nat postrouting oifname "ens3" masquerade
  • 如果ens3接口使用静态IP地址,请添加SNAT规则。 例如,如果ens3使用198.51.100.1地址:

# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1

五、在nftables命令中使用集

nftables框架本身支持集合。 例如,如果规则应匹配多个IP地址,端口号,网络接口或任何其他匹配条件,则可以使用集。

5.1 在Nftable中使用匿名集

匿名集包含用大括号括起来的逗号分隔值,例如{22、80、443},可以在规则中直接使用这些值。 还可以将匿名集也用于IP地址或任何其他匹配条件。

匿名集的缺点在于,如果要更改集,则必须替换规则。

inet 家族中必须存在example_chain链和example_table表

1) 要将规则添加到example_table中的example_chain中,以允许到端口22、80和443的传入流量:

# nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept

2) 在example_table中显示所有链及其规则:

# nft list table inet example_table
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    tcp dport { ssh, http, https } accept
  }
}

5.2 在nftable中使用命名集

nftables框架支持可变的命名集。命名集是可以在表中的多个规则中使用的元素的列表或范围。相对于匿名集的另一个好处是,可以更新命名集而无需替换使用该集的规则。

创建命名集时,必须指定该集合包含的元素类型,可以设置以下类型:

  • ipv4_addr 包含IPv4地址或范围的集合,例如192.0.2.1或192.0.2.0/24

  • ipv6_addr 包含IPv6地址或范围的集合,例如2001:db8:1::1或2001:db8:1::1/64

  • ether_addr 包含物理地址(MAC)列表的集合,例如52:54:00:6b:66:42

  • inet_proto 包含Internet协议类型列表的集合,例如tcp

  • inet_service 包含Internet服务列表的集合, 例如ssh

  • mark 包含数据包标记列表的集合,数据包标记可以是任何正32位整数值(0到2147483647)

1) 创建一个空集。 以下示例为IPv4地址创建了一个集合:

  • 要创建一个可以存储多个单独的IPv4地址的集合,请执行以下操作:

# nft add set inet example_table example_set { type ipv4_addr \; }
  • 要创建一个可以存储IPv4地址范围的集合,请执行以下操作:

# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }

2) 创建使用集合的规则

例如,以下命令将一条规则添加到example_table中的example_chain中,该规则将丢弃来自example_set中IPv4地址的所有数据包。

# nft add rule inet example_table example_chain ip saddr @example_set drop

由于example_set仍为空,因此该规则当前无效。

3) 将IPv4地址添加到example_set

  • 如果创建一个存储单个IPv4地址的集合,请输入:

# nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
  • 如果创建一个存储IPv4范围的集合,请输入:

# nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }

指定IP地址范围时,可以选择使用无类域间路由(CIDR)表示法,例如上例中的192.0.2.0/24。

六、在nftables命令中使用判定映射

判定映射(也称为字典)使nft通过将匹配标准映射到动作来基于数据包信息执行动作。

6.1 在Nftable中使用文字映射

文字映射是直接在规则中使用的{match_criteria:action}语句。 该语句可以包含多个逗号分隔的映射。

文字映射的缺点是,如果要更改映射,则必须替换规则。

该示例使用文字映射将IPv4和IPv6协议的TCP和UDP数据包都路由到不同的链,以分别计算传入的TCP和UDP数据包。

1) 创建example_table:

# nft add table inet example_table

2) 在example_table中创建tcp_packets链:

# nft add chain inet example_table tcp_packets

3) 将规则添加到tcp_packets中,以计算此链中的流量:

# nft add rule inet example_table tcp_packets counter

4) 在example_table中创建udp_packets链

# nft add chain inet example_table udp_packets

5) 将规则添加到udp_packets中,以计算此链中的流量:

# nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }

6) 创建传入流量的链。 例如,要在example_table中创建一个名为incoming_traffic的链以过滤传入流量:

# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }

7) 将带有文字映射的规则添加到incoming_traffic:

# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }

文字映射区分数据包,并根据其协议将其发送到不同的计数器链。

8) 列出流量计数器,显示example_table:

# nft list table inet example_table
table inet example_table {
  chain tcp_packets {
    counter packets 36379 bytes 2103816
  }

  chain udp_packets {
    counter packets 10 bytes 1559
  }

  chain incoming_traffic {
    type filter hook input priority filter; policy accept;
    ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
  }
}

tcp_packets和udp_packets链中的计数器同时显示已接收数据包的数量和字节。

6.2 在nftables中使用可变判定映射

nftables框架支持可变的判定映射,可以在一个表中的多个规则中使用这些映射。文字映射的另一个好处是,可以更新可变映射,而无需替换使用它的规则。

创建可变判定映射时,必须指定元素的类型:

  • ipv4_addr 匹配部分包含IPv4地址的映射,例如192.0.2.1

  • ipv6_addr 匹配项包含IPv6地址的映射,例如2001:db8:1 :: 1

  • ether_addr 匹配部分包含硬件网卡地址(MAC)的映射,例如52:54:00:6b:66:42。

  • inet_proto 匹配部分包含Internet协议类型的映射,例如tcp

  • inet_service 匹配部分包含Internet服务名称端口号的映射,例如ssh或22

  • mark 匹配部分包含数据包标记的映射。数据包标记可以是任何正的32位整数值(0到2147483647)。

  • counter 匹配部分包含计数器值的映射。计数器值可以是任何正的64位整数值。

  • quota 匹配部分包含配额值的地图的配额。配额值可以是任何正的64位整数值。

该示例会根据传入数据包的源IP地址来允许或丢弃传入数据包,使用可判定映射,只需一个规则即可配置此方案,而IP地址和操作将动态存储在该映射中,该示例

在映射中添加和删除条目。

1) 创建一个表。 例如,创建一个名为example_table的表来处理IPv4数据包:

# nft add table ip example_table

2) 创建一个链。 例如,要在example_table中创建名为example_chain的链:

# nft add chain ip example_table example_chain { type filter hook input priority 0 \; }

3) 创建一个空的映射。 例如,要创建IPv4地址的映射,请执行以下操作:

# nft add map ip example_table example_map { type ipv4_addr : verdict \; }

4) 创建使用映射的规则。 例如,以下命令将一条规则添加到example_table中的example_chain,该规则将操作应用于在example_map中定义的IPv4地址:

# nft add rule example_table example_chain ip saddr vmap @example_map

5) 将IPv4地址和相应的操作添加到example_map: 本示例定义了IPv4地址到操作的映射

# nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }

结合上面创建的规则,防火墙将接受来自192.0.2.1的数据包,并丢弃来自192.0.2.2的数据包。

6) 可选、通过添加另一个IP地址和操作语句来增强映射:

# nft add element ip example_table example_map { 192.0.2.3 : accept }

7) 可选、从映射上删除一个条目:

# nft delete element ip example_table example_map { 192.0.2.1 }

8) 显示规则集:

# nft list ruleset
table ip example_table {
  map example_map {
    type ipv4_addr : verdict
    elements = { 192.0.2.2 : drop, 192.0.2.3 : accept }
  }

  chain example_chain {
    type filter hook input priority filter; policy accept;
    ip saddr vmap @example_map
  }
}

七、使用nftables配置端口转发

通过端口转发,管理员可以将发送到特定目标端口的数据包转发到其他本地或远程端口。

例如,如果Web服务器没有公用IP地址,则可以在防火墙上设置端口转发规则,该规则将防火墙上端口80和443上的传入数据包转发到Web服务器。 使用此防火墙规则,Internet上的用户可以使用防火墙的IP或主机名访问Web服务器。

7.1 将传入的数据包转发到其他本地端口

下面示例将端口8022上的传入IPv4数据包转发到本地系统上的端口22。

1) 使用IP地址族创建一个名为nat的表:

# nft add table ip nat

2) 将路由前和路由后链添加到表中:

# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }

3) 在预路由链中添加一条规则,该规则会将端口8022上的传入数据包重定向到本地端口22:

# nft add rule ip nat prerouting tcp dport 8022 redirect to :22

7.2 将特定本地端口上的传入数据包转发到其他主机

使用目标网络地址转换(DNAT)规则将本地端口上的传入数据包转发到远程主机。 这使Internet上的用户可以访问在具有专用IP地址的主机上运行的服务。

下面示例将本地端口443上的传入IPv4数据包转发到IP地址为192.0.2.1的远程系统上的相同端口号。

1) 使用IP地址族创建一个名为nat的表:

# nft add table ip nat

2) 将路由前和路由后链添加到表中:

# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

3) 在预路由链中添加一条规则,该规则会将端口443上的传入数据包重定向到192.0.2.1上的同一端口:

# nft add rule ip nat prerouting tcp dport 443 dnat to 192.0.2.1

4) 在路由后链中添加一条规则,以伪装外向流量:

# nft add rule ip daddr 192.0.2.1 masquerade

5) 启用数据包转发:

# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

八、使用nftable限制连接数量

使用nftable来限制连接数或阻止试图建立给定数量的连接的IP地址,以防止它们使用过多的系统资源。

8.1 使用nftable限制连接数

使用nft实用程序的ct count参数,管理员可以限制连接数。

下面示例限制传入连接

1) 添加一个规则,该规则只允许从IPv4地址同时连接到SSH端口(22)的两个,并拒绝来自同一IP的所有其他连接:

# nft add rule ip example_table example_chain tcp dport ssh meter example_meter { ip saddr ct count over 2 } counter reject

2) 可选、显示在上一步中创建的仪表:

# nft list meter ip example_table example_meter
table ip example_table {
  meter example_meter {
    type ipv4_addr
    size 65535
    elements = { 192.0.2.1 : ct count over 2 , 192.0.2.2 : ct count over 2  }
  }
}

元素条目显示当前与规则匹配的地址。 在此示例中,元素列出了与SSH端口具有活动连接的IP地址。 请注意,输出不显示活动连接数或连接被拒绝。

8.2 阻止在一分钟内尝试十个以上新的传入TCP连接的IP地址

nftables框架使管理员可以动态更新集,本节说明如何使用此功能临时阻止在一分钟内建立十个以上IPv4 TCP连接的主机。 五分钟后,nftables会自动从拒绝列表中删除IP地址。

1) 使用ip地址系列创建过滤器表:

# nft add table ip filter

2) 将输入链添加到过滤器表中:

# nft add chain ip filter input { type filter hook input priority 0 \; }

3) 将一个名为denylist的集合添加到过滤器表中:

# nft add set ip filter denylist { type ipv4_addr \; flags dynamic, timeout \; timeout 5m \; }

此命令为IPv4地址创建一个动态集。 5m超时参数定义了nftables在5分钟后会自动从集合中删除条目。

4) 添加一条规则,该规则会自动将尝试在一分钟内建立十个以上新TCP连接的主机的源IP地址添加到拒绝列表集中:

# nft add rule ip filter input ip protocol tcp ct state new, untracked limit rate over 10/minute add @denylist { ip saddr }

5) 添加一个规则,以删除来自拒绝列表集中IP地址的所有连接:

# nft add rule ip filter input ip saddr @denylist drop

九、调试nftables规则

nftables框架为管理员调试规则以及数据包是否匹配规则提供了不同的选项。

9.1 用计数器创建规则

要确定规则是否匹配,可以使用计数器。 本节介绍如何使用计数器创建新规则。

1) 将带有counter参数的新规则添加到链中。 以下示例添加了一个带有计数器的规则,该计数器允许端口22上的TCP通信并计算与该规则匹配的数据包和通信:

# nft add rule inet example_table example_chain tcp dport 22 counter accept

2) 要显示计数器值:

# nft list ruleset
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    tcp dport ssh counter packets 6872 bytes 105448565 accept
  }
}

9.2 向现有规则添加计数器

要确定规则是否匹配,可以使用计数器。 本节介绍如何向现有规则添加计数器。

1) 显示链中的规则及其句柄:

# nft --handle list chain inet example_table example_chain
table inet example_table {
  chain example_chain { # handle 1
    type filter hook input priority filter; policy accept;
    tcp dport ssh accept # handle 4
  }
}

2) 通过替换规则但使用counter参数来添加计数器。 以下示例替换了上一步中显示的规则,并添加了一个计数器:

# nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept

3) 要显示计数器值:

# nft list ruleset
table inet example_table {
  chain example_chain {
    type filter hook input priority filter; policy accept;
    tcp dport ssh counter packets 6872 bytes 105448565 accept
  }
}

9.3 监视与现有规则匹配的数据包

通过将nftables中的跟踪功能与nft monitor命令结合使用,管理员可以显示与规则匹配的数据包。 该过程描述了如何启用对规则的跟踪以及如何监视与该规则匹配的数据包。

1) 显示链中的规则及其句柄:

# nft --handle list chain inet example_table example_chain
table inet example_table {
  chain example_chain { # handle 1
    type filter hook input priority filter; policy accept;
    tcp dport ssh accept # handle 4
  }
}

2) 通过替换规则但使用meta nftrace set 1参数来添加跟踪功能。 以下示例替换了上一步中显示的规则,并启用了跟踪:

# nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept

3) 使用nft monitor命令显示跟踪。 以下示例过滤命令的输出,以仅显示包含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)
...

十、备份和还原nftables规则集

10.1 将nftables规则集备份到文件

备份nftables规则:

  • 采用nft列表规则集格式:

# nft list ruleset > file.nft
  • JSON格式:

# nft -j list ruleset > file.json

10.2 从文件还原nftables规则集

还原nftables规则:

  • 如果要还原的文件为nft列表规则集格式或包含nft命令:

# nft -f file.nft
  • 如果要还原的文件为JSON格式:

# nft -j -f file.json
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章