Mildred's Website

IP Forwarding winth a Linux bridge

IP Forwarding winth a Linux bridge

Background

I maintain a mail server at home, and to get its public IP address, I have a VPN on it (so it is independent on how I connect to the Internet). Recently I decided to update my home network router so I could connect directly to the server (instead of going out to the internet and back in via the VPN). I just added a static route to the public IP to using the private IP as gateway.

The only problem is that on the mail server, in order to be flexible how it is connected to the network, the LAN IP address is configured on a bridge network device where the physical device is part of. There are a few VLAN tricks too.

An ascii-art diagram:

-----[ enp1s0 ]-----------------------------------------------
         |
         |                            [tun0] 193.33.56.74
     [ bridge ] 192.168.5.16

The problem

When an IP packet with the destination IP set to the public IP (193.33.56.74 in the diagram) arrives on the physical network, it never gets to the bridge device. When I tcpdump enp1s0, I see the packet, when I tcpdump bridge the packet does not appear.

This is because the bridge address only has the LAN IP address and not the public IP address. Even though I have IP forwarding in place, it does not work.

The solution

The trick is to add to sysctl.conf

# bridge forward
net.bridge.bridge-nf-call-arptables=0
net.bridge.bridge-nf-call-iptables=0

And this can only work if the correct kernel module is loaded at boot time:

# /etc/modules-load.d/bridge-forward.conf
br_netfilter

Details about bridge configuration

For reference, this is how I configure the bridge with systemd-networkd:

en.network:

[Match]
Name=en* !en*.610 !en*u*

[Network]
Bridge=bridge

[BridgeVLAN]
VLAN=1
PVID=1
EgressUntagged=1

[BridgeVLAN]
VLAN=610

bridge.netdev:

[NetDev]
Name=bridge
Kind=bridge

[Bridge]
DefaultPVID=1
VLANFiltering=yes

bridge.network:

[Match]
Name=bridge

[Network]
VLAN=lan
VLAN=vlan610

[BridgeVLAN]
VLAN=1

[BridgeVLAN]
VLAN=610

lan.netdev:

[NetDev]
Name=lan
Kind=vlan

[VLAN]
Id=1

lan.network:

[Match]
Name=lan

[Network]
#DHCP=ipv4
Address=192.168.5.16/24
Gateway=192.168.5.1
DNS=X.X.X.X
DNS=X.X.X.X

(vlan610.netdev and vlan610.network not shown)