FreeBSD comes with the if_bridge(4) driver which interconnects network cards in order to form an Ethernet switch (or historically a multiport bridge, hence the name). if_bridge even supports the Rapid Spanning Tree Protocol (RSTP) which avoids network loops. Thus, you could connect two (or more) ports of a FreeBSD box running if_bridge to another FreeBSD box running if_bridge, too, and won't experience a network storm. That way both boxes (or software switches, if you like) had a redundant connection to each other and could tolerate the loss of one interconnection. But what if one connection should use the Internet? Here comes tinc into play. Tinc is an SSL VPN software which can also transport layer 2 ethernet frames when configured on a tap device. That tap device will then be connected to the bridge. Here's a complete picture:
FreeBSD box 1 FreeBSD box 2 /------------------------------\ /------------------------------\ | | | | lan 1 | | direct ethernet connection | | lan 2 -----------|----(em2) (em0)-----|------------------------------------|-----(em0) (em2)----|----------- | \---(bridge0)---/ | | \---(bridge0)---/ | | | | | | | | (tap0) | | (tap0) | | | | | | | | (tinc daemon) | | (tinc daemon) | | | | (oooooooooo) | | | | \------(em1)-----|-----------(--Internet--)-----------|-----(em1)----/ | | (public ip 1) | (oooooooooo) | (public ip 2) | | | | | \------------------------------/ \------------------------------/
Instead of em(4) based ethernet cards you can use any supported nic, of course. em1 on box 1 can even be some kind of ppp uplink with a dynamic ip address. Since tap devices present themselves as 10 MBits/sec interfaces, their RSTP costs are 2000000. 100 MBit nics or 1GE cards have lower costs of 200000 and 20000, respectively. Thus, RSTP will prefer the direct connection, and only if that one is down, it'll use the Internet connection (unless that one is down, too). Here are the steps which are needed to build such a scenario on FreeBSD 10.3 as depicted above:
# pkg install tinc
# mkdir -p /usr/local/etc/tinc/lebridge/hosts
# tincd -n lebridge -K
Name = box2 Device = /dev/tap0 MaxTimeout = 120 Mode = hub ProcessPriority = high
Name = box1 Device = /dev/tap0 MaxTimeout = 120 Mode = hub ProcessPriority = high ConnectTo = box2
Address = public ip 2 Compression = 10
# cat /usr/local/etc/tinc/lebridge/rsa_key.pub >> /usr/local/etc/tinc/lebridge/hosts/box2
Compression = 10
# cat /usr/local/etc/tinc/lebridge/rsa_key.pub >> /usr/local/etc/tinc/lebridge/hosts/box1
# scp box2:/usr/local/etc/tinc/lebridge/hosts/box2 /usr/local/etc/tinc/lebridge/hosts/ # scp /usr/local/etc/tinc/lebridge/hosts/box1 box2:/usr/local/etc/tinc/lebridge/hosts/
#!/bin/sh ifconfig "$INTERFACE" up ifconfig bridge0 addm "$INTERFACE" stp "$INTERFACE"
#!/bin/sh ifconfig "$INTERFACE" destroy
# chmod 0755 /usr/local/etc/tinc/lebridge/tinc-up /usr/local/etc/tinc/lebridge/tinc-down
cloned_interfaces="bridge0" ifconfig_bridge0="maxaddr 16384 timeout 30 addm em0 stp em0 addm em2 edge em2 up" ifconfig_em0="up" ifconfig_em2="up" ifconfig_em1="inet $PUBLIC_IP_2 netmask x.x.x.x" defaultrouter="$GATEWAY_OF_PUBLIC_IP_2" tincd_enable="YES" tincd_cfg="lebridge" tincd_flags="-d 2 -L"
cloned_interfaces="bridge0" ifconfig_bridge0="maxaddr 16384 timeout 30 addm em0 stp em0 addm em2 edge em2 up" ifconfig_em0="up" ifconfig_em2="up" ifconfig_em1="inet $PUBLIC_IP_1 netmask x.x.x.x" defaultrouter="$GATEWAY_OF_PUBLIC_IP_1" tincd_enable="YES" tincd_cfg="lebridge" tincd_flags="-d 2 -L"
net.link.bridge.log_stp=1
ifconfig_bridge0="inet 10.23.42.2 netmask 255.255.255.0 maxaddr 16384 timeout 30 addm em0 stp em0 addm em2 edge em2 up"And /etc/rc.conf on box 1:
ifconfig_bridge0="inet 10.23.42.1 netmask 255.255.255.0 maxaddr 16384 timeout 30 addm em0 stp em0 addm em2 edge em2 up"
# ifconfig bridge0 addr
Please note that you should apply appropriate firewall filters on interface em1 on both boxes.