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