Building a Multisourced Infrastructure Using OpenVPN
You need two machines to run the OpenVPN dæmon in server mode (we refer to them as vpnsrvA and vpnsrvB, and let's assume their physical IP addresses in your network are 192.168.7.1 and 192.168.17.1, respectively) and two new private subnets: data (for example, 10.100.100.0/24) and management (10.200.200.0/24). All of your applications and services will run in the data subnet, and vpnsrvA and vpnsrvB will exchange runtime status and routing information in the management subnet. Think of these two machines as virtual network switches for your virtual LAN. Also, note that these subnets do not have to be class C; you can choose a bigger data network, especially if you are planning to connect a large number of hosts.
Listing 1a. OpenVPN Server Configuration for vpnsrvA
server 10.100.100.0 255.255.255.0 ifconfig 10.100.100.1 10.100.100.2 push "route 10.100.100.0 255.255.255.0" push "route 10.200.200.0 255.255.255.0" dev tun proto udp user nobody persist-key persist-tun dh keys/dh1024.pem ca keys/ca.crt cert keys/vpnsrvA-1.crt key keys/vpnsrvA-1.key comp-lzo verb 3 keepalive 10 60 client-config-dir ccd management tunnel 5656 /etc/openvpn/pass
Listing 1b. OpenVPN Server Configuration for vpnsrvB
mode server tls-server ifconfig 10.100.100.10110.100.100.102 ifconfig-pool 10.100.100.410.100.100.251 route 10.100.100.025220.127.116.11 push "route 10.100.100.02518.104.22.168" push "route 10.200.200.02522.214.171.124" dev tun proto udp user nobody persist-key persist-tun dh keys/dh1024.pem ca keys/ca.crt cert keys/vpnsrvB- 1.crt key keys/vpnsrvB-1.key comp-lzo verb 3 keepalive 10 60 client-config-dir ccd management tunnel 5656 /etc/openvpn/pass
Configure vpnsrvA and vpnsrvB as OpenVPN servers for the data subnet (Listings 1a and 1b). You may add more configuration options as needed. Note that the “server” line in the configuration file is a shortcut and cannot be used for both vpnsrvA and vpnsrvB. It actually expands to a set of commands that would have assigned 10.100.100.1 to both servers (see the OpenVPN man page for more details). We want an active-active configuration; therefore, we need vpnsrvA and vpnsrvB to be in the same subnet but to have different IP addresses. To accomplish this, we explicitly expand the server definition for vpnsrvB and assign it the 10.100.100.101 IP address.
Another important note is that the client configuration directory (usually called ccd) and keys directory (called keys) need to be identical on both vpnsrvA and vpnsrvB. One of the easiest ways to accomplish this is to use rsync. rsync allows us to keep it simple and avoid extra variables in the mix. Plus, we always can switch the direction of rsync and promote either of the servers to be the master. For now, let's assume that vpnsrvA is the master and that vpnsrvB mirrors the ccd and keys directories from vpnsrvA using rsync. You will create keys (preferably using the easy-rsa package that ships with OpenVPN) and update the ccd entries on the master server.
Listing 2. OpenVPN Client Configuration
# Note: "remote" must point to servers' physical # (not virtual) IP addresses client remote 192.168.7.1 remote 192.168.17.1 dev tun proto udp user nobody persist-key persist-tun keepalive 10 60 comp-lzo ca keys/ca.crt cert keys/client-1.crt key keys/client-1.key ns-cert-type server
At this point, you can configure several hosts on your network as OpenVPN clients (Listing 2). Each host will have its own certificate/key pair, and the ifconfig-push directive in the ccd entry for this host will set its IP address (see Resources for a link to the OpenVPN HOWTO for a detailed explanation of how to set it up). We tie the virtual IP address to a host based on its certificate/key pair, in much the same way as in a DHCP configuration you would tie an IP address to a host based on its Ethernet MAC address. Therefore, each client must have its own unique certificate/key pair.
Note that we use OpenVPN's built-in capability to round-robin between multiple servers and reconnect after connectivity failures, which is controlled by the keepalive option. Once this is done, you should be able to start the OpenVPN clients, and they should at least be able to communicate with their current OpenVPN server and refer to it by IP—10.100.100.1 or 10.100.100.101. If your client connects to vpnsrvA and you bring down the openvpn dæmon on vpnsrvA, the client will detect it and automatically reconnect to vpnsrvB.
A quick note about firewalls—in a virtual LAN, your main data interface will be called tun0. Therefore, all the rules you used to define for interface eth0 in a single-sourced configuration will need to be redefined for tun0. The Ethernet interface, however, will require additional rules to allow UDP on port 1194 (OpenVPN) from the client machines to both vpnsrvA and vpnsrvB.
The setup that we already have accomplished is somewhat fault-tolerant. If vpnsrvA becomes unavailable, all clients will reconnect to vpnsrvB, and connectivity will be restored. In other words, this is active-passive redundancy. But, what will happen if both vpnsrvA and vpnsrvB are up? Let's assume that host1 and host2 run the openvpn dæmon in client mode. host1 connected to vpnsrvA and was assigned 10.100.100.25; host2 connected to vpnsrvB and was assigned 10.100.100.41. The routing table on vpnsrvA is shown in Listing 3. In this scenario, when host1 attempts to ping 10.100.100.101, its outgoing packets will be routed first to vpnsrvA but then will go back to the same tun0 interface, because vpnsrvA does not know about the existence of vpnsrvB. Similarly, when host1 attempts to ping host2, vpnsrvA also will send these packets back, as indicated by the 10.100.100.0/24 route. As a result, both operations will fail.