It appears that, probably because of an iptables rule from Docker, you had the module br_netfilter
loaded and active (ie: sysctl net.bridge.bridge-nf-call-iptables
returns 1). This makes bridged frames (Ethernet, layer 2) subject to iptables filtering (IP, layer 3):
What's bridge-netfilter?
Since Linux kernel 3.18-rc1, you have to modprobe br_netfilter to
enable bridge-netfilter.
The bridge-netfilter code enables the following functionality:
{Ip,Ip6,Arp}tables can filter bridged IPv4/IPv6/ARP packets, even when encapsulated in an 802.1Q VLAN or PPPoE header. This enables the
functionality of a stateful transparent firewall.
All filtering, logging and NAT features of the 3 tools can therefore be used on bridged frames.
Combined with ebtables, the bridge-nf code therefore makes Linux a very powerful transparent firewall.
This enables, f.e., the creation of a transparent masquerading machine (i.e. all local hosts think they are directly connected to the
Internet).
Letting {ip,ip6,arp}tables see bridged traffic can be disabled or enabled using the appropriate proc entries, located in
/proc/sys/net/bridge/
:
bridge-nf-call-arptables
bridge-nf-call-iptables
bridge-nf-call-ip6tables
For example this module gets automatically loaded whenever an iptables with the physdev
match is in use, even in an other network namespace.
There is documentation explaining side effects caused by this module. Those side effects are intended when using it for bridge transparent firewalling. Also, the iptables physdev
match cannot work properly without it (it simply won't match anymore). It's also explained how to prevent its effects, especially in chapter 7:
Because of the br-nf code, there are 2 ways a frame/packet can pass
through the 3 given iptables chains. The first way is when the frame
is bridged, so the iptables chains are called by the bridge code. The
second way is when the packet is routed.
Rather than disabling on iptables this module like this:
sysctl -w net.bridge.bridge-nf-call-iptables=1
one should adapt its iptables rules as explained in chapter 7 to avoid side effets. Else other unknown parts of the system will be disrupted.
Until recently in kernel 5.3 this module was not namespace aware and having it loaded suddenly enabled it on all network namespaces causing all kind of troubles when unexpected. It's also since this then that it's also possible to enable it per bridge (ip link set dev BRIDGE type bridge nf_call_iptables 1
) rather than per namespace.
Once tools (Docker...) and kernel (>= 5.3) follow evolution, simply having it enabled in select network namespaces and bridges should suffice, but today probably not. Also note that kernel 5.3 also inherited native bridge stateful firewalling, usable by nftables, probably turning this module soon obsolete (once direct encapsulation/decapsulation support in bridge for VLAN and PPPoE are available):
Netfilter
Add native connection tracking support for the bridge. Before this
patchset, only chance for people to do stateful filtering is to use
the br_netfilter emulation layer, this is a step forward to deprecate
it
Best Answer
Netfilter can do that, e.g