ipset 替代方案或某种通配符的聪明想法

ipset 替代方案或某种通配符的聪明想法

这里是高级程序员,但讨厌 Linux 网络限制,与所有编程语言相比,这使事情变得困难。

实际上我需要做基于策略的路由允许特定的 lan IP 地址选择特定的传出接口(比如说 eth5)。在我的情况下,即使 ipset 也不够强大。我想允许第一个八进制为“10”而最后一个八进制以“9”结尾的所有 lan ip。这将是10.*.*.??9javascript 中的 orif(ip.match("\10\..*\.(\d+9|9)\g")) ...USE eth5

有谁知道某种技巧可以实现这一目标?如果我们必须坚持使用 CIDR,那可能会有数千个 IP CIDR,这太疯狂了。

谢谢

答案1

我不会将我的答案限制在算法的一小部分,因为 OP 也达到了实现限制。答案必须与他们合作。


路由堆栈是 Linux 网络堆栈的一部分,仅限于处理33 个 CIDR 网络掩码相当于 /32 (/255.255.255.255) 直到 /0 (/0.0.0.0) 。

网络堆栈的其他部分,例如某些防火墙设施,则不受此限制。通过使用 255.0.0.255 等网络掩码,可以忽略 IPv4 地址中的 2 个中间数字部分。遗憾的是,网络掩码可以轻松处理 2 的幂或除以 2 的幂的余数,但无法帮助处理模 10(除以 10 的余数),并且除以 10 在数据包处理中不可用。因此,仍然有 9 到 249 之间的 25 个值需要检查,并且需要这些值的列表。唉,再说一遍IP集也受限于 CIDR 网络掩码, 和iptables' 用于IP集不允许使用非约束网络掩码:IP集根本无法使用。

要么使用〜25iptables规则(不是那么多)或使用更灵活的nftables与一个

iptables

仅使用网络掩码 255.0.0.0 检查 IPv4 地址开头部分10.,并检查最后部分的 25 种可能性。根据要解决的具体问题,可以添加要考虑的传入接口的附加限制。

iptables -t mangle -N specialrouting
iptables -t mangle -A PREROUTING -s 10.0.0.0/255.0.0.0 -j specialrouting

specialrouting例如,要使用 25 种可能性填充用户链,请使用此巴什脚本:

#!/bin/bash

iptables -t mangle -F specialrouting # for idempotence
for i in {9..255..10}; do
    iptables -t mangle -A specialrouting -s 10.0.0.$i/255.0.0.255 -j MARK --set-mark 0xcafe
done

最后,2^16(对于两个被忽略的中间字节)x 25 = 1638400 种可能性将获得标记。

如果模数为 16(2 的幂),则过滤 16 个值 9、25、41、57 ... 249,而不是 25 个模 10 的值,那么上面的所有内容都可以用单个规则替换,因为网络掩码可以处理任何 2 的幂的模数。这里网络掩码 255.0.0.15(0xff00000f)可与以下单个规则一起使用:

iptables -t mangle -A PREROUTING -s 10.0.0.9/255.0.0.15 -j MARK -set-mark 0xcafe

或者用nftables

通过使用类似于上面的脚本预先计算的集合的元素列表,模 10 情况的规则集将是(要加载nft -f specialrouting.nft):

specialrouting.nft:

table ip specialrouting         # for idempotence
delete table ip specialrouting  # for idempotence

table ip specialrouting {
    set modulo10 {
        type ipv4_addr
        flags constant
        elements = { 10.0.0.9, 10.0.0.19,
                 10.0.0.29, 10.0.0.39,
                 10.0.0.49, 10.0.0.59,
                 10.0.0.69, 10.0.0.79,
                 10.0.0.89, 10.0.0.99,
                 10.0.0.109, 10.0.0.119,
                 10.0.0.129, 10.0.0.139,
                 10.0.0.149, 10.0.0.159,
                 10.0.0.169, 10.0.0.179,
                 10.0.0.189, 10.0.0.199,
                 10.0.0.209, 10.0.0.219,
                 10.0.0.229, 10.0.0.239,
                 10.0.0.249 }
    }

    chain prerouting {
        type filter hook prerouting priority -150; policy accept;
        ip saddr & 255.0.0.255 == @modulo10 meta mark set 0xcafe
    }
}

对于模 16 的单nftables规则(没有其样板)将类似于单一的iptables上面的规则:

ip saddr & 255.0.0.15 == 10.0.0.9 meta mark set 0xcafe

使用标记进行布线

然后,数据包上设置的标记(仅在 Linux 网络堆栈中该数据包的内部生命周期内)可以用作路由堆栈的消息,并与路由规则匹配以使用备用路由表:

ip rule add fwmark 0xcafe lookup 100

接下来是表 100 中的路由,其中​​包括最重要的路由dev eth5,此外还包括从主要的路由表:

ip route add ... dev eth5 table 100
...

返回流量来自以太坊5可能应该使用同一个表:

ip rule add iif eth5 lookup 100

补充笔记

至少在测试时,避免因为路由不完整而导致流量下降,SRPF, IErp_filter,不应启用(如果发行版默认启用它):

for i in $(sysctl -N -ar 'net\.ipv4\.conf\..*\.rp_filter'); do sysctl -w $i=0; done

使用标记时还有其他可能性,例如将标记存储在流的 conntrack 条目中,但如果没有设置的精确描述,我不知道这里需要什么。这个博客有几个例子:Linux 及更高版本! Netfilter康马克

请注意,涉及重新路由标记当地发起的(或相同的本地终止)流量而不是转发/路由流量会遇到极端情况(UDP 的情况比 TCP 的情况更严重),所以我什至没有尝试解决这种情况。

相关内容