Skip to content

Latest commit

 

History

History
290 lines (208 loc) · 9.61 KB

MULTI_NODE.md

File metadata and controls

290 lines (208 loc) · 9.61 KB
title description category
Multi Node
Set up a controller with two nodes
howto

WORK IN PROGRESS (2020-04-06)

When you want to scale up your deployment, i.e. have multiple nodes connect with one controller, this document is for you!

This document will show how to set up multiple nodes. The OpenVPN clients will be distributed over the nodes using DNS round-robin.

If you already installed the software on one machine already, and want to convert your current installation into a controller you can use the convert_to_controller.sh script.

Requirements

At least 3 machines (or VMs) running CentOS 7. The two machines that will be the nodes ideally have the same specifications. They also SHOULD have CPU AES acceleration, e.g. AES-NI.

All three need to be set up with static IP configurations and working DNS. Make sure all works properly before starting the setup. For example, my test deployment uses:

Role DNS Host IPv4 IPv6
Controller frkovpn.tuxed.net 145.0.6.71 2001:610:188:418:145:0:6:71
Node A node-a.frkovpn.tuxed.net 145.0.6.72 2001:610:188:418:145:0:6:72
Node B node-b.frkovpn.tuxed.net 145.0.6.73 2001:610:188:418:145:0:6:73

We will use NAT for IPv4 and IPv6 client traffic.

Perform these steps on the hosts:

$ curl -L -O https://github.com/eduvpn/documentation/archive/v2.tar.gz
$ tar -xzf v2.tar.gz
$ cd documentation-2

TIP: whenever you modify a .php file, make sure the syntax is correct after editing:

$ php -l /path/to/file.php

This will tell you whether or not the syntax is correct!

Controller

On the controller host:

$ sudo -s
# ./deploy_centos_controller.sh

Make note of the credentials that are printed at the end, you can use them to test your server!

After the controller is installed, make sure you'll get a valid TLS certificate, for example using the included lets_encrypt_centos.sh script:

# ./lets_encrypt_centos.sh

Now visit your site at https://frkovpn.tuxed.net/. Make sure there is no TLS error and you can login with the credentials you noted before.

By default there is an internet profile. We will duplicate this and rename it. For this, edit /etc/vpn-server-api/config.php. You will find something like this:

<?php return array (
  'vpnProfiles' =>
  array (
    'internet' =>
    array (
        // ...
    ),
  ),
);

Now copy the internet section below it and rename internet to node-a and the duplicate to node-b. Also add the useVpnDaemon option:

<?php return array (
  'useVpnDaemon' => true,
  'vpnProfiles' =>
  array (
    'node-a' =>
    array (
        // ...
    ),
    'node-b' =>
    array (
        // ...
    ),
  ),
);

Modify the configuration keys in the respective sections:

Node Option Value
a managementIp 145.0.6.72
a profileNumber 1
a hostName node-a.frkovpn.tuxed.net
a displayName Node A
a range 10.1.0.0/25
a range6 fd00:1:1:1::/64
b managementIp 145.0.6.73
b profileNumber 2
b hostName node-b.frkovpn.tuxed.net
b displayName Node B
b range 10.2.0.0/25
b range6 fd00:2:2:2::/64

You can of course choose your own range and range6, but make sure they are not the same for both profiles.

Next, modify the RequireAny section in /etc/httpd/conf.d/vpn-server-api.conf by adding the IP addresses of the nodes:

<RequireAny>
    Require local
    Require ip 145.0.6.72
    Require ip 2001:610:188:418:145:0:6:72
    Require ip 145.0.6.73
    Require ip 2001:610:188:418:145:0:6:73
</RequireAny>

Restart Apache:

$ sudo systemctl restart httpd

Finally, we need to create a CA to secure the connection between the controller and nodes. You can do this on the controller, or on your own system. We use vpn-ca for this. You can easily install it on the controller:

$ sudo yum -y install vpn-ca
$ mkdir -p ${HOME}/ca
$ cd ${HOME}/ca
$ vpn-ca -init
$ vpn-ca -client vpn-daemon-client -not-after CA
$ vpn-ca -server vpn-daemon-node-a -not-after CA
$ vpn-ca -server vpn-daemon-node-b -not-after CA
$ chmod 0640 *.crt *.key

Now install the vpn-daemon-client certificate:

$ sudo mkdir -p /etc/vpn-server-api/vpn-daemon
$ sudo chmod 0710 /etc/vpn-server-api/vpn-daemon
$ sudo cp ca.crt vpn-daemon-client.crt vpn-daemon-client.key /etc/vpn-server-api/vpn-daemon
$ sudo chgrp -R apache /etc/vpn-server-api/vpn-daemon

