iptables:接口上的 DROP 不执行任何操作,但如果我不指定接口,则可以工作

Jam*_*ieB 5 networking firewall iptables

设置:

Ubuntu 20.04 位于具有 5 个物理以太网端口(我们称其为 eth1 - eth5)的盒子上。

我已使用 brctl 将它们全部连接到网桥(“br0”),并且它们都可以互相 ping 通。

我正在尝试做的事情:允许 eth2 - eth5 继续彼此自由聊天,同时限制可以通过 eth1 进入的内容。(最终 eth1 将成为特定入站流量的“外部连接”,而其他接口可以自由通信。)

iptables -A FORWARD -j DROP

期望:每个人都会失明。效果很好。桥接器使用 iptables 中的规则。测试成功,撤消该操作。

iptables -F
iptables -A FORWARD -i eth1 -j DROP
Run Code Online (Sandbox Code Playgroud)

预期:eth1 失明,但其他一切都很好。现实:什么也没有发生。我仔细检查了 iptables -L,其中唯一的东西是 Chain FORWARD 下的一个“DROP all - Anywhere”。

iptables -F
iptables -A FORWARD -i br0 -j DROP
Run Code Online (Sandbox Code Playgroud)

这似乎有影响。连接的笔记本电脑仍然可以 ping 网桥本身,但无法相互 ping 通。

为什么当我删除特定接口时它不起作用?

我也愿意接受诸如“你以完全错误的方式处理这件事”之类的建议。另请注意:我试图避免任何类型的 IP 过滤。我想按接口(物理以太网端口)进行过滤,而不是按插入其中的 IP 地址进行过滤。

A.B*_*A.B 12

iptables工作在路由层。它在桥接层不起作用。一旦eth1设置为桥接端口,就不再参与路由。这意味着不会有数据包被路由通过,并且通常它根本eth1不会遍历iptables 。

br_netfilter、桥接和iptables

有一个问题:当br_netfilter模块加载时(通常由 Docker加载),iptables还将过滤桥接的IPv4 帧。OP的问题暗示模块已加载。这种情况如下图所示,蓝色字段中的绿色框(处理 IPv4 的iptables)(以太网桥接):

Netfilter 和通用网络中的数据包流

在这种情况下,任何桥接帧都将通过处理该帧 ( ) 的桥出现在iptablesbr0中。eth1仍然无法像路由接口一样被引用。相反,这需要特殊physdev模块(它也会触发 的加载br_netfilter)来指定桥接端口。必须注意区分桥接流量和路由流量,因为iptables会看到两者。本文档可以帮助处理更复杂的规则集:基于 Linux 的桥接器上的 ebtables/iptables 交互第 7 节

所以最后,当模块br_netfilter被加载时,或者无论如何通过以下规则加载时,为了实现目标,下面这个非常简单的例子就可以了。由于我没有来自 OP 的有关 Docker 或其他任何内容的上下文,因此我必须首先强制 FORWARD 的策略接受并插入规则,因为如果默认策略是 DROP 并且 Docker 加载了自己的规则,那么这个简单的示例还远远不够:

iptables -P FORWARD ACCEPT
iptables -F FORWARD

iptables -I FORWARD 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -I FORWARD 2 -m physdev --physdev-in eth1 -j DROP
Run Code Online (Sandbox Code Playgroud)

nftables

这需要内核 >= 5.3。

请注意,如果没有理由加载br_netfilter(例如运行 Docker),则可以在适当的位置直接使用nftables ,而不是使用iptables :网桥系列,因为nftables可以直接在网络中使用状态防火墙的conntrack设施。 Bridge 系列,没有这个拼凑(最初是因为ebtables不能使用conntrack)。

因此,我们可以br_netfilter完全删除该模块:

rmmod br_netfilter
Run Code Online (Sandbox Code Playgroud)

这样做会扰乱 Docker。

或者只是br_netfilter在当前网络命名空间和当前桥上禁用 的功能(如果加载的话,测试失败应该意味着模块未加载)(默认情况下无论如何都不会启用它,但只是为了彻底):

if sysctl -n net.bridge.bridge-nf-call-iptables 2>/dev/null; then
    sysctl -qw net.bridge.bridge-nf-call-iptables=0
    ip link set dev br0 type bridge nf_call_iptables 0
fi
Run Code Online (Sandbox Code Playgroud)

每个命名空间切换桥接切换足以激活该功能:必须禁用两者才能禁用它。

否则它仍然会影响iptables以及ip 系列中的nftables ( nftables没有工具可以正确处理这个问题)。如果 Docker 正在同一网络命名空间(主机)中运行,那么这样做也会中断 Docker,除非它实际上是在其他网络命名空间中运行的 Docker-in-Docker。

桥系列中直接等效的nftablesnft -f ...规则集是(使用 加载):

table bridge t {
    chain forward { type filter hook forward priority filter; policy accept;
        ct state established,related accept
        iif eth1 drop
    }
}

Run Code Online (Sandbox Code Playgroud)