这里是高级程序员,但讨厌 Linux 网络限制,与所有编程语言相比,这使事情变得困难。
实际上我需要做基于策略的路由允许特定的 lan IP 地址选择特定的传出接口(比如说 eth5)。在我的情况下,即使 ipset 也不够强大。我想允许第一个八进制为“10”而最后一个八进制以“9”结尾的所有 lan ip。这将是10.*.*.??9
javascript 中的 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 的情况更严重),所以我什至没有尝试解决这种情况。