Nftables是个嘛
简单来说,他是一个数据包分类框架,nftables的推出,直接能够取代 {ip,ip6,arp,eb}_tables四种框架,也就是nftables直接实现了四合一的功能
当然,他也对上述四个框架做了一定程度上的兼容,能让你在nftables内核上运行iptables(也就是nft 可以利用内核提供的表达式去模拟旧的 iptables 命令)
nftables的特点
与iptables之间的差异:
- iptables规则的布局是基于连续的大块内存的,即数组式布局;而- nftables的规则采用链式布局。其实就是数组和链表的区别
- iptables大部分工作在内核态完成,如果要添加新功能,只能重新编译内核;而- nftables的大部分工作是在用户态完成的,添加新功能很 easy,不需要改内核。
- iptables有内置的链,即使你只需要一条链,其他的链也会跟着注册;而- nftables不存在内置的链,你可以按需注册。由于- iptables内置了一个数据包计数器,所以即使这些内置的链是空的,也会带来性能损耗。
- 简化了 IPv4/IPv6双栈管理
- 原生支持集合、字典和映射
优势功能:
- 改进性能 
- 支持查询表 - nftables拥有一些高级的类似编程语言的能力,例如:定义变量和包含外部文件,即拥有使用额外脚本的能力。- nftables也可以用于多种地址簇的过滤和处理
- 不同于 iptables,nftables并不包含任何的内置表,需要哪些表并在这些表中添加什么处理规则一切由管理员决定
- 表包含规则链,规则链包含规则
 
