是否可以基于时间戳构建 nftables 映射?
目前我使用:
numgen random mod 2 map {
0: 10.10.10.1,
1: 10.10.10.2,
}
但是如何将random mod 2
表达式转换为,即每 30 分钟交替(timestamp / 1800) mod 2
生成 map 的键0
?1
是否可以基于时间戳构建 nftables 映射?
目前我使用:
numgen random mod 2 map {
0: 10.10.10.1,
1: 10.10.10.2,
}
但是如何将random mod 2
表达式转换为,即每 30 分钟交替(timestamp / 1800) mod 2
生成 map 的键0
?1
可以通过使用名为map的预先计算的查找来解决nftables的限制。
必需的:
meta hour
typeof
并且type
这似乎是. 或者不会被接受,即使像旧的 nftables一样被读回。meta hour
type meta hour
type hour
typeof meta hour
type hour
nftables
不能进行任意算术(或逻辑等)运算。目前它仅限于对必须来自数据包路径或一些扩展的数据在左侧(LHS)执行一些操作numgen
,并将其与恒定的右侧(RHS)进行比较,包括从集和地图。没有办法让nftables计算 LHS 中的任意除法(使用右移除以两个作品的幂,但请参见下文)。而且似乎也没有办法将这种计算的结果表示为命名映射中被接受为键的数据类型,因为通常是这种操作的结果的“非限定”整数类型不是有效的键类型一个命名的地图,至少目前是这样。例如,我不确定
numgen
表达式是否可以与命名地图一起使用,即使它与匿名地图一起使用。对于这种情况,Linux 内核 5.4在内核中引入了与数据包时间戳相关的元语句:
在这里,
meta hour
提供了缺少的必需操作“mod 86400”,这与 OP 的“timestamp / 1800”要求足够相关:给出了自一天开始以来数据包的时间。此外,它有一个特定的类型,允许它在命名地图中使用。作为一种类似于循环展开以简化复杂操作的方法,可以预先计算表达式中无法计算的值并将其存储在映射表中,只要该类型对命名映射有效即可。这是可以接受的,因为条目的数量是预先知道的,并且仍然是有限的:对于这种情况,一天有 48 个半小时。
然后映射可以提供最终结果:IPv4 地址。
负载均衡器(执行dnat )的示例规则集,它将wan0上接收的所有流量在每小时的前半小时转发到 10.10.10.1,在后半小时转发到 10.10.10.2:
生成 nftables 命令以填充地图hour2ip的脚本(使用
./script.sh | nft -f -
):这将生成这种命令:
笔记:
meta hour
(它是模数)发送到内核或从内核显示回来的方式,通常只使用 UTC 时间。这就是为什么排序会根据当前时区发生变化,但会按预期运行。TZ=UTC
您可以在显示时检查使用或不使用环境变量的效果nft list map ip mytable hour2ip
以更好地理解它。如果您更喜欢使用标记来获得更大的灵活性(通过在其他地方重用标记,而不仅仅是dnat规则,包括将其保存到connmark),您可以使用例如两个映射:一个映射小时来标记,另一个映射标记为 IP 地址。
为此,例如将之前的规则集替换为:
并在生成条目的前一个脚本中替换:
和:
创建填充hour2mark的命令,例如: