I am currently living in a country that blocks many websites and has unreliable network connections to the outside world. I have two OpenVPN endpoints (say: vpn1 and vpn2) on Linux servers that I use to circumvent the firewall. I have full access to these servers. This works quite well, except for the high package loss on my VPN connections. This packet loss varies between 1% and 30% depending on time and seems to have a low correlation, most of the time it seems random.
I am thinking about setting up a home router (also on Linux) that maintains OpenVPN connections to both endpoints and sends all packets twice, to both endpoints. vpn2 would send all packets from home to vpn1. Return trafic would be send both directly from vpn1 to home, and also through vpn2.
+------------+
| home |
+------------+
| |
| OpenVPN |
| links |
| |
~~~~~~~~~~~~~~~~~~ unreliable connection
| |
+----------+ +----------+
| vpn1 |---| vpn2 |
+----------+ +----------+
|
+------------+
| HTTP proxy |
+------------+
|
(internet)
For clarity: all packets between home and the HTTP proxy will be duplicated and sent over different paths, to increase the chances one of them will arrive. If both arrive, the first second one can be silently discarded.
Bandwidth usage is not an issue, both on the home side and endpoint side. vpn1 and vpn2 are close to each other (3ms ping) and have a reliable connection.
Any pointers on how this could be achieved using the advanced routing policies available in Linux?
Use the bonding infrastructure at the 'home' and 'vpn1' side, and specifcally with the mode=3 setting which broadcasts traffic on all interfaces which belong to a bond.
For more information on how to configure bonding, see the excellent manual at http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.37.y.git;a=blob;f=Documentation/networking/bonding.txt;h=5dc638791d975116bf1a1e590fdfc44a6ae5c33c;hb=HEAD
I used the answer provided by @user48116 and it works like a charm. The setup is actually quite easy!
NOTE: I implemented this with two connections to just one single server, as this already solved the problem for me. If you want to try a setup with two servers, the easiest way is probably to use port forwarding to forward the UDP port from the second server to the first, and use the same recipe as described here. I have not tested this myself though.
First, make sure you have a 2.6 kernel with bonding support (default in all modern distributions) and you have ifenslave installed.
Next, put this into your /etc/rc.local or any other place you prefer, but make sure it's run before openvpn is started (because it will try to bind to bond0):
Client:
You could add some routing if needed here, make sure you do all the proper routing from the other side too though.
Server:
Create a /etc/openvpn/tap-up.sh script (and don't forget to mark it executable with chmod a+x tap-up.sh):
Next, add a bridge0a.conf and bridge0b.conf to /etc/openvpn/ together with a shared key. The files are the same for a and b, except for a different port (for example, use 3002 for b). Replace 11.22.33.44 by your server's public IP.
Client:
Server:
Don't forget to edit /etc/defaults/openvpn to make sure your new VPN configurations are started. Reboot you machines, or load rc.local and restart openvpn manually.
Now you're ready to test your setup:
If everything goes well and the line is good, you will see four replies for every ICMP package: your packages are duplicated on the local side, and the replies to these two packages are duplicated again on the remote side. This will not be an issue for TCP connections, because TCP will simply ignore all duplicates.
This is an issue for UDP packets, as it's up to the software to handle duplicates. For example, a DNS query will yield four replies instead of the expected two (and use four times the normal bandwidth for the response instead of two times):
Good luck!