我可以增加 nftables 规则集语法的可读性吗?这会影响其功能吗?

我可以增加 nftables 规则集语法的可读性吗?这会影响其功能吗?

从手册中我无法清楚了解这些命令的功能是否相同:

meta skuid == "root" counter accept
skuid 0 counter accept

ct state == { established,  related } counter accept
ct state established,related counter accept

我关于语法的问题是:

  1. 我可以跳过单词吗meta(似乎在中使用项目时必须跳过log flags)?
  2. 我可以在任何匹配某些内容的命令中添加 == 符号吗(为了便于阅读)?
  3. 我可以将列表(项目集)写为item1,item2和不可以吗{ item1, item2 },或者它仅适用于ct命令?

答案1

要验证两个规则是否相同,甚至不仅仅是显示相同(在涉及多个协议层的极少数情况下,规则可能显示相同,功能相同,但在字节码级别不完全相同,这几乎是一个可重复性错误),请使用该选项,--debug=netlink该选项还将显示发送到内核的字节码。如果字节码相同,则规则相同。

这是一个交互式示例(使用 nftables 1.0.9。结果可能根据版本的不同而略有不同):

$ unshare -Urnm
# nft -V
nftables v1.0.9 (Old Doc Yak #3)
  cli:      editline
  json:     yes
  minigmp:  no
  libxtables:   yes
# nft add table t
# nft add chain t c
# nft --debug=netlink add rule t c 'meta skuid == "root" counter accept'
ip t c
  [ meta load skuid => reg 1 ]
  [ cmp eq reg 1 0x00000000 ]
  [ counter pkts 0 bytes 0 ]
  [ immediate reg 0 accept ]

# nft --debug=netlink add rule t c 'skuid 0 counter accept'
ip t c
  [ meta load skuid => reg 1 ]
  [ cmp eq reg 1 0x00000000 ]
  [ counter pkts 0 bytes 0 ]
  [ immediate reg 0 accept ]

# nft --debug=netlink add rule t c 'ct state == { established,  related } counter accept'
__set%d t 3 size 2
__set%d t 0
    element 00000002  : 0 [end] element 00000004  : 0 [end]
ip t c
  [ ct load state => reg 1 ]
  [ lookup reg 1 set __set%d ]
  [ counter pkts 0 bytes 0 ]
  [ immediate reg 0 accept ]

# nft --debug=netlink add rule t c 'ct state established,related counter accept'
ip t c
  [ ct load state => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x00000006 ) ^ 0x00000000 ]
  [ cmp neq reg 1 0x00000000 ]
  [ counter pkts 0 bytes 0 ]
  [ immediate reg 0 accept ]

可以看出,前 2 条规则是相同的。Indeed"root"照常由用户空间解析为 uid 0,并且meta关键字是可选的(至少对于此处的版本而言)。

最后两条规则,即使功能相同,也不完全相同。On case 使用一组匿名的两个值。但这两个值应该以按位方式组合(即:所有可能的符号都有不同的 2 指数作为值),这就是最后一条规则的作用,其中 扮演了,不同的角色。乍一看,我会说第二条ct规则比第一条更优化:不需要涉及集合查找。

第一种情况仍然存在:当使用vmap(判定图而不是简单集合)根据以下情况调用不同的判定时连接跟踪单一规则中的规定。

无论你选择什么,对于给定的nftables版本,它将始终以一种方式显示回来:

# nft -s list ruleset
table ip t {
    chain c {
        meta skuid 0 counter accept
        meta skuid 0 counter accept
        ct state { established, related } counter accept
        ct state established,related counter accept
    }
}
# 

这可能就是应该使用的,或者最终可能会被使用的,只是因为当手动处理而不是通过工具处理时,转储规则集,编辑它并重新加载它通常是可行的。

中的情况ct根本无法概括:只有涉及两个值的幂时才能完成第二种变体(如果实现了特定的语法支持),因此它们可以通过按位运算进行组合:

# nft describe ct state
ct expression, datatype ct_state (conntrack state) (basetype bitmask, integer), 32 bits

pre-defined symbolic constants (in hexadecimal):
    invalid                         0x00000001
    new                             0x00000008
    established                     0x00000002
    related                         0x00000004
    untracked                       0x00000040
# 

一个明显的例子是使用 TCP 标志nftables

# nft describe tcp flags
payload expression, datatype tcp_flag (TCP flag) (basetype bitmask, integer), 8 bits

pre-defined symbolic constants (in hexadecimal):
    fin                             0x01
    syn                             0x02
    rst                             0x04
    psh                             0x08
    ack                             0x10
    urg                             0x20
    ecn                             0x40
    cwr                             0x80
# 

就像ct

# nft --debug=netlink add rule t c 'tcp flags { ack,syn } accept'
__set%d t 3 size 2
__set%d t 0
    element 00000010  : 0 [end] element 00000002  : 0 [end]
ip t c
  [ meta load l4proto => reg 1 ]
  [ cmp eq reg 1 0x00000006 ]
  [ payload load 1b @ transport header + 13 => reg 1 ]
  [ lookup reg 1 set __set%d ]
  [ immediate reg 0 accept ]

# nft --debug=netlink add rule t c 'tcp flags ack,syn accept'
ip t c
  [ meta load l4proto => reg 1 ]
  [ cmp eq reg 1 0x00000006 ]
  [ payload load 1b @ transport header + 13 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
  [ cmp neq reg 1 0x00000000 ]
  [ immediate reg 0 accept ]

# nft --debug=netlink add rule t c 'tcp flags ack|syn accept'
ip t c
  [ meta load l4proto => reg 1 ]
  [ cmp eq reg 1 0x00000006 ]
  [ payload load 1b @ transport header + 13 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
  [ cmp neq reg 1 0x00000000 ]
  [ immediate reg 0 accept ]

# 

最后两条规则(请注意使用|按位或运算而不是,内置语法)完全相同。但第一条规则使用匿名集,就像上一种情况一样。在此示例的所有情况下,多个 TCP 标志中有一个匹配就足以匹配:功能等效。如果需要同时匹配两个标志,则只有第二种情况可用。

通常,下面的规则需要同时存在两个标志,不能用匿名集来实现:

# nft --debug=netlink add rule t c 'tcp flags & (syn|ack) == syn|ack accept'
ip t c
  [ meta load l4proto => reg 1 ]
  [ cmp eq reg 1 0x00000006 ]
  [ payload load 1b @ transport header + 13 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
  [ cmp eq reg 1 0x00000012 ]
  [ immediate reg 0 accept ]


# nft list ruleset
[...]
        tcp flags syn,ack / syn,ack accept
[...]

注意:以这种方式组合标志是没有意义的,ct因为与 TCP 标志相反,一次只能存在一个标志(给定的数据包不能有多个连接跟踪状态)。

相关内容