集合(Sets)

nftables 提供了内建的通用的集合(set)机制,它允许你使用任何支持的选择器创建集合。集合可能使用字典(dictionaries)映射组(maps)表示。

集合的元素在内部通常使用性能好的数据结构比如哈希表和红黑树表示。

匿名集合

匿名集合是:

  • 绑定到一条规则,规则被删除时,集合也会被删除
  • 它们没有特定的名字,内核会为它们分配一个标识符
  • 它们不能被更新,所以一旦绑定到规则上后就不能添加和删除元素

下面的例子显示了如何创建一个简单的集合:

% nft add rule filter output tcp dport { 22, 23 } counter

上面的规则捕获所有到 TCP 22 和 23 端口的通信,同时更新计数器。

命名集合

你可以使用下面的命令创建命名集合:

% nft add set filter blackhole { type ipv4_addr\;}

注意这个例子中 blackhole 是集合的名字,type 选项指示集合中数据的类型,在这个例子中是 IPv4 地址。当前最大支持长度 16 个字符的集合名字。

% nft add element filter blackhole { 192.168.3.4 }
% nft add element filter blackhole { 192.168.1.4, 192.168.1.5 }

然后你可以在规则中使用它:

% nft add rule ip input ip saddr @blackhole drop

当前支持的数据类型有:

  • ipv4_addr:IPv4 地址
  • ipv6_addr:IPv6 地址
  • ether_addr:以太网(Ethernet)地址
  • inet_proto:网络协议
  • inet_service:网络服务
  • mark:标记类型

命名集合可以在任何时候更新,所以你可以添加和删除元素。

Eric Leblond 在他的 Why you will love nftables 文章中展示了一个简单的例子用来比较 iptablesnftables

ip6tables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT

这在 nftables 可以用几条带集合的规则表示为:

% nft add rule ip6 filter input tcp dport {telnet, http, https} accept
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept

列出命名集合

你可以使用下面的命令列出命名集合的内容:

% nft list set filter myset