Creating a Bridge Interface
A quick and dirty guide to setting up a bridge interface with a reliable device name.
Find MAC address
Find the MAC address of the NICs you'd like to bridge using ifconfig:
ifconfig -a
Example output is shown below. Make a note of the HWaddr of the interfaces you want to bridge. We'll need these MAC addresses in the next step.
┌(foo@server)─(10:30 PM Tue Jun 24)─(~) └> ifconfig -a enp5s0 Link encap:Ethernet HWaddr 00:1C:C0:AE:B5:E7 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0(0 MiB) TX bytes:0 (0 MiB) enp6s0 Link encap:Ethernet HWaddr 00:1C:C0:AE:B5:E8 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0(0 MiB) TX bytes:0 (0 MiB) enp7s0 Link encap:Ethernet HWaddr 00:1C:C0:AE:B5:E9 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0(0 MiB) TX bytes:0 (0 MiB) enp8s0 Link encap:Ethernet HWaddr 00:1C:C0:AE:B5:EA RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0(0 MiB) TX bytes:0 (0 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:480 (480.0 b) TX bytes:480 (480.0 b) wan Link encap:Ethernet HWaddr 00:1C:C0:AE:B5:E6 inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:41620 errors:0 dropped:0 overruns:0 frame:0 TX packets:40231 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:21601203 (20.6 MiB) TX bytes:6145876 (5.8 MiB)
Set udev rules
We're going to set a udev rule that renames the interfaces upon boot and starts any services that may depend on them. The following rule will look for the MAC addresses we noted in the previous step (make sure the letters are in lowercase in this file). If found, it will rename the interfaces from the kernel generated ones to the names of our choosing. Here we're renaming enp*s0
to lan*
. This will help give us reliable names to use when referring to the devices. Avoid using names the kernel may use by default such as eth0
.
vi /etc/udev/rules.d/30-br0.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e7", NAME="lan0" SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e8", NAME="lan1" SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e9", NAME="lan2" SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:ea", NAME="lan3" ENV{SYSTEMD_WANTS}="network@br0.service"
Create systemd service
You may have noticed the reference to network@br0.service
in the previous step. This lets udev know to start a systemd service named network@br0.service after the interfaces have been renamed to lan0
, et al. Systemd can be a true pain in the butt when trying to set services to only come online after a network interface is up, so let's create a framework where services can be specified in the interface's startup service. We can do this using an old school init.d style script. Because this is launched via udev, we don't need to bother with systemd's [Install] section or actually enabling this service.
vi /etc/systemd/system/network\@br0.service
[Unit] Description=Network Connectivity (br0) [Service] Type=oneshot RemainAfterExit=yes ExecStart=/etc/network/br0.sh start ExecStop=/etc/network/br0.sh stop
Create the network init script
Remember to set the script to executable only by root after it's creation by issuing:
touch /etc/network/br0.sh chown root:root /etc/network/br0.sh chmod 700 /etc/network/br0.sh
vi /etc/network/br0.sh
#!/bin/bash # # Wait for lan port renames and bring the bridge up. start() { if [ -n "`ip link | grep br0`" ]; then echo -n "Attempting to bring up br0 : Interface br0 is already up!" return else while [ -z "`ip link | grep br0`" ] do echo -n "Attempting to bring up br0 : " # Test to see if the LAN ports have been assigned yet. lan_status=`ip link` lan_up=`echo $lan_status | grep lan0 | grep lan1 | grep lan2 | grep lan3` if [ "$lan_up" ]; then ip link add name br0 type bridge # Make sure to give the interface a unique MAC ip link set dev br0 address 00:1c:c0:ae:b5:eb ip link set br0 up ip link set dev lan0 up ip link set dev lan1 up ip link set dev lan2 up ip link set dev lan3 up ip link set lan0 master br0 ip link set lan1 master br0 ip link set lan2 master br0 ip link set lan3 master br0 # Add a separate subnet for the device to route on. ip addr add dev br0 192.168.2.1/24 broadcast 192.168.2.255 # Enhance the send/receive windows on this route ip route change 192.168.2.0/24 dev br0 proto kernel scope link src 192.168.2.1 initcwnd 65 initrwnd 65 # Start any services that depend on this NIC HERE #systemctl start sshd else echo "LAN ports unavailable, waiting 0.1s." sleep 0.1 fi done fi echo -n "Done." return } stop() { echo -n "Bringing down interface br0 : " # Stop any services that depend on this NIC HERE #systemctl stop sshd ip route del 192.168.2.0/24 dev br0 proto kernel scope link src 192.168.2.1 ip link set lan3 nomaster ip link set lan2 nomaster ip link set lan1 nomaster ip link set lan0 nomaster ip link set dev br0 down ip link set dev lan3 down ip link set dev lan2 down ip link set dev lan1 down ip link set dev lan0 down ip address flush dev lan3 ip address flush dev lan2 ip address flush dev lan1 ip address flush dev lan0 ip address flush dev br0 ip link delete br0 type bridge >/dev/null 2>&1 echo -n "Done." return } status() { if [ "`which ifconfig`" ]; then ifconfig br0 echo fi ip link show br0 } restart() { stop echo start } case "$1" in start) start ;; stop) stop ;; status) status ;; restart) restart ;; *) echo -n " Usage: ./br0.sh (start | stop | status | restart)" ;; esac
Reboot
Reboot your machine to verify the changes have been applied correctly. Make sure the NICs have been renamed and that they have been assigned to the bridge. Verify that any services that depend on the bridge interface have started correctly.