nftables是一个集成的过滤工具,集成了iptables、ip6tables、arptables和ebtables。

从Red Hat Enterprise Linux8,nftables取代了iptables。相应地CentOS8及RockyLinux8也采用了nftables。

nftables启动和停止

nftables已服务(service)的形式被安装到系统上,因此可使用systemctl命令进行操作。

nftables设定文件

nftables 服务启动时,会读取 /etc/sysconfig/nftables.conf 设定文件。而实际的Ruleset的设定文件,一般保存在 /etc/nfttables/ 目录下,文件名需要在 /etc/sysconfig/nftables.conf 文件里进行 include。

nftables的3个因素

设定nftables之前首先需要理解Family,Type,Hook3个因素。



■Family表

Family 概要
ip 表示IPv4,相当于iptables。
ip6 表示IPv6,相当于ip6tables。
inet 表示IPv4及IPv6。
arp 表示ARP,可操作IPv4的ARP
bridge 表示Bridge,可操作通过Bridge设备的数据包。
netdev 可分类NIC驱动程序传递到网络堆栈后的所有流量,例如可进行DDoS对策。

■Type表

Type 概要
filter 可用于所有的 family和hook
route 可用于routing。可用于Family:ip,ip6,inet及Hook:output
nat 用于NAT。可用于Family:ip,ip6,inet及Hook:input,output,prerouting,postrouting

■Hook表

Hook 概要
input 可用于Family:ip,ip6,inet,arp,bridge及Type:filter,nat
output 可用于Family:ip,ip6,inet,arp,bridge及Type:filter,route,nat
forward 可用于Family:ip,ip6,inet,bridge及Type:filter
prerouting 可用于Family:ip,ip6,inet,bridge及Type:filter,nat
postrouting 可用于Family:ip,ip6,inet,bridge及Type:filter,nat
ingress 可用于Family:netdev及Type:filter

创建table

nftables的默认设定没有table,因此需要从创建table开始。创建table的命令格式如下。

nft add table [family] [tableName]

确认当前的Ruleset。

[root@sys-blog ~]# nft list ruleset

Family inet上添加firewall001 table。

[root@sys-blog ~]# nft add table inet firewall001
[root@sys-blog ~]# nft list tables inet
table inet firewall001

确认添加table之后的Ruleset。

[root@sys-blog ~]# nft list ruleset
table inet firewall001 {
}

删除table使用下面的命令。

[root@sys-blog ~]# nft delete table inet firewall001

创建chain

创建table后,接下来创建chain。创建chain的命令格式如下。

nft add chain [family] [table name] [chain name] { type [type] hook [hook} priority [priority] \; }

priority是整数,数值越小优先度越高。

创建如下的Chain。

  • Type:filter
  • Hook:input
  • Family:inet
  • Table:firewall001
  • Chain:fiter_INPUT
[root@sys-blog ~]# nft add chain inet firewall001 filter_INPUT { type filter hook input priority 0 \;}
[root@sys-blog ~]# nft list ruleset
table inet firewall001 {
    chain filter_INPUT {
        type filter hook input priority filter; policy accept;
    }
}

删除Chain使用如下命令。

[root@sys-blog ~]# nft delete chain inet firewall00 filter_INPUT

设定Rule

创建Table及Chain后,开始设定Rule。

开始追加Rule之前,先确认当前的Rule。

[root@sys-blog ~]# nft list ruleset
table inet firewall001 {
        chain filter_INPUT {
                type filter hook input priority filter; policy accept;
        }
}

追加允许connection状态为 related, established 数据包的Rule。在这里ct为Conntrack或者Connection Tracking。

[root@sys-blog ~]# nft add rule inet firewall001 filter_INPUT ct state related,established accept
[root@sys-blog ~]# nft list table inet firewall001
table inet firewall001 {
        chain filter_INPUT {
                type filter hook input priority filter; policy accept;
                ct state established,related accept
        }
}

追加允许从loopback接口的连接。

[root@sys-blog ~]# nft add rule inet firewall001 filter_INPUT iif lo accept
[root@sys-blog ~]# nft list table inet firewall001
table inet firewall001 {
        chain filter_INPUT {
                type filter hook input priority filter; policy accept;
                ct state established,related accept
                iif "lo" accept
        }
}

追加丢弃所有数据包的Rule。nft命令 -a 选项,会显示handle号。

[root@sys-blog ~]# nft add rule inet firewall001 filter_INPUT drop
[root@sys-blog ~]# nft -a list table inet firewall001
table inet firewall001 { # handle 17
    chain filter_INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        ct state established,related accept # handle 4
        iif "lo" accept # handle 6
        drop # handle 7
    }
}

在handle6的后面,追加允许目标端口为22,connection状态为 new, untracked 数据包的Rule。

[root@sys-blog ~]# nft add rule inet firewall001 filter_INPUT handle 6 tcp dport 22 ct state { new,untracked } accept
[root@sys-blog ~]#nft -a list table inet firewall001
table inet firewall001 { # handle 17
    chain filter_INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        ct state established,related accept # handle 4
        iif "lo" accept # handle 6
        tcp dport 22 ct state { new, untracked } accept # handle 9
        drop # handle 7
    }
}

在handle9后面,追加允许数据包metadata为 icmp,ipv6-icmp 数据包的Rule。

[root@sys-blog ~]# nft add rule inet firewall001 filter_INPUT handle 9 meta l4proto { icmp,ipv6-icmp } accept
[root@sys-blog ~]# nft -a list table inet firewall001
table inet firewall001 { # handle 17
    chain filter_INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        ct state established,related accept # handle 4
        iif "lo" accept # handle 6
        tcp dport 22 ct state { new, untracked } accept # handle 9
        meta l4proto { icmp, ipv6-icmp } accept # handle 11
        drop # handle 7
    }
}

删除Rule时指定handle号,在这里删除handle号为11的Rule。

[root@sys-blog ~]# nft delete rule inet firewall001 filter_INPUT handle 11
[root@sys-blog ~]# nft -a list table inet firewall001
table inet firewall001 { # handle 17
    chain filter_INPUT { # handle 1
        type filter hook input priority filter; policy accept;
        ct state established,related accept # handle 4
        iif "lo" accept # handle 6
        tcp dport 22 ct state { new, untracked } accept # handle 9
        drop # handle 7
    }
}


修改nftables的方法

  1. 将nftables的结果保存到指定的文件
  2. 修改文件
  3. 反应到nftables

把当前配置的nftables设置写入到文件中(/tmp/nftables.nft)。

[root@sys-blog ~]# nft list ruleset > /tmp/nftables.nft

“nft list ruleset” 命令显示nftables当前规则集的命令,可以用来检查规则集。

修改/tmp/nftables.nft文件后,使用 “nft -f <文件名>” 修改后的规则集反映到系统。

[root@sys-blog ~]# nft -f /tmp/nftables.nft

一般Ruleset内容会保存 /etc/nfttables/ruleset.nft 文件。

小结

修改nftables需谨慎,万一修改时犯错,可能再也无法从外部连接该服务器。