Copy the ca.crt, vpn-daemon-node-a.* to Node A and ca.crt, vpn-daemon-node-b.* to Node B for later use.

Before moving on to the nodes, make not of the vpn-server-node secret under the apiConsumers section in /etc/vpn-server-api/config.php. You'll need it next!

Nodes

The instructions below will be only shown for Node A, but they are identical for Node B... so you have to perform them twice, please note that on Node B you should replace any occurrence of node-a with node-b. Ideally you perform these steps in parallel on both machines.

Make sure you can reach the API endpoint:

$ curl https://frkovpn.tuxed.net/vpn-server-api/api.php
{"error":"missing authentication information"}

This error is expected as no secret was provided. This just makes sure the controller is configured correctly and allows requests from the nodes.

Next, it is time to install the software. You should have downloaded and unpacked the archive already, see Requirements.

$ cd documentation-2
$ sudo -s
# ./deploy_centos_node.sh

The script will ask for the API URL and the secret. The API URL is the URL we tested above. The secret is the one extracted at the end of the previous section.

The script will output some errors about being unable to start OpenVPN. This is because we changed the controller's default configuration. It is fine, we will fix that shortly!

First we install the vpn-daemon:

$ sudo yum -y install vpn-daemon

Modify /etc/sysconfig/vpn-daemon:

ENABLE_TLS=-enable-tls
LISTEN=:41194

Now copy the certificates/keys you copied to the node already before to the right place:

$ sudo cp ca.crt                /etc/pki/vpn-daemon/
$ sudo cp vpn-daemon-node-a.crt /etc/pki/vpn-daemon/server.crt
$ sudo cp vpn-daemon-node-a.key /etc/pki/vpn-daemon/private/server.key
$ sudo chgrp -R vpn-daemon      /etc/pki/vpn-daemon

Start/enable the daemon:

$ sudo systemctl enable --now vpn-daemon

Next we have to update the node configuration. Edit /etc/vpn-server-node/config.php and add the following configuration options:

'useVpnDaemon' => true,
'profileList' => ['node-a'],

The firewall also requires tweaking, open it to allow traffic from the controller to the node's VPN daemon:

In /etc/sysconfig/iptables:

-A INPUT -s 145.0.6.71/32 -p tcp -m state --state NEW -m tcp --dport 41194 -j ACCEPT

In /etc/sysconfig/ip6tables, if you prefer using IPv6:

-A INPUT -s 2001:610:188:418:145:0:6:71/128 -p tcp -m state --state NEW -m tcp --dport 41194 -j ACCEPT

Now you are ready to apply the changes and it should work without error:

$ sudo vpn-maint-apply-changes

Restart the firewall:

$ sudo systemctl restart iptables
$ sudo systemctl restart ip6tables

Make sure you repeat these steps on Node B as well!

Now is the time to test everything. Go to the portal at https://frkovpn.tuxed.net/, download a configuration, test it with your client. Download a configuration for both profiles and make sure they work. Login to the admin portal using the admin user and password you noted at the end of the controller install and make sure you see your client(s) under "Connections" in the portal when connected to either "Node A" or "Node B" profile with your VPN client.

Load Balancing

Now that everything works, we can merge the profiles to setup a round-robin DNS based load balancing over the nodes.

On the controller you need to modify /etc/vpn-server-api/config.php again.

For the node-b profile set hideProfile to true. The hostName key in both profiles gets the value nodes.frkovpn.tuxed.net. Update the displayName of node-a to something generic, e.g. Secure Internet.

As, by default, each profile uses its own "TLS Crypt" key, we need to make sure both of them use to same key now that the profiles are "merged":

$ sudo cp /var/lib/vpn-server-api/tls-crypt-node-a.key /var/lib/vpn-server-api/ta.key

The ta.key is the fallback "TLS Crypt" key. If that file exists, the profile specific keys are ignored.

On the nodes, apply the changes again:

$ sudo vpn-maint-apply-changes

As for DNS, you can use the following configuration:

nodes.frkovpn   IN  A       145.0.6.72
                IN  A       145.0.6.73
                IN  AAAA    2001:610:188:418:145:0:6:72
                IN  AAAA    2001:610:188:418:145:0:6:73

From now on, the load should be distributed over the VPN nodes once you download a new configuration. You can monitor this through the portal on the "Connections" page. By connecting multiple devices you should see them connect to the different nodes instead of all to one node.

Maintenance

The vpn-maint-scripts package has instructions for maintaining a multi node setup. Please refer to those instructions here.