nftables是继承于iptables的新一代防火墙,比iptables速度更快,拥有统一的语法格式。
1. 内核配置
要想使用nftables,必须使能iptables,以及相关nf配置,以下配置项需要开启:
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_NUMGEN=y
CONFIG_NFT_COUNTER=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MANGLE=y
这些会启用驱动文件iptables.c(位于kernel/net/ipv4/netfilter/)和ip6_tables.c(位于kernel/net/ipv6/netfilter/,且使能了inet或者ipv6)以及相关依赖文件。
2. apt安装nftables
上面配置编译后,会在/usr/sbin/中生成iptables,同时可以使用iptables相关命令,但是,nftables相关命令nft仍然不能使用,它需要手动安装:
bash
sudo apt-get install nftables
nftables依赖iptables,如果iptables无法使用,那么nftables也无法使用
3. 修改配置
nftables安装好后,就可以使用nft命令了,它可以开机就运行,需要使能开机启动nftables服务:
bash
sudo systemctl enable nftables
nftables服务会读取/etc/nftables.conf文件,执行它里面的规则。nft指令只是临时的影响nftables形为,重启后,将失去作用,要使命令结果得以重启后仍然使用,需要将命令结果保存进nftables.conf:
bash
sudo nft list ruleset > /etc/nftables.conf
要立即使用配置生效,执行命令:
bash
sudo nft -f /etc/nftables.conf
4. nftables操作
nftables.conf文件基于表->链->规则,一个表里面包含有若干个链,每个链又包含若干规则,命令nft其实也是基于这个规则使用的,nft命令格式:
nft [add|delete|list] [table family] [object] [options]
注意,该命令需要root权限,所以,执行时通常需要前加sudo
4.1添加表
下面命令创建一个名为ysz_table的表
bash
sudo nft add table inet ysz_table
注意inet位置,它表示针对的网络协议,可以是下面其中一个:
- inet:包含ipv4和ipv6
- ip:仅ipv4
- ip6:仅ipv6
- arp:针对arp数据包
- bridge:针对以太网帧
4.2 添加链
下面命令创建一个命为in_chain的链,它被放在ysz_table表中:
bash
sudo nft add chain inet ysz_table in_chain '{ type filter hook input priority 0 ; }'
- 类型type:可以是filter/nat/mangle等其中一个
- 勾子hook:勾住的数据流有input(输入)/output(输出)/postrouting(路由)等
- 优先级priority:一个勾子上有多个链时起作用,整数,可以为负,值越小,处理的优先级越高。
特别注意,由于shell会解拆断解析花括号,因此需要''号将花括号围起来。
4.3 添加规则
下面命令设定规则:禁止192.168.2.5访问
bash
sudo nft add rule inet ysz_table in_chain ip saddr 192.168.2.5 drop
匹配规则:
- ip saddr 192.168.2.5 匹配IP源地址(saddr: source addr)
- ip daddr 192.168.2.5 匹配IP目标地址(daddr: destination addr),通常设定为勾子output的链中
- tcp dport ssh 匹配目标端口ssh的tcp端口发出数据,通常ssh默认端口是22,因此默认情况下它等价于tcp dport 22,类似的有tcp dport http,tcp dport nfs等
- tcp sport ssh 匹配源端口ssh的tcp端口传入数据
- udp sport 1234 匹配源端口1234的udp传入数据,类似的有udp dport 1234
执行操作:
- accept:接收数据
- drop:丢弃数据
- reject:拒绝数据,并返回错误
- log:记录数据包到系统日志/var/log/message
- limit:限流处理,防止DDOS攻击,nft add rule inet ysz_table in_chain ip saddr 192.168.2.5 limit rate 100/second accept,限制192.168.2.5每秒钟100数据包以下
insert插入规则:
通常需要获已有规则的句柄,再指定插入的位置,而且是在指定规则句柄前一个位置插入,add如果指定了句柄,也是在指定句柄后一个位置添加。
- 查看句柄:nft -a list ruleset 或者 nft --handle list ruleset

- 插入规则:nft insert rule inet ysz_table in_chain handle 4 udp sport 256 accept 这里在句柄为4的规则前一个位置插入新的规则
- 加入规则:nft add rule inet ysz_table in_chain handle 4 udp sport 1223 accept 这里在句柄为4的规则后一个位置加入新的规则
4.4 删除
- 删除规则:nft delete rule inet ysz_table in_chain handle 5
- 删除链:nft delete chain inet ysz_table in_chain
- 删除表:nft delete table inet ysz_table
5.集合
5.1 直接引用集合
将集合元素放进花括号直接引用
bash
sudo nft add rule inet ysz_table out_chain ip daddr { 192.168.2.85,192.168.2.40 } accept
5.2 使用集合变量
创建一个名为myipset的集合变量
注意:
- 类型花括号必须用 ' ' 围起来,有以下类型
- ipv4_addr ipv4类型地址
- ipv6_addr ipv6类型地址
- ether_addr 以态网地址
- inet_proto 网络协议
- mark 标记类型
bash
sudo nft add set inet ysz_table myipset '{ type ipv4_addr ; }'
将IP放进myipset变量
bash
sudo nft add element inet ysz_table myipset { 192.168.2.33,192.168.2.35 }
引用myipset变量
bash
sudo nft add rule inet ysz_table out_chain ip daddr @myipset accept
5.3 区间
创建一个名为myrange的区间变量,类型和5.2说的一样的
bash
sudo nft add set inet ysz_table myrange '{ type ipv4_addr ; flags interval ; }'
将区间IP放进myrange,注意,IP后面的/24是子网掩码,相当于255.255.255.0,这里相当于IP区间:192.168.3.0~192.168.3.255
bash
sudo nft add element inet ysz_table myrange { 192.168.3.0/24 }
引用myrange
bash
sudo nft add rule ip saddr @myrange accept
6.只允许指定IP访问
有两种方式,一种是在链中增加规则drop,同时增加指定IP accept:
bash
sudo nft add rule inet ysz_table in_chain ip saddr 192.168.2.15 accept
sudo nft add rule inet ysz_table in_chain drop
另一种是创建链时,设置链的策略为drop,同时增加指定IP accept:
bash
sudo nft add chain inet ysz_table my_drop_chain '{ type filter hook input priority 0; policy drop; }'
sudo nft add rule inet ysz_table my_drop_chain ip saddr 192.168.2.15 accept