I’m gonna describe how to set up OpenVPN in high availability mode. The configuration will involve Linux bonding, tap interfaces, OpenVPN and iproute2 policy routing rules.
The idea is to set up 2 different tunnels between the 2 systems we want to interconnect. Each tunnel will use a different IP connection. The optimum configuration would involve 2 Internet connections, with different and independent providers (an ADSL and a cable one that don’t share any infraestructure should fit quite right). Linux bonding will provide with the high availability we need. It will also provide with load balancing, so that we make a better use of the bandwidth we are paying for. We’ll use some iproute2 rules so that each tunnel’s traffic gets routed via a different interface.
I’ll use as example a setup between a Gentoo system and a Debian one. It should work on any other GNU/Linux distro (adapting the relevant network config files, of course). The Debian system will perform the server role. The Gentoo box will be the client.
We start editing /etc/network/interfaces on the Debian system:
Debian server system - /etc/network/interfaces # Tap interfaces auto tap0 iface tap0 inet manual pre-up openvpn --mktun --dev tap0 post-down openvpn --rmtun --dev tap0 auto tap1 iface tap1 inet manual pre-up openvpn --mktun --dev tap1 post-down openvpn --rmtun --dev tap1 # Bonding interfaces auto bond0 iface bond0 inet static # Change the IP address range as needed! address 192.168.2.1 netmask 255.255.255.0 slaves tap0 tap1 # We use LACP mode. Ethernet frames will be sent to test # the end-to-end link up/down status. bond_mode 802.3ad bond_miimon 100 # We choose fast LACP rate. The down link events will be detected # within some seconds. bond_lacp_rate fast # layer3+4 policy will balance the load according to network (IP) # and transport (TCP and UDP) addresses and ports. It's what better # fits our scenario. bond_xmit_hash_policy layer3+4 # We add a route to reach the client internal network. Please adapt # the range as needed! post-up ip route add 192.168.0.0/16 via 192.168.2.11
The setup of the Gentoo system will be more complex. We’ll have to edit /etc/conf.d/net, /etc/modprobe.d/bond.conf and /etc/iproute2/rt_tables. We’ll also need some iptables rules to mark the packages so that policy routing works.
Gentoo client system - /etc/conf.d/net tuntap_tap0="tap" config_tap0=( "null" ) tuntap_tap1="tap" config_tap1=( "null" ) slaves_bond0="tap0 tap1" config_bond0=( "null" ) RC_NEED_bond0="net.tap0 net.tap1" # We configure the eth interfaces config_eth0=( "192.168.0.11/24 scope link" ) config_eth1=( "192.168.1.11/24 scope link" ) # We add routes for interface eth0 # We are populating the main and internet1 routing tables # Change IPV4 addresses as needed! routes_eth0=( "1.1.1.1 via 192.168.0.1 metric 1" "table internet1 192.168.0.0/24" "table internet1 default via 192.168.0.1" ) # We add routes for interface eth1 # We are populating the main and internet2 routing tables # Change IPV4 addresses as needed! routes_eth1=( "1.1.1.1 via 192.168.1.1 metric 1" "table internet2 192.168.1.0/24" "table internet2 default via 192.168.1.1" ) # We configure the bonding interface # Adapt the IP addresses as needed! config_bond0=( "192.168.2.11/24" ) routes_bond0=( "default via 192.168.2.1" ) # We set iproute2 rules so that each tunnel's traffic gets routed # via a different interface postup() { # eth0 is the interface associated with our 1st Internet # connection if [ ${IFACE} = eth0 ] ; then /sbin/ip rule add fwmark 1000 lookup internet1; # RPF and policy routing don't play together well # We disable RPF for eth0 echo 2 > /proc/sys/net/ipv4/conf/eth0/rp_filter; fi # eth1 is the interface associated with our 2nd Internet # connection if [ ${IFACE} = eth1 ] ; then /sbin/ip rule add fwmark 1001 lookup internet2; echo 2 > /proc/sys/net/ipv4/conf/eth1/rp_filter; fi } predown() { if [ ${IFACE} = eth0 ] ; then /sbin/ip rule del fwmark 1000 lookup internet1; fi if [ ${IFACE} = eth1 ] ; then /sbin/ip rule del fwmark 1001 lookup internet2; fi return 0 }
Gentoo client system - /etc/modprobe.d/bond.conf options bonding miimon=100 mode=802.3ad lacp_rate=fast\ xmit_hash_policy=layer3+4
Client system - /etc/iproute2/rt_tables (this settings are GNU/Linux generic, so I leave out "Gentoo" from the title) 200 internet1 201 internet2
Client system - iptables packet marking rules # This is the public IPV4 address of the Debian system # Just an example. Change for the address of your system! IPV4_IO_PUB=1.1.1.1 iptables -t mangle -A OUTPUT -d ${IPV4_IO_PUB} -p udp --dport 1194 \ -j MARK --set-mark 1000 iptables -t mangle -A OUTPUT -d ${IPV4_IO_PUB} -p udp --dport 1195 \ -j MARK --set-mark 1001
Now we are almost at the end of the configuration. Only the tunnels’ setup is left. Basicly we have to create 2 OpenVPN tunnels in tap mode (or, using the OpenVPN jargon, bridge mode). You may refer to the OpenVPN guide about bridges (but don’t stick to that, cause we won’t use exactly the same configuration).
We begin with the Debian system (the one that performs the server role). We create 2 OpenVPN profiles:
Server system - /etc/openvpn/io1.conf # Some of the settings here are my particular choices # You can tweak the configuration as you wish # # We use a "better" hash than the default auth SHA256 ca io1/keys/ca.crt cert io1/keys/io1.crt # We use a "better" block cipher than the default cipher AES-256-CBC comp-lzo comp-noadapt connect-freq 10 5 dev tap0 dh io1/keys/dh4096.pem # fast-io is supposed to improve performance. I've found no issue # with it at all. So I enable it. fast-io float group nogroup keepalive 5 60 key io1/keys/io1.key mode server mute 3 mssfix mtu-disc maybe passtos persist-key persist-tun # We listen on 1194 UDP port 1194 proto udp replay-persist io1/io1.replay # We set a larger replay window than the default. # This will help in WiFi-like scenarios. replay-window 256 30 status io1/io1.status 10 status-version 2 tls-server user nobody verb 4
Server system - /etc/openvpn/io2.conf # Some of the settings here are my particular choices # You can tweak the configuration as you wish # # We use a "better" hash than the default auth SHA256 ca io2/keys/ca.crt cert io2/keys/io2.crt # We use a "better" block cipher than the default cipher AES-256-CBC comp-lzo comp-noadapt connect-freq 10 5 dev tap1 dh io2/keys/dh4096.pem # fast-io is supposed to improve performance. I've found no issue # with it at all. So I enable it. fast-io float group nogroup keepalive 5 60 key io2/keys/io2.key mode server mute 3 mssfix mtu-disc maybe passtos persist-key persist-tun # We listen on 1195 UDP port 1195 proto udp replay-persist io2/io2.replay # We set a larger replay window than the default. # This will help in WiFi-like scenarios. replay-window 256 30 status io2/io2.status 10 status-version 2 tls-server user nobody verb 4
Now we have to configure the Gentoo system (client role).
Client system - /etc/openvpn/internet1.conf # Some of the settings here are my particular choices # You can tweak the configuration as you wish # # We use a "better" hash than the default auth SHA256 ca internet1/keys/ca.crt cert internet1/keys/internet1.crt # We use a "better" cipher than the default cipher AES-256-CBC client comp-lzo comp-noadapt dev tap0 # fast-io is supposed to improve performance. I've found no issue # with it at all. So I enable it. fast-io float group nobody key internet1/keys/internet1.key mssfix mtu-disc maybe mute 3 nobind ns-cert-type server passtos persist-key persist-tun proto udp # Change to the public IPV4 address of your server remote 1.1.1.1 1194 remote-random replay-persist internet1/internet1.replay # We set a larger replay window than the default. # This will help in WiFi-like scenarios. replay-window 256 30 resolv-retry infinite status internet1/internet1.status 10 status-version 2 user nobody verb 4
Client system - /etc/openvpn/internet2.conf # Some of the settings here are my particular choices # You can tweak the configuration as you wish # # We use a "better" hash than the default auth SHA256 ca internet2/keys/ca.crt cert internet2/keys/internet2.crt # We use a "better" cipher than the default cipher AES-256-CBC client comp-lzo comp-noadapt dev tap0 # fast-io is supposed to improve performance. I've found no issue # with it at all. So I enable it. fast-io float group nobody key internet2/keys/internet2.key mssfix mtu-disc maybe mute 3 nobind ns-cert-type server passtos persist-key persist-tun proto udp # Change to the public IPV4 address of your server remote 1.1.1.1 1195 remote-random replay-persist internet2/internet2.replay # We set a larger replay window than the default. # This will help in WiFi-like scenarios. replay-window 256 30 resolv-retry infinite status internet2/internet2.status 10 status-version 2 user nobody verb 4
Leave a Reply