- 事务型规则更新 
- 所有规则自动应用 
组件组成:
- 内核的实现 提供了 netlink 接口并 运行时规则集评估 
- libnl netlink通信 与内核通信的基本函数 
- nftables 用户空间 新引入的命令行工具 - nft和用户进行交互
优点:
- 更新速度快: - nftables使用原子的快速操作来更新规则集合
- 内核更新少: - 使用 - iptables时,每一个匹配或投递都需要内核模块的支持。因此,如果你忘记一些东西或者要添加新的功能时都需要重新编译内核。而在- nftables中就不存在这种情况了, 因为在- nftables中,大部分工作是在用户态完成的,内核只知道一些基本指令(过滤是用伪状态机实现的)。例如,- icmpv6支持是通过- nft工具的一个简单的补丁实现的,而在- iptables中这种类型的更改需要内核和- iptables都升级才可以。
nftables 使用
基础操作
首先,我们需要明确一点:nftables实际上也是由tables,chain和rule组成,tables包含chain,chain包含rule,其中rule是真正的动作。
因此,开始使用时我们未尝不可先从添加一个表开始:
表:
介绍
- 首先,nftables并没有内置表,因此我们可以自由决定表的数量和名称 
- 其次,我们可以自由决定表的地址簇,当然,每个表只有一个地址簇,其中ip(也就是ipv4)是默认簇  - 其中我们知道 - inet不能用于- nat类型,只能用于- filter的链
	Nftables 表 是 Nftables 的一种容器,存放 chain 链
	Nftables 表 无法修改名称,仅存在 flag 可能会有更新。
	Nftables 表 需要定义 数据包 的 family 地址簇 类型,用以限定引用范围
	Nftables 表 对 规则顺序 没有影响,仅限定了 规则 的使用区域与地址簇类别
	Nftables 表 可以使用 标志位 flag 暂时禁用所有规则,且仅有 dormant 唯一标志 	{flags dormant;}
	Nftables 表 所使用的 地址簇****family 一共有六大类
	主四类为 ip / ip6 / bridge / arp,分别对应 IPV4 / IPV6 / L2 / ARP 专项
	第五类为 ip&ip6 双栈使用的 inet , 不能搭配 nat 类型链,只能搭配 filter 类型链,且网络层流量会自动匹配对应协议栈规则
	第六类为 netdev ,优先级顺序最高,通常用于代码开发和排障测试使用。
	Nftables 表的配置需要参考如下
	可选项 [
	可选项 [
具体操作:
- 创建表 - 1 - nft add|create table [<family>] <name> [{ flags flags ; }] 
- 列出表: - 1 
 2
 3
 4
 5
 6
 7
 8- 列出所有表 
 nft list tables [<family>]
 列出指定族的所有表
 nft list tables [<family>] <name> [-n] [-a]
 列出表中的所有规则:
 nft list table [<family>] <name>- 如:列出 inet 簇中 mytable 表中的所有规则 
 nft list table inet mytable
- 删除一个表: - 1 - nft delete table [<family>] <name> - 只能删除不包含链的表 
- 清空表中的链与规则: - 1 - nft flush table [<family>] <name> 
链
介绍:
链是用来保存规则的,由于nftables不配置内置链,因此我们需要显式创建链
链内部规则按顺序从上到下执行
- 链分为两种类型: - 常规链:主要用来做跳转, 不需要指定钩子的类型和优先级,支持所有簇,主要以调度其他链和跳转为主
- 基本链:来自网络栈数据包的入口点,需要指定钩子类型和优先级,支持 ip和ip6簇,管理流经网络协议栈(TCP/IP)的数据包
 
- 基本链的类型: - filter:过滤数据包- route:对数据包进行重路由- nat:对 数据流 进行 网络地址转换(数据流仅第一个包会因为钩子进入本链,之后即使有钩子也会绕过)
- 配置特点: - Nftables 链 需要指定 类型 type 配置 流量应当以何种方式被控制(基础链强制) 
 Nftables 链 需要调用 钩子 hook 抓取网络数据包 才会对数据进行处理(基础链强制)
 Nftables 链 需要调用 优先级 priority 管理链的优先级顺序(基础链强制)
- nftables依然使用 - netfiler的五个钩子 -  然而nftables在钩子上相较于iptables 的不同在于 他新增了 - ingress钩子 
- 各个钩子的作用: - prerouting:刚到达并未被- nftables的其他部分所路由或处理的数据包(在这条钩子捕获 刚刚进入内核网络接口的数据包。)。
- input:已经被接收并且已经经过- prerouting钩子的传入数据包(捕获 打算进入本机的本地进程之前的数据包)。
- forward:如果数据报将被发送到另一个设备,它将会通过- forward钩子(捕获 那些通过并不进入主机的所有数据包)。
- output:从本地传出的数据包(捕获 打算离开本机的本地进程产出的数据包)。
- postrouting:仅仅在离开系统之前,可以对数据包进行进一步处理(捕获 刚刚进入内核网络接口的数据包)
- ingress:在prerouting之前处理(捕获 网卡驱动 向 内核网络接口 传递的数据包。)
 
- 不同簇之间对于钩子的适用范围不同 - ip、- ip6和- inet簇支持的钩子有:- prerouting、- input、- forward、- output、- postrouting。
- arp簇支持的钩子有:- input、- output
- netdev地址簇表 可以使用 INGRESS 钩子类型
 
- nftables链的优先级: - Nftables 基础链 优先级 priority 通过 顺序排列 进而 按顺序执行不同 钩子 hook,优先级小数值优先 - 优先级采用整数值表现,数字越小处理优先级越高: - 见:  - NF_IP_PRI_CONNTRACK_DEFRAG (-400)
- NF_IP_PRI_RAW (-300)
- NF_IP_PRI_SELINUX_FIRST (-225)
- NF_IP_PRI_CONNTRACK (-200)
- NF_IP_PRI_MANGLE (-150)
- NF_IP_PRI_NAT_DST (-100)
- NF_IP_PRI_FILTER (0)
- NF_IP_PRI_SECURITY (50)
- NF_IP_PRI_NAT_SRC (100)
- NF_IP_PRI_SELINUX_LAST (225)
- NF_IP_PRI_CONNTRACK_HELPER (300)
 - 特殊 1:当存在两个拥有 相同钩子 但 钩子优先级不同 的 A/B 基础链 (A<B),会先执行 A 链 然后 执行 B 链 
 特殊 2:但当上方情况为 A 链 执行 Drop 时,此时数据包 Drop 行为会立即生效,并终止继续执行
- 链有几个常见策略: - accept(常用)
- drop (常用)
- queue
- continue
- return
 
基本语法
- 创建常规链: - 1 
 2
 3
 4- nft create chain [<family>] <table> <name> 
 如:
 nft add chain inet mytable tcpchain
- 创建一个基本链,必须指定钩子和优先级,基本链的类型可以是 - filter,- route或者- nat。- 1 
 2
 3
 4
 5- nft (add | create) chain [<family>] <table> <name> [ { type <type> hook <hook> [device <device>] priority <priority> \; [policy <policy> \;] } ] 
 例:添加一个筛选输入数据包的基本链
 nft add chain inet mytable input { type filter hook input priority 0\; }- 命令中的反斜线 - (\)用来转义,这样- Shell就不会将分号解释为命令的结尾。
- 列出链的所有规则: - 1 - nft list chain [<family>] <table> <name> 
- 编辑链 
要编辑一个链,只需按名称调用并重新定义要更改的规则即可。
| 1 | 将input链的策略更改成drop | 
- 清空/删除链: - 1 - nft (delete | flush) chain [<family>] <table> <name> - 要删除的链中不能包含任何规则或者跳转目标。 
规则
基本操作
 nftables 的规则包含在链中,创建nftables规则的基本语法有:
- 将规则添加到链尾: - 1 - nft add rule [<family>] <table> <chain> <matches> <statements> 
- 将规则添加到链头: - 1 - nft insert rule [<family>] <table> <chain> [position <position>] <matches> <statements> 
- 指定位置增加规则 - 1 
 2
 3
 4
 5
 6- 可以通过index/handle来指定增加规则的位置 
 例子:
 在 input 链中已有规则中的第二条规则前插入一条新的规则
 nft insert rule inet mytable input index 1 tcp dport nfs accept
 在 input 链中已有规则中的第一条规则后插入一条新的规则
 nft add rule inet mytable input index 0 tcp dport 1234 accept- 注意: - index的值是从- 0开始的,- index*必须指向一个已存在的规则的索引。
 也可以使用handle来指定规则的句柄
- 通过handle来指定规则添加的位置 - 通过 - handle的值来指定规则添加的位置,必须先知道现有规则的句柄位置。你可以通过参数- --handle来获取当前规则的句柄位置。- 1 
 2- nft --handle list ruleset 
 获取到当前规则的句柄位置后,我们就可以在指定句柄位置添加规则
		在 nftables 中,句柄值是固定不变的,除非规则被删除。而 index 的值是可变的,只要有新规则插入,就		有可能发生变化。一般建议使用 handle 来插入新规则.
		你也可以在创建规则时就获取到规则的句柄值,只需要在创建规则时同时加上参数 --echo 和 --handle
- 更改规则; - 1 - nft replace rule [<family>] <table> <chain> [handle <handle>] <matches> <statements> 
- 删除规则: - 1 - nft delete rule [<family>] <table> <chain> [handle <handle>] - 单个规则只能通过句柄值进行删除 
matches 匹配
 其中,matches为报文需要满足的条件:
- 目前有以下几种报文可以被识别: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- ip : ipv4 协议字段 
 ip6 : ipv6 协议字段
 tcp : tcp 协议字段
 udp : udp 协议字段
 udplite : udp-lite 协议
 sctp : sctp 协议
 dccp
 ah
 esp
 comp
 icmp
 icmpv6
 ether : 以太头
 dst
 frag :
 hbh
 mh
 rt
 vlan : vlan
 arp : arp协议
 ct : 连接状态
 meta : 报文的基本信息
- 每种类型的报文可以检查多个字段,比如: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- ip dscp cs1 
 ip dscp != cs1
 ip dscp 0x38
 ip dscp != 0x20
 ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21,
 af22, af23, af31, af32, af33, af41, af42, af43, ef}
 ip length 232
 ip length != 233
 ip length 333-435
 ip length != 333-453
 ip length { 333, 553, 673, 838}
 ip6 flowlabel 22
 ip6 flowlabel != 233
 ip6 flowlabel { 33, 55, 67, 88 }
 ip6 flowlabel { 33-55 }
具体有哪些match可以见:
https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Rules
https://www.mankier.com/8/nft#Expressions到https://www.mankier.com/8/nft#Payload_Expressions
statments 触发
statments作为保温匹配规则时触发的操作,有以下几种:
| 1 | Verdict statements : 动作 | 
而Verdict Statements 是一系列报文匹配match时触发的操作:
- accept:接受数据包并停止剩余规则评估。 
- drop:丢弃数据包并停止剩余规则评估。 
- queue:将数据包排队到用户空间并停止剩余规则评估。 
- continue:使用下一条规则继续进行规则评估。 
- return:从当前链返回并继续执行最后一条链的下一条规则。 
- jump < chain > :跳转到指定的规则链,当执行完成或者返回时,返回到调用的规则链。 
- goto < chain >:类似于跳转,发送到指定规则链但不返回。 
rule中具体规则详见:https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Rules
statment详解见:https://www.mankier.com/8/nft#Statements
进阶
集合
	nftables 的语法原生支持集合,可以用来匹配多个 IP 地址、端口号、网卡或其他任何条件。
- 匿名集合: - 匿名集合适用于将来不需要更改的规则,但如果要修改集合规则,就得将原规则进行替换: - 如: - 1 
 2
 3
 4
 5- 允许来自源 IP 处于 10.10.10.123 ~ 10.10.10.231 这个区间内的主机的流量。 
 nft add rule inet mytable input ip saddr { 10.10.10.123, 10.10.10.231 } accept
 允许指定协义的流量通过
 nft add rule inet mytable input tcp dport { http, nfs, ssh } accept
- 命名集合: - nftables的命名集合是可以修改的。创建命名集合时需要指定其元素的类型,当前支持的数据类型有: - ipv4_addr:- IPv4地址
- ipv6_addr:- IPv6地址
- ether_addr: 以太网(Ethernet)地址
- inet_proto: 网络协议
- inet_service: 网络服务
- mark: 标记类型
 - 例: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- 创建一个空的命名集合 
 nft add set inet mytable myset { type ipv4_addr \; }
 nft list sets
 table inet mytable {
 set myset {
 type ipv4_addr
 }
 }
 之后向集合中添加一些元素
 nft add element inet mytable myset { 10.10.10.22, 10.10.10.33 }
 nft list set inet mytable myset
 table inet mytable {
 set myset {
 type ipv4_addr
 elements = { 10.10.10.22, 10.10.10.33 }
 }
 }
 在添加规则时引用集合,你可以使用 @ 符号跟上集合的名字来引用命名集合
 将来源为集合 myset 中的 IP 地址的请求阻止掉
 nft insert rule inet mytable input ip saddr @myset drop
 nft list chain inet mytable input
 table inet mytable {
 chain input {
 type filter hook input priority 0; policy accept;
 ip saddr @my_set drop
 tcp dport http accept
 tcp dport nfs accept
 tcp dport ssh accept
 ip saddr { 10.10.10.123, 10.10.10.231 } accept
 }
 }
- 支持区间 - 如果想要在上述的集合钟使用区间,可以加一个 - flag interval- 例子: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- 创建一个支持区间的命名集合 
 nft add set inet mytable my_rangeset { type ipv4_addr \; flags interval
 nft add element inet mytable my_rangeset { 10.10.10.0/24 }# 使用了子网掩码来表示 IP 地址段,它会被隐式转换为 IP 地址的区间
 nft list set inet mytable my_rangeset
 table inet mytable {
 set my_rangeset {
 type ipv4_addr
 flags interval
 elements = { 10.10.10.0/24 }
 }
 }
- 级联不同类型 - 集合支持不同类型的元素进行级联 - 例子: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- nft add set inet mytable my_concatset { type ipv4_addr . inet_proto . inet_service \; } 
 不同类型的元素可以通过级联操作符 . 来分隔。
 nft list set inet mytable my_concatset
 table inet mytable {
 set my_concatset {
 type ipv4_addr . inet_proto . inet_service
 }
 }
 向集合中添加元素
 nft add element inet mytable my_concatset { 10.30.30.30 . tcp . telnet }
 然后我们可以在级联类型中对集合进行引用
 如果数据包的源 IP、协议类型、目标端口匹配 10.30.30.30、tcp、telnet 时,就会允许该数据包通过
 nft add rule inet mytable input ip saddr . meta l4proto . tcp dport @my_concatset accept
 当然,匿名集合也可以使用级联
 nft add rule inet mytable input ip saddr . meta l4proto . udp dport { 10.30.30.30 . udp . bootps } accept
字典
字典支持在一条规则上面使用不同类型的数据
当然字典同集合一样,也分为命名字典和匿名字典
例:
| 1 | 创建命名字典 | 
表和命名空间
在 nftables 中,每个表都是一个独立的命名空间,这就意味着不同的表中的链、集合、字典等名字可以相同。
如:
| 1 | nft add table inet table_one | 
当然由于 nftables 将每个表都被视为独立的防火墙,一个数据包必须被所有表中的规则放行才能真正通过。如果,出现两条链的优先级相同,就会进入竞争状态。但我们可以通过nftables的优先级特性来讲这个问题解决
备份
通过 nftables 用户态工具 nft 直接在终端中加入的规则都是临时的。如果要想永久生效,我们可以将规则备份后并在开机自动加载时进行恢复。
- 备份规则: - $ nft list ruleset > /root/nftables.conf
- 恢复规则: - $ nft -f /root/nftables.conf
后记
大概的介绍了一下nftables的作用,感觉没啥要补充的了,接下来就要到实战了😋
后续:懒得整了,实战连接:
https://icloudnative.io/posts/use-nftables-as-firewall/
然后这byd写了我小一周,主要全在了解网络协议去了。唉,网络