We are located in a rural area with two slow ADSL connections (3.5/0.5 Mbps) and wanted to improve connection speed and reliability by somehow "combining" them. The following describes our solution which so far works very well.
This is therefore not a question we need resolved, but rather documentation of something that works because it was very difficult to find instructions and I hope this helps someone else in a similar situation. And maybe someone more advanced than me spots a bug that I'd be glad to come to know of and fix.
This documentation was compiled from the working system and had to be adjusted slightly to account for requirements specific to our location which are irrelevant for a more general description. So, while every effort has been made for reliable accuracy, I haven't redone the whole thing along this documentation, so there may be something missing or wrong. Post a comment if it doesn't work for you and I'll try to help.
The following two sources were very helpful in getting this to work, so hearty thanks to both authors!
Best Answer
This solution applies Linux Ethernet Bonding to two independent OpenVPN connections from a local gateway server to a server in the cloud that you have root access to, like a Linode or a DigitalOcean Droplet. The two Internet connections that the OpenVPN connections are based on use two ADSL routers in transparent bridge mode, i.e. we use their modem functionality only and create connections via PPP over Ethernet (PPPoE) driver. And the firewalls are implemented with FireHOL on both ends of the bonded connection.
The graph gives an overview. The LAN PCs are connected to eth0, 192.168.1.1/24, on the Gateway Server. The two routers are connected via individual, physical network interfaces eth1, 192.168.10.1/24, and eth2, 192.168.11.1/24. (Couldn't make PPPoE work with virtual interfaces on eth0.) The PPPoE driver creates interfaces ppp0 and ppp1 for individual connections to the ISP. OpenVPN binds to the Gateway Servers' 192.168.10.1/24 and 192.168.11.1/24 addresses on the LAN side, and to ports 1194 and 1195 of the Cloud Server's eth0 interface, 50.60.70.80/24. And these two OpenVPN connections are then bonded to create the virtual interfaces 10.80.0.2/30 on the LAN side and 10.80.0.1/30 on the Cloud Server side. Defining the Cloud Server's 10.80.0.1 address as default gateway on the LAN's Gateway Server allows all LAN computers to access the Internet at almost double the speed of one individual PPPoE connection.
The following configuration is based on Ubuntu Server (works here with 16.04 on the LAN side and 18.04 on the Cloud side). All commands assume root privileges.
Cloud Server Side
OpenVPN Tunnels
Install the latest OpenVPN version (replace
bionic
for 18.04 withxenial
for 16.04)In
/etc/default/openvpn
make sureis active. Disable the service, tunnels will be managed from
/etc/network/interfaces
:Create
/etc/openvpn/tap0.conf
and
/etc/openvpn/tap1.conf
like/etc/openvpn/tap0.conf
exceptLinux Ethernet Bonding
Using
ifupdown
for network management on the Cloud Server, modify your/etc/network/interfaces
(adjustgateway
for your environment):Options for the bonding device can be maintained in
/etc/modprobe.d/bonding.conf
:mode=0
means to use bonded lines in a round-robin fashion which should provide both, failover and speed enhancement.The following two scripts create/destroy the bonding device. Create
/usr/local/bin/vpn-start
(andchmod +x
):You may need to adjust the
mtu
to your environment. Create/usr/local/bin/vpn-stop
(andchmod +x
):Firewall
For your firewalling needs you can install FireHOL:
Leave
START_FIREHOL=NO
in/etc/default/firehol
and instead create/etc/systemd/system/firehol.service
and enable it
Create
/etc/firehol/firehol.conf
:Activate and Check
Restart the Cloud Server. Check the bonding device:
LAN Side
PPPoE Internet Connections
You would have to find out for your modems how to put them in transparent bridge mode and assign the LAN addresses. Using
ifupdown
for network management on the LAN Gateway Server, add the following to/etc/network/interfaces
:Install the PPPoE driver:
Create the two PPP configuration files,
/etc/ppp/peers/dsl1
:and
/etc/ppp/peers/dsl2
:replacedefaultroute
in/etc/ppp/peers/dsl1
makes this connection the default Internet connection before bonding.Provide the passwords in
/etc/ppp/chap-secrets
and/etc/ppp/pap-secrets
:Make sure both files are owned by
root
andchmod 600
.Add the following to the end of
/etc/network/interfaces
:This will automatically establish the PPPoE connections as defined in the configuration files their names given by the
provider
directives.The VPN tunnels and the bonding device are managed by two scripts that run when the two PPP connections have come up/gone down. Create
/etc/ppp/ip-up.d/bond0
(andchmod +x
):and
/etc/ppp/ip-down.d/bond0
(andchmod +x
):See below for the implementations of the
vpn-*
scripts.OpenVPN Tunnels
For the OpenVPN installation proceed like on the Cloud Server. OpenVPN will here be managed by scripts triggered when the PPPoE connections are established/destroyed.
Create
/etc/openvpn/tap0.conf
and
/etc/openvpn/tap1.conf
like/etc/openvpn/tap0.conf
exceptLinux Ethernet Bonding
/usr/local/bin/vpn-start
(chmod +x
) creates the VPN tunnels, sets up the bonding device and creates routing table entries that ensure traffic goes through the right channels as the bonding driver requests:The names for the routing tables need to be declared in
/etc/iproute2/rt_tables
:Make sure the numbers are unique within this configuration file.
The
mtu
needs to correspond to the one configured on the Cloud Server./usr/local/bin/gw
(chmod +x
) allows to switch default gateway:Create
/usr/local/bin/vpn-stop
(chmod +x
):The two
vpn-*
and thegw
scripts can of course be run manually also if need be.Firewall
Install FireHOL like on the Cloud Server with the following
/etc/firehol/firehol.conf
configuration:Activate and Check
Restart the LAN Server and check the bonding device:
Output should resemble Cloud Server.
If you now navigate e.g. to https://www.whatsmyip.org/ in your browser you should see your cloud server's IP address.
You can test your speed improvement e.g. by running
Here we see bonded speed only some 5% less than the sum of the individual lines' speeds.
Failover with Link Balancer
If one of the Internet connections goes down the bonding device doesn't continue on the remaining connection as one might expect. For this event one can prepare by setting up FireHOL's Link Balancer.
One way to do this is by creating a suitable
/etc/firehol/link-balancer.conf
and schedule/usr/sbin/link-balancer
as a cron job to periodically (e.g. every 2 minutes) check the connections and failover to what is still available if need be. The followinglink-balancer.conf
will make Internet access continue on the remaining good line if one goes bad:The default check for the bonded connection seems not to reliably detect its state, that's why the custom
check_bond0
.When the bad connection gets back up again, Link Balancer will make both connections default gateways that will be balanced on a connection basis. Couldn't with reasonable effort revive the bonded connection, so in these rare cases one will have to manually restart potentially both VPN ends.