![Linux 平台上每个端口的 MAC 地址数量限制](https://linux22.com/image/757987/Linux%20%E5%B9%B3%E5%8F%B0%E4%B8%8A%E6%AF%8F%E4%B8%AA%E7%AB%AF%E5%8F%A3%E7%9A%84%20MAC%20%E5%9C%B0%E5%9D%80%E6%95%B0%E9%87%8F%E9%99%90%E5%88%B6.png)
我希望限制特定端口上允许学习的 MAC 地址数量。L2 交换机上也有类似的功能。例如这基于 cisco 的配置。如果达到最大值,则具有新 MAC 地址的数据包预计为:
- 没学过Linux bridge
- 掉落。
我希望在 bridge 模块中实现这样的功能,但我没有找到任何相关的配置/代码。是否可以使用 iptables/ebtables 实现相同的功能,还有其他选择吗?
谢谢,伊利亚
答案1
iptables发生得太晚,无法发挥作用。ebtables缺乏太多可用功能,而且无论如何都会受到与nftables' 桥梁家族如下所述。
一种可能的方法是使用nftables在里面网络设备家庭和放将其大小设置为允许存储它们的最大 MAC 地址数,并且如果需要,将其元素的默认超时设置为桥的老化时间。
先决条件
这网络设备家族表要求接口(此处为桥接端口)提前存在,以便创建使用它的基础链。因此,只有在存在此类接口后,才必须加载该表。如果是虚拟接口,则应在创建后立即加载该表,在接口启动之前加载,或者至少在将其设置为桥接端口之前加载,以防止发生学习。
足够新的版本nftables并且应该使用内核:
- nftables0.9.1 引入了动态的下面存在的关键字(以前的版本仍然可以省略),因此nftables>= 0.9.1 应为首选,
- nftables 0.8.4 引入了一种新的语法来从数据包路径中添加元素,因此应避免使用 nftables <0.8.4 或重新制定规则,
- 内核 4.2 引入了对网络设备系列:内核 >= 4.2 是必需的
执行
如果过滤是在桥接层进行的(又称桥梁家庭),这确实会过滤流量,但这不会阻止网桥在过滤器丢弃额外的 MAC 地址之前学习任何 MAC 地址,因为网络过滤器的桥接钩子在桥接器看到这些帧后从桥接器调用(可以通过运行来确认bridge monitor fdb
)。可以禁用学习全部桥接端口上的 MAC,但不选择哪些是或不是。
所以应该这样做前桥接器,以防止它看到 MAC 地址,这样它就不可能学习它:在接口级别,使用网络设备家庭。网络过滤器目前只能处理入口在里面网络设备家庭,但这没问题,因为我们只对过滤这种情况的入口流量感兴趣:从“外部”到达并进入网桥的流量。
由于这是一个相对简单的过滤器,放置在桥接器之前,因此它不会处理任何花哨的东西。它不会以不同的方式处理 VLAN 标记数据包(这可以在规则集中扩展,添加针对特定 VLAN 的附加设置和检查。它仍然是一个固定的规则集,大多数更改都需要更改设置/链/规则)。
在里面网络设备系列基链与接口绑定。
更新:更改了答案,以便处理老化问题,这样最近未见过的 MAC 地址槽在一段时间后可以自由重复使用(最好是桥的老化时间,或此时间加一秒)。同时放弃“快速路径”规则,因为现在每个数据包无论如何都必须更新源 MAC 的计时器。更新规则表现为添加规则,但它也会将计时器重置为超时值(当规则中没有说明时规则是默认定义的放)。如果某个 MAC 地址在这段时间内没有出现,内核会自动将其从集合中删除。只剩下一条规则可以做到这一点:
- 对于收到的任何帧,使用源 MAC 地址更新集合:
- 如果集合已满并且尝试添加新的 MAC 地址,则失败,因此不会执行剩余的接受陈述,
- 否则,在集合中添加新的 MAC 地址,或刷新它(如果已经存在),超时时间为 30 秒,然后执行接受陈述
- 放弃剩余的所有东西(默认策略)。
规则集
在此示例中,可以使用以下方式加载规则集nft -f portsecmax.nft
:
桥接端口接口名为swp1(可能是eth0或者ens224等等),并且选择了同名的基础链,
用于记忆 MAC 地址的集合的大小设置为允许的最大 MAC 地址数量:本例中为 3,
集合元素的默认超时时间为 30 秒,这是默认值老化时间在 Linux 桥上,除非发生更改。如果用例是永远保留第一个尺寸(此处有 3 个)看到的 MAC 地址,请从
timeout 30s
下面删除。
portsecmax.nft
:
table netdev portsecmax # for idempotency
delete table netdev portsecmax # for idempotency
table netdev portsecmax {
set macswp1 {
type ether_addr
size 3
flags dynamic,timeout
timeout 30s
}
chain swp1 {
type filter hook ingress device "swp1" priority filter; policy drop;
update @macswp1 { ether saddr } accept comment "false if set is full and adding a new element"
}
}
重置允许的 MAC 地址列表:
nft flush set netdev portsecmax macswp1
禁用该功能(选择以下三个选项之一):删除表或删除链或将链的默认策略更改为接受:
nft delete table netdev portsecmax
nft delete chain netdev portsecmax swp1
nft add chain netdev portsecmax swp1 '{ policy accept; }'