我正在构建一个基于 iptables 的防火墙配置工具,并尝试使“线路碰撞”场景发挥作用。
eth0
给定一个带有eth1
桥接器br0
和第三个接口的设置eth2
:
| | |
eth0 eth1 eth2
| == br0== | |
| |
| |
--- linux node ---
在这种情况下,假设我想丢弃 TCP 端口 80 的流量(如果它要流向连接到的网络)eth0
,但允许它流向eth1
。
因此,我尝试可靠地匹配通过特定接口发出的数据包eth0
。
如果我在表中添加以下 iptables 规则filter
:
-A FORWARD -o br0 --physdev-out eth0 -j LOG
给定一个来自eth1
(网桥的另一半)的数据包,则规则匹配得很好,记录如下:
... IN=br0 OUT=br0 PHYSIN=eth2 PHYSOUT=eth1 ...
然而,如果数据包来自eth2
,那么规则不再匹配。
看来路由算法无法确定选择哪个桥接接口,因此数据包通过桥接器中的两个接口发送出去。
如果我添加另一个更加混杂的日志规则,那么我会得到该数据包的以下日志输出:
... IN=eth2 OUT=br0 ...
我的猜测是,在第一种情况下,路由算法可以选择桥上的其他接口,因为该数据包不应该按照它来时的路径出去。在第二种情况下,它没有选择特定的接口,因此你根本得不到任何 physdev 信息!
然而,如果网桥已经获知了目标 MAC 地址(如图所示brctl showmacs br0
),那么它就可以确定正确的接口,并且您会再次获得 physdev 信息。
(还有第三种情况:这似乎适用于桥接器包含三个接口的情况,但仅通过排除源接口,它仍然无法建立单个接口来发送数据包。)
所以,问题是,无论如何我怎样才能可靠地匹配发出的数据包eth0
?
鉴于我在开始时给出的示例,仅匹配将通过多个接口路由出去的数据包是不够的,其中一个是eth0
(尽管这在其他情况下会很有用)。我希望能够以不同的方式处理eth0
和的流量eth1
,允许流量通过eth1
,但不允许eth0
。
答案1
观察到的行为的原因
当数据包从非桥接接口到达时,iptables 没有获取物理桥接信息的原因是,数据包从未靠近桥接机制,即使此时我们知道我们正在桥接上将其发送出去。
如果数据包确实通过桥接端口到达,但它是 N>2 桥接,那么问题在于 iptables PHYSDEV 扩展仅为“out”提供一个值,因此它不会告诉我们是否有两个。
解决方案
使用 ebtables 而不是 iptables。ebtablesOUTPUT
链将知道它在哪个物理桥接接口上发送数据包。
在上述场景中,您想要过滤通过特定桥接接口(eth0
)离开的数据包,而不管它如何到达系统,请添加如下 ebtables 规则:
-A OUTPUT -o eth0 -j <target>
在更复杂的场景中,如果你想过滤从特定接口到达并通过桥接接口离开的数据包,事情会变得更加困难。假设我们想丢弃所有从eth2
(非桥接)到eth0
(桥接为 的一部分br0
)的流量,我们需要将此规则添加到iptables:
-A FORWARD -i eth2 -o br0 -j MARK --set-mark 1234
这将标记来自eth2
和发往网桥的任何数据包。然后我们将此规则添加到ebtables:
-A OUTPUT -physdev-out eth0 --m mark --mark 1234 -j DROP
DROP
任何被 iptables 标记为来自 的数据包都将eth2
通过特定的桥接端口传出eth0
。
致谢
感谢 netfilter iptables 邮件列表的 Pascal Hambourg 帮助我们提出这个解决方案。