nftables基础与实践
翻译nftables的文档man nft - mankier.com ,加上实际的操作实践,满足基本的需求。
最后更新时间:2021/7/13
1. 简介
nft是一个命令行工具,用于在Linux内核的nftables框架中设置、维护和检查包过滤和分类规则。Linux 内核子系统称为 nf_tables,"nf"代表 Netfilter。
2. 地址簇
ip | IPv4 地址簇 |
---|---|
ip6 | IPv6 地址簇 |
inet | Internet (IPv4/IPv6) 地址簇 |
arp | ARP 地址簇,处理 IPv4 ARP 数据包 |
bridge | 网桥地址簇,处理通过网桥设备的数据包 |
netdev | Netdev 地址簇,处理来自入口的数据包 |
如果指定的标识符没有地址族,则默认使用ip簇;
IPv4/IPv6/Inet 地址簇的hooks
Hook | 描述 |
---|---|
prerouting | 所有进入系统的数据包都由prerouting钩子处理。它在路由过程之前调用,用于早期过滤或更改影响路由的数据包属性。 |
input | 传送到本地系统的数据包由input钩子处理。 |
forward | 转发到不同主机的数据包由forward钩子处理。 |
output | 本地进程发送的数据包由output钩子处理。 |
postrouting | 所有离开系统的数据包都由 postrouting 钩子处理。 |
ingress | 所有进入系统的数据包都由这个钩子处理。它在第 3 层协议处理程序之前调用,因此在prerouting钩子之前调用,并且可用于过滤和监管。Ingress 仅适用于 Inet 系列(自 Linux 内核 5.10 起)。 |
其他地址簇不记录了。
3. 规则集ruleset
ruleset关键词被用来标识被放置在内核中的整套表、链、规则的集合。操作命令有list和flush,具体如下:
# 查询所有规则
nft list ruleset -a
# 按照地址簇查询——只查询inet地址簇的规则集
nft list ruleset inet -a
# 清空规则集【危险操作】
【nft flush ruleset】
# 按地址簇清空规则
【nft flush ruleset arp】
【nft flush ruleset ip】
【nft flush ruleset ip6】
【nft flush ruleset bridge】
【nft flush ruleset inet】
【nft flush ruleset netdev】
4. 表table
- table是链、集合和有状态对象的容器。
通过地址簇与命名区分。地址簇是ip ip6 inet arp bridge netdev六个其中之一,若未指定,默认为ip地址簇。inet是dummy虚拟的簇,代表IPv4/IPv6的混合hybrid。 - 元表达式nfproto关键字可用来测试 正在处理的包属于哪个地址簇上下文(ipv4 或 ipv6)
- add和create的唯一的区别是若表已经存在,前者不会报错,后者会报错
Error: Could not process rule: File exists
;因为add命令可以修改表的状态。
具体操作如下:
# 以交互模式启动nft 后面就不用一直输入nft命令,当远程服务器有堡垒机的root用户限制时候,可以更为方便的使用
nft --interactive
nft --i
# 创建表 不指定协议簇 默认ip协议
nft add|create table [地址簇] [表名]
nft create table nat
nft add table nat
# 查看运行结果 nft list ruleset
table ip 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 \; }
## 即使您没有向prerouting链添加规则,nftables框架也要求此链与传入的数据包回复匹配。
## 请注意,您必须将--选项传递给nft命令,以避免shell将负优先级值解析为nft命令的选项
# 查看运行结果 nft list ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
}
}
# 增加规则
# 源IP是10.11.0.0/16的伪装成wg0网卡的流量
nft add rule nat postrouting ip saddr 10.121.0.0/16 oifname wg0 counter masquerade
# 从tun0网卡进来的流量伪装成wg0网卡的流量
nft add rule nat postrouting iifname tun0 oifname wg0 counter masquerade
# 查看运行结果 nft list ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade
}
}
nft add rule filter input tcp dport 22 accept
# 向链中增加一个计数器
nft add rule nat postrouting counter
# 查看运行结果 nft list ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade
counter packets 0 bytes 0
}
}
# 暂时禁用表,规则会失效
nft add table nat { flags dormant\; }
# 查看运行结果 nft list ruleset
table ip nat {
flags dormant
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade
counter packets 0 bytes 0
}
}
# 激活表
nft add table nat
# 查看运行结果 nft list ruleset
# 发现flags dormant消失了
# 为了测试表的删除需要新建表test
nft add table inet mytable
# 此时再用nft list ruleset查看就太多了
# 查询所有表
nft list tables
# 结果是两行table ip nat和table inet test
# 查询指定指定表 地址簇为inet表名为test
nft list table inet mytable
# 命令后加-a用于显示句柄handles 后面加-nn用于不解析ip地址和端口
# 为了测试清空 需要给表test增加链和规则
nft add chain inet mytable mychain { type filter hook input priority 100\; } # 添加新的基础链:获取输入数据包
nft add rule inet mytable mychain counter # 给链增加计数器
# 查询结果 nft list table inet mytable
table inet mytable {
chain mychain {
type filter hook input priority 100; policy accept;
counter packets 60 bytes 13792
}
}
# 查询结果 nft list table inet mytable -a 可以查询规则的句柄
table inet mytable {
chain mychain {
type filter hook input priority 100; policy accept;
counter packets 201 bytes 25718 # handle 2
}
}
# 清空表test 不会删除基础链
nft flush table inet mytable
# 删除表
nft delete table inet mytable
5. 链chain
链是规则的容器。
- 有两种形式——基础链和常规链。基础链是来自网络堆栈的数据包的入口点,常规链可用作跳转目标并用于更好的组织规则。
- 指定钩子和优先级值后,该链将被创建为基础链并链接到到网络堆栈。
- 若基础链的类型填写了不匹配的钩子,会报错
Error: Could not process rule: Operation not supported
# 新增
nft add chain [地址簇] [表名] [链名] { type [类型] hook [钩子] priority [优先级值]\; }
nft add chain inet mytable mychain { type filter hook input priority 100\; } # 添加新的基础链:获取输入
nft add chain inet mytable forward { type nat hook postrouting priority 150\; } # 添加新的基础链:转发给其他主机
# 查询结果 nft list table inet mytable -a
table inet mytable {
chain mychain {
type filter hook input priority 100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 150; policy accept;
}
}
# 修改链 rename
nft rename chain [表地址簇] [表名] [旧链名] [新链名]
nft rename chain inet mytable mychain mychain1
# 新增规则
nft add rule mytable postrouting iifname tun0 oifname wg0 counter masquerade
会报错Error: NAT is only supported for IPv4/IPv6
nft add rule nat postrouting iifname tun0 oifname wg0 counter masquerade
nat表是ip地址簇的,就可以增加这个规则
# 新增常规链
nft add rule nat postrouting iifname tun0 oifname wg0 counter masquerade
支持的链类型
类型 | 协议簇 | 钩子 | 描述 |
---|---|---|---|
filter | all | all | 使用的标准链类型 |
nat | ip, ip6, inet | prerouting, input, output, postrouting | 这种类型的链根据 conntrack 条目执行本地地址转换。 只有连接的第一个数据包实际遍历此链 - 它的规则通常定义创建的 conntrack 条目的详细信息(例如 NAT 语句)。 |
route | ip, ip6 | output | 如果数据包已经穿过这种类型的链并即将被接受,并且 IP 标头的相关部分已更改,则会执行新的路由查找。 这允许例如 在 nftables 中实现策略路由选择器。 |
除了上面说明的特殊情况,还有三个值得注意的怪癖:
- netdev簇仅支持一种组合:即filter类型和ingress钩子。基本链还需要存在设备参数,因为他们仅存在于每个传入接口。
- arp簇仅支持filter类型链的input和output钩子。
- inet簇还支持ingress钩子,在与netdev链input钩子相同的位置过滤 IPv4 和 IPv6 数据包。这个inet hook允许你在prerouting、input、forward、output、postrouting和这个ingress hook之间共享集合和映射。
priority参数接收有符号整数值或标准优先级名称,指定有相同钩子值得链的遍历顺序。该顺序是升序的,低值比高值对应的链优先级更高。
标准优先级值可以替换为易于记忆的名称。 并非所有名称在每个钩子的每个系列中都有意义(请参阅下面的兼容性矩阵),但它们的数值仍可用于确定链的优先级。
这些名称和值是根据 xtables 在注册其默认链时使用的优先级来定义和提供的。
大多数地址簇使用相同的值,但bridge使用与其他地址簇不同的值。 请参阅以下描述值和兼容性的表格。
- 标准优先级名称、地址簇和钩子兼容性矩阵:
名称 | 值 | 地址簇 | 钩子 |
---|---|---|---|
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 |
- bridge地址簇系列的标准优先级名称和钩子兼容性
名称 | 值 | 钩子 |
---|---|---|
dstnat | -300 | prerouting |
filter | -200 | all |
out | 100 | output |
srcnat | 300 | postrouting |
使用这些标准名称也可以实现基本算术表达式(加法和减法)以简化相对优先级,例如 mangle - 5 代表 -155。 值也将像这样打印,直到值与标准值相差不超过 10。
基础链还允许设置链的策略,即在包含的规则中没有明确接受或拒绝的数据包会发生什么。 支持的策略值是接受(这是默认值)或丢弃。
6. 规则rule
规则被添加到指定表指定链中,由表达式和语句组成。操作有add insert replace delete,add和insert命令可支持用句柄handle或index(以0开始)新增规则
在内部,规则位置总是由handle标识,index的转换发生在用户空间。如果在翻译完成后发生并发规则集更改,这有两个潜在影响: 如果在引用的规则之前插入或删除规则,则有效规则index可能会更改。如果引用的规则被删除,则该命令将被内核拒绝,就像给出了无效句柄一样。
注释是单个单词或双引号括起来的多单词字符串,可用于对实际规则注释。注意:如果使用bash添加规则要对双引号进行转义。
# 创建规则—— add 将规则添加到链的末尾,insert 则将规则添加到链的开头。
nft insert rule nat postrouting oif eth0 snat to 1.2.3.5
# 将规则添加到链中指定位置有两种方法——利用handle或index,推荐handle,因为链中有其他规则增加到index之前,则index会发生变化
# add配handle,添加到对应handle后面; insert加handle添加到对应handle之前;
# nft add rule [表名] [链名] handle 9 [规则]
# nft insert rule [表名] [链名] handle 9 [规则]
# 可以在创建规则时就获取到规则的句柄值,只需要在创建规则时同时加上参数 --echo 和 --handle
nft add rule nat postrouting handle 9 oif eth0 snat to 1.2.3.7
nft insert rule nat postrouting handle 9 oif eth0 snat to 1.2.3.6
nft list table nat -a
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oif "eth0" snat to 1.2.3.5 # handle 10
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade # handle 3
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade # handle 4
counter packets 3172 bytes 214592 # handle 5
ip saddr 10.121.0.3 iifname "tun0" oifname "eth0" counter packets 0 bytes 0 masquerade # handle 6
oif "eth0" snat to 1.2.3.6 # handle 12
oif "eth0" snat to 1.2.3.4 # handle 9
}
}
# 删除规则
nft delete rule nat postrouting handle 9
# 更新规则
nft replace rule nat postrouting handle 12 oif eth0 snat to 1.2.3.7
# 查询结果 nft list table nat -a
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oif "eth0" snat to 1.2.3.5 # handle 10
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade # handle 3
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade # handle 4
counter packets 3172 bytes 214592 # handle 5
ip saddr 10.121.0.3 iifname "tun0" oifname "eth0" counter packets 0 bytes 0 masquerade # handle 6
oif "eth0" snat to 1.2.3.7 # handle 12
}
}
# 查询指定表nat的指定链postrouting
nft list chain nat postrouting -a
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oif "eth0" snat to 1.2.3.5 # handle 10
ip saddr 10.121.0.0/16 oifname "wg0" counter packets 0 bytes 0 masquerade # handle 3
iifname "tun0" oifname "wg0" counter packets 0 bytes 0 masquerade # handle 4
counter packets 3172 bytes 214592 # handle 5
ip saddr 10.121.0.3 iifname "tun0" oifname "eth0" counter packets 0 bytes 0 masquerade # handle 6
oif "eth0" snat to 1.2.3.7 # handle 12
}
}
7. 集合set
- 匿名集合
匿名集是没有特定名称的集。集合成员用花括号括起来,在创建使用集合的规则时用逗号分隔元素。一旦删除该规则,该集合也将被删除。它们无法更新,即一旦声明了匿名集,就不能再更改它,除非通过删除/更改使用匿名集的规则。
# 创建表filter
nft add table filter
# 创建表filter的链input
nft add chain filter input
# 用匿名集合创建规则 此处实际上匹配了四条规则
nft add rule filter input ip saddr { 10.0.0.0/8, 192.168.0.0/16 } tcp dport { 22, 443 } accept
table ip filter {
chain input {
ip saddr { 10.0.0.0/8, 192.168.0.0/16 } tcp dport { ssh, https } accept
}
}
- 命名集合
命名集是需要先定义才能在规则中引用的集。与匿名集合不同,元素可以随时添加到命名集合或从命名集合中删除。使用集合名称前缀的@ 从规则中引用集合。
# 先定义命名集合
nft add set filter allowed_hosts { type ipv4_addr \; }
nft list sets
nft list filter allowed_hosts
table ip nat {
}
table inet mytable {
}
table ip filter {
set allowed_hosts {
type ipv4_addr
}
}
# 集合添加元素
nft add element filter allowed_hosts { 192.168.1.2, 192.168.1.3 }
nft list set filter allowed_hosts
table ip filter {
set allowed_hosts {
type ipv4_addr
elements = { 192.168.1.2, 192.168.1.3 }
}
}
# 删除集合元素
nft delete element filter allowed_hosts { 192.168.1.2 }
# 用命名集合创建规则
nft add set filter allowed_ports { type inet_service \; }
nft add element filter allowed_ports { 80, 443, 8000 }
# 查看
nft list set filter allowed_ports
table ip filter {
set allowed_ports {
type inet_service
elements = { http, https, 8000 }
}
}
nft list set filter allowed_ports -nn
table ip filter {
set allowed_ports {
type inet_service
elements = { 80, 443, 8000 }
}
}
# 使用命名集合
nft add rule filter input ip saddr @allowed_hosts tcp dport @allowed_ports accept
# 查询 nft list chain filter input
table ip filter {
chain input {
ip saddr { 10.0.0.0/8, 192.168.0.0/16 } tcp dport { ssh, https } accept
ip saddr @allowed_hosts tcp dport @allowed_ports accept
}
}
设置规格
关键词 | 描述 | 类型 |
---|---|---|
type | 集合所有元素的数据类型 | 字符串: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark |
typeof | 集合元素的数据类型 | 派生数据类型的表达式 |
flags | 设置标志 | 字符串: constant, dynamic, interval, timeout |
timeout | 元素停留在集合中的时间,如果从数据包路径(规则集)中添加集合,则是必需的 | 字符串, decimal followed by unit. Units are: d, h, m, s |
gc-interval | 垃圾收集间隔,仅在 timeout 或 flag timeout 处于活动状态时可用 | 字符串, decimal followed by unit. Units are: d, h, m, s |
elements | 集合包含的元素 | set data type |
size | 集合中元素的最大数量,如果从数据包路径(规则集)中添加集合,则为强制性 | unsigned integer (64 bit) |
policy | 制定政策 | 字符串: performance [default], memory |
auto-merge | 相邻/重叠集合元素的自动合并(仅适用于区间集合) |
8. 字典map
使用不同类型的数据并将匹配条件映射到某一个规则上面,并且由于是哈希映射的方式,可以完美的避免链式规则跳转的性能开销。
设置规格
关键词 | 描述 | 类型 |
---|---|---|
type | 集合所有元素的数据类型 | 字符串: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark |
typeof | 集合元素的数据类型 | 派生数据类型的表达式 |
flags | 设置标志 | 字符串: constant, dynamic, interval, timeout |
elements | 集合包含的元素 | set data type |
size | 集合中元素的最大数量,如果从数据包路径(规则集)中添加集合,则为强制性 | unsigned integer (64 bit) |
policy | 制定政策 | 字符串: performance [default], memory |
匿名字典
# 创建一个表
nft create table ip mytable
# 创建三个个链
nft create chain ip mytable tcpchain
nft create chain ip mytable udpchain
nft create chain ip mytable filterchain
# 地址簇为ip的表mytable的filterchain链增加一条规则——从逻辑上将对 TCP 和 UDP 数据包的处理规则拆分开来
nft add rule ip mytable filterchain meta l4proto vmap { tcp : jump tcpchain, udp : jump udpchain }
# 查看 nft list chain ip mytable filterchain
table ip mytable {
chain filterchain {
meta l4proto vmap { tcp : jump tcpchain, udp : jump udpchain }
}
}
命名字典
# 创建
nft add map ip mytable myvmap { type ipv4_addr : verdict \; }
# 添加元素
nft add element ip mytable myvmap { 192.168.0.10 : accept, 192.168.0.11 : drop }
# 添加规则
nft add rule ip mytable filterchain ip saddr vmap @myvmap
# 查看 nft list table mytable
table ip mytable {
map myvmap {
type ipv4_addr : verdict
elements = { 192.168.0.10 : accept, 192.168.0.11 : drop }
}
chain tcpchain {
}
chain udpchain {
}
chain filterchain {
meta l4proto vmap { tcp : jump tcpchain, udp : jump udpchain }
ip saddr vmap @myvmap
}
}
9. 元素
语法规则
{add | create | delete | get } element [family] table set { ELEMENT[, ...] }
ELEMENT := key_expression OPTIONS [: value_expression]
OPTIONS := [timeout TIMESPEC] [expires TIMESPEC] [comment string]
TIMESPEC := [numd][numh][numm][num[s]]
元素相关命令允许更改命名集合和命名字典的内容。
get命令可以检查一个元素是否包含在一个集合中。
选项 | 描述 |
---|---|
timeout | 带有标志超时的集合/映射的超时值 |
expires | 给定元素到期之前的时间,仅对规则集复制有用 |
comment | 每个元素的注释字段 |
# 创建表
nft create table filter
# 用命名集合创建规则
nft add set filter allowed_ports { type inet_service \; }
nft add element filter allowed_ports { 80, 443, 8000 }
# 查看
nft list set filter allowed_ports
# 删除
nft delete element ip filter allowed_ports {8000}
# 判断某元素是否在集合中【此条未测试通过】
nft get inet_service filter allowed_ports { 8000 }
10. 备份|恢复
# 备份
nft list ruleset >> backup.nft
# 恢复(原子性)
nft -f backup.nft
11. 流表flowtable
flowtable允许在软件中加速数据包转发。其条目通过一个元组表示,元组由输入接口、原地址、目的地址、端口和3/4层协议组成。
12. 有状态对象【重要】
基础语法
{add | delete | list | reset} type [family] table object
delete type [family] table handle handle
list counters [family]
list quotas [family]
有状态对象是附加到表的并由唯一名称标识。它们将规则中的状态信息分组,以在规则中引用它们,使用关键字“类型名称”,例如“计数器名称”。
-
CT Helper
-
基础语法
ct helper helper { type type protocol protocol ; [l3proto family ;] }
-
ct helper用于定义连接跟踪助手,可以将其与ct helper set语句结合使用。type和protocol是强制性的,l3proto 默认派生自表簇,即在 inet 表中,内核将尝试加载 ipv4 和 ipv6 助手后端,如果内核支持它们。
-
-
CT Timeout
-
基础语法
ct timeout name { protocol protocol ; policy = { state: value [, ...] } ; [l3proto family ;] }
-
ct timeout用于更新连接跟踪超时值。超时策略由ct timeout set语句指定。protocol和policy是强制性的,l3proto 默认派生自表族。
-
conntrack 超时规格
关键词 描述 类型 protocol 字符串(例:ip) state 字符串(例:“established”) value 无符号整数 l3proto 地址簇(例:ip) -
定义和分配ct timeout策略
table ip filter { ct timeout customtimeout { protocol tcp; l3proto ip policy = { established: 120, close: 20 } } chain output { type filter hook output priority filter; policy accept; ct timeout set "customtimeout" } }
-
测试和更新超时策略
用
yum install conntrack
安装# 命令 显示流事件 conntrack -E # 结果 前两个值为 协议 剩余秒数 [NEW] icmp 1 30 src=10.121.6.6 dst=192.168.5.71 type=8 code=0 id=1 [UNREPLIED] src=192.168.5.71 dst=192.168.5.119 type=0 code=0 id=1 [UPDATE] icmp 1 30 src=10.121.6.6 dst=192.168.5.71 type=8 code=0 id=1 src=192.168.5.71 dst=192.168.5.119 type=0 code=0 id=1 # 晒选条件为tcp协议22端口 mark是更新标记 conntrack -U -p tcp --dport 22 --mark 10 # 结果 可以看到10.121.6.6访问了192.168.5.71的22端口、58.40.70.86访问了192.168.5.119的22端口 tcp 6 431971 ESTABLISHED src=10.121.6.6 dst=192.168.5.71 sport=6401 dport=22 src=192.168.5.71 dst=192.168.5.119 sport=22 dport=6401 [ASSURED] mark=10 use=2 tcp 6 79 TIME_WAIT src=10.121.6.6 dst=192.168.5.71 sport=9890 dport=22 src=192.168.5.71 dst=192.168.5.119 sport=22 dport=9890 [ASSURED] mark=10 use=2 tcp 6 299 ESTABLISHED src=58.40.70.86 dst=192.168.5.119 sport=2526 dport=22 src=192.168.5.119 dst=58.40.70.86 sport=22 dport=2526 [ASSURED] mark=10 use=2 tcp 6 431943 ESTABLISHED src=58.40.70.86 dst=192.168.5.119 sport=2528 dport=22 src=192.168.5.119 dst=58.40.70.86 sport=22 dport=2528 [ASSURED] mark=10 use=2
-
-
CT Expectation
-
基础语法
ct expectation name { protocol protocol ; dport dport ; timeout timeout ; size size ; [*l3proto family ;] }
-
ct expectation 用于创建连接期望。期望是用ct expectation set语句分配的。protocol, dport, timeout 和 size是强制性的,l3proto 默认源于表簇。
-
conntrack 期望规格
关键词 描述 类型 protocol 期望对象的第四层协议 字符串(例:ip) dport 期望连接的目的端口 无符号整数 timeout 期望的超时值 无符号整数 size 期望的大小值 无符号整数 l3proto 期望对象的第3层协议 地址簇(例:ip) -
定义和分配ct expectation策略
table ip filter { ct expectation expect { protocol udp dport 9876 timeout 2m size 8 l3proto ip } chain input { type filter hook input priority filter; policy accept; ct expectation set "expect" } }
-
-
Counter
-
基础语法
counter [packets bytes]
-
counter 规格
关键词 描述 类型 packets 数据包的初始计数 无符号整数 (64 bit) bytes 初始字节数 无符号整数 (64 bit)
-
-
Quota
-
基础语法
quota [over | until] [used]
-
counter 规格
关键词 描述 类型 quota 配额限制,用作配额名称 两个参数,无符号整数 (64 bit)和字符串,bytes, kbytes, mbytes 需要在这些参数前写上 “over” 和"until" used 已用配额的初始值 两个参数,无符号整数 (64 bit)和字符串,bytes, kbytes, mbytes
-
13. 表达式Expression
表达式表示值,可以是网络地址、端口号等常量,也可以是在规则集评估期间从数据包中收集的数据。可以使用二进制、逻辑、关系和其他类型的表达式组合表达式以形成复杂或关系(匹配)表达式。它们还用作某些类型操作的参数,例如 NAT、数据包标记等。每个表达式都有一个数据类型,它决定了符号值的大小、解析和表示以及与其他表达式的类型兼容性。
# 描述命令
describe expression | data type
nft describe tcp flags
14. 数据类型
14种,暂时留空
15. 主要表达式
- 元表达式
meta {length | nfproto | l4proto | protocol | priority}
[meta] {mark | iif | iifname | iiftype | oif | oifname | oiftype | skuid | skgid | nftrace | rtclassid | ibrname | obrname | pkttype | cpu | iifgroup | oifgroup | cgroup | random | ipsec | iifkind | oifkind | time | hour | day }
元表达式类型
Keyword | Description | Type |
---|---|---|
length | 数据包的长度(以字节为单位) | 整数(32-bit) |
nfproto | 真正的钩子协议族,仅在 inet 表中有用 | 整数(32 bit) |
l4proto | 4层协议,跳过 ipv6 扩展标头 | 整数(8 bit) |
protocol | EtherType 协议值 | ether_type |
priority | TC 报文优先级 | tc_handle |
mark | 报文标记 | mark |
iif | 输入接口索引 | iface_index |
iifname | 输入接口名称 | ifname |
iiftype | 输入接口类型 | iface_type |
oif | 输出接口索引 | iface_index |
oifname | 输出接口名称 | ifname |
oiftype | 输出接口硬件类型 | iface_type |
sdif | 从机输入接口索引 | iface_index |
sdifname | 从设备接口名称 | ifname |
skuid | 与原始套接字关联的 UID | uid |
skgid | 与原始套接字关联的 GID | gid |
rtclassid | 路由领域 | realm |
ibrname | 输入桥接口名称 | ifname |
obrname | 输出桥接口名称 | ifname |
pkttype | packet type | pkt_type |
cpu | 处理数据包的 CPU 编号 | 整数(32 bit) |
iifgroup | 传入设备组 | devgroup |
oifgroup | 传出设备组 | devgroup |
cgroup | 控制组标识id | 整数(32 bit) |
random | 伪随机数 | 整数(32 bit) |
ipsec | 若数据包是 ipsec 加密的,则为 true | 布尔值(1 bit) |
iifkind | 输入接口种类 | |
oifkind | 输出接口种类 | |
time | 接收包的绝对时间 | 整数(32 bit) 或 字符串 |
day | 星期几 | 整数(8 bit) 或 字符串 |
hour | 一天中的第几小时 | 字符串 |
元表达式特定类型
类型 | 描述 |
---|---|
iface_index | 接口索引(32 位数字) 可以用数字指定,也可以指定为现有接口的名称。 |
ifname | 接口名称(16 字节字符串) 不一定存在。 |
iface_type | 接口类型(16 位数字) |
uid | 用户 ID(32 位数字) 可以用数字或用户名指定。 |
gid | 组 ID(32 位数字) 可以用数字或组名指定。 |
realm | 路由领域(32 位数字)。可以用数字指定或作为 /etc/iproute2/rt_realms 中定义的符号名称指定。 |
devgroup_type | 设备组(32 位数字)。可以用数字指定,也可以指定为 /etc/iproute2/group 中定义的符号名称。 |
pkt_type | 数据包类型:主机(寻址到本地主机)、广播(对所有)、多播(对组)、其他(寻址到另一台主机)。 |
ifkind | I接口种类(16 字节字符串)。有关列表,请参阅ip-link(8)中的TYPES 。 |
time | ISO 格式的整数或日期。例如:“2019-06-06 17:00”。小时和秒是可选的,如果需要可以省略。如果省略,则假定为午夜。以下三个等效:“2019-06-06”、“2019-06-06 00:00”和“2019-06-06 00:00:00”。当给出一个整数时,它被假定为一个 UNIX 时间戳。 |
day | 一周中的某一天(“Monday”、“Tuesday”等),或者 0 到 6 之间的整数。字符串不区分大小写匹配,并且不需要完全匹配(例如,“Mon”将匹配“Monday” )。当给出整数时,0 是星期日,6 是星期六。 |
hour | 以 24 小时格式表示小时的字符串。可以选择指定秒数。例如,17:00 和 17:00:00 是等价的。 |
# 使用元表达式
# 合格的元表达式
filter output meta oif eth0
filter forward meta iifkind { "tun", "veth" }
# 【不合格的元表达式】
filter output oif eth0
# 传入的数据包经过 ipsec 处理
raw prerouting meta ipsec exists accept
-
套接字表达式
-
Osf表达式
-
路由表达式
-
Numgen表达式
-
哈希表达式
16. 有效载荷表达式
留空待写
17. 语句
- Nat语句
语法规则
snat [[ip | ip6] to] ADDR_SPEC [:PORT_SPEC] [FLAGS]
dnat [[ip | ip6] to] ADDR_SPEC [:PORT_SPEC] [FLAGS]
masquerade [to :PORT_SPEC] [FLAGS]
redirect [to :PORT_SPEC] [FLAGS]
ADDR_SPEC := address | address - address
PORT_SPEC := port | port - port
FLAGS := FLAG [, FLAGS]
FLAG := persistent | random | fully-random
nat 语句仅对 nat 链类型有效。
待补充
18. 参考文档
- nftables用户手册 man nft - mankier.com
- golang库-nftableslib——lib文档
- nftables官方文档 nftables HOWTO documentation page——HowTo中文翻译
- 疑难问题解决和 FAQ
- 其他前辈的文章1
- 基佬杨写的教程
- 第七章是nftables入门 Red Hat Enterprise Linux 8 安全网络-配置安全网络和网络通信
- nftables家族介绍
- 官方故障排除文档
- 剖析语法文档——nftables相比iptables到底改变了什么
- ebpf防火墙GUI版本——ebpfsnitch