# OpenVPN server on Ubuntu 18.06

## Setup server

### Leverage an AWS instance

Leverage an instance with:

* "Source/Destination Check" disabled.
* Firewall open on port 1194/UDP.

### Configure IP forward

Run:

```bash
nano /etc/sysctl.conf
```

Enable net.ipv4.ip\_forward:

```bash
net.ipv4.ip_forward=1
```

Apply changes:

```bash
sysctl -p
```

#### If you are using ufw\...

Get your default network card:

```bash
ip route | grep default
```

Output example:

```
default via 172.31.0.1 dev eth0 proto dhcp src 172.31.10.197 metric 100
```

Edit ufw config:

```bash
nano /etc/ufw/before.rules
```

Add the block `START OPENVPN RULES` and `END OPENVPN RULES`:

```bash
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#

# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to wlp11s0 (change to the interface you discovered!)
-A POSTROUTING -s 10.22.0.0/16 -o eth0 -j MASQUERADE
-A POSTROUTING -s 3.4.3.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES

# Don't delete these required lines, otherwise there will be errors
*filter

```

Edit ufw default config:

```bash
nano /etc/default/ufw
```

Allow forward:

```bash
 DEFAULT_FORWARD_POLICY="ACCEPT"
```

Allow openvpn and SSH:

```bash
ufw allow 1194/udp
ufw allow OpenSSH
```

### Install Openvpn

Run:

```bash
apt update
apt install openvpn
```

Download EasyRSA:

```bash
wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.4/EasyRSA-3.0.4.tgz
tar xvf EasyRSA-3.0.4.tgz
```

Copy and edit vars:

```bash
cd ~/EasyRSA-3.0.4/
cp vars.example vars
nano vars
```

Uncomment and change the following config:

```
set_var EASYRSA_REQ_COUNTRY     "AU"
set_var EASYRSA_REQ_PROVINCE    "New South Wales"
set_var EASYRSA_REQ_CITY        "Sydney"
set_var EASYRSA_REQ_ORG         "Your Company"
set_var EASYRSA_REQ_EMAIL       "hostmaster@yourcompany.com"
set_var EASYRSA_REQ_OU          "Your Company"
```

Initiate the public key:

```bash
./easyrsa init-pki
```

Build CA certificate. Keep the default Common Name and hit enter:

```bash
./easyrsa build-ca nopass
```

Create a private key for the server and a certificate request:

```bash
./easyrsa gen-req server nopass
```

Copy the server key to the /etc/openvpn/ directory:

```bash
cp ~/EasyRSA-3.0.4/pki/private/server.key /etc/openvpn/
```

Sign the request. Input yes when prompted:

```bash
./easyrsa sign-req server server
```

Sign the request. Input yes when prompted:

```bash
./easyrsa sign-req server server
```

Copy certificates to openvpn dir:

```bash
cp ./pki/issued/server.crt /etc/openvpn/
cp ./pki/ca.crt /etc/openvpn/
```

Create a strong Diffie-Hellman key to use during key exchange (may take a few minutes to complete):

```bash
./easyrsa gen-dh
```

Generate an HMAC signature to strengthen the server's TLS integrity verification capabilities:

```bash
openvpn --genkey --secret ta.key
```

Copy the files to openvpn dir:

```bash
sudo cp ~/EasyRSA-3.0.4/ta.key /etc/openvpn/
sudo cp ~/EasyRSA-3.0.4/pki/dh.pem /etc/openvpn/
```

### Configuring the OpenVPN Service

Copy sample config:

```bash
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
sudo gzip -d /etc/openvpn/server.conf.gz
```

Edit server config:

```bash
nano /etc/openvpn/server.conf
```

Double check tls-auth and add key-direction:

```bash
tls-auth ta.key 0
key-direction 0

```

Double check cipher and add auth:

```bash
cipher AES-256-CBC
auth SHA256
```

Change dh:

```bash
#dh dh2048.pem
dh dh.pem
```

Enable user and group:

```bash
user nobody
group nogroup
```

Enable client-to-client:

```bash
client-to-client
```

Start and enable service:

```bash
systemctl enable openvpn@server
systemctl restart openvpn@server
systemctl status openvpn@server
```

### Setup client config

Run:

```bash
mkdir -p ~/client-configs/keys
mkdir -p ~/client-configs/files
chmod -R 700 ~/client-configs
cp ~/EasyRSA-3.0.4/ta.key ~/client-configs/keys/
cp ~/EasyRSA-3.0.4/pki/ca.crt ~/client-configs/keys/
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf
nano ~/client-configs/base.conf
```

Config remote server:

```bash
#remote my-server-1 1194
remote YOUR-VPN-SERVER-DOMAIN 1194
```

Double check proto:

```bash
proto udp
```

Enable user and group:

```bash
user nobody
group nogroup
```

Comment out certificates (they are provided in the .ovpn file):

```bash
#ca ca.crt
#cert client.crt
#key client.key
```

Double check cipher and add auth:

```bash
cipher AES-256-CBC
auth SHA256
```

Add these lines in the end of the file. The last ones are commented out (only need to enable them for Linux clients that ship with an /etc/openvpn/update-resolv-conf file):

```bash
key-direction 1
# script-security 2
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
```

Create a script to compile the base config:

```bash
nano ~/client-configs/make_config.sh
```

Add:

```bash
#!/bin/bash

# First argument: Client identifier

KEY_DIR=~/client-configs/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf

cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-auth>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-auth>') \
    > ${OUTPUT_DIR}/${1}.ovpn

```

Set permissions:

```bash
chmod 700 ~/client-configs/make_config.sh
```

### Add client certificate

Generate certificate:

```bash
cd ~/EasyRSA-3.0.4
./easyrsa gen-req client2 nopass
./easyrsa sign-req client client2
cp pki/private/client2.key ~/client-configs/keys/
cp pki/issued/client2.crt ~/client-configs/keys/
cd ~/client-configs
./make_config.sh client2
ls files/client2.ovpn
```

### References

<https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-18-04>

<https://hackernoon.com/using-a-vpn-server-to-connect-to-your-aws-vpc-for-just-the-cost-of-an-ec2-nano-instance-3c81269c71c2>

## Revoke certificate

Run EasyRsa revoke command. Type yes when prompted:

```bash
cd /root/EasyRSA-3.0.4
./easyrsa revoke client2
```

Create a certificate revocation list (CRL):

```bash
./easyrsa gen-crl
```

Copy the CRL to the server config folder:

```bash
cp pki/crl.pem /etc/openvpn
```

Edit server config:

```bash
nano /etc/openvpn/server.conf
```

Add the following line to the end of the file:

```bash
crl-verify crl.pem
```

Restart server:

```bash
sudo systemctl restart openvpn@server
```

### References

<https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-18-04>

## Multi instances

Copy your current server config:

```bash
cd /etc/openvpn/
cp server.conf server2.conf
```

Edit the new file:

```bash
nano server2.conf
```

Change the following config:

```bash
port XXXX
server X.X.X.0 255.255.255.0
```

Start the server:

```bash
systemctl start openvpn@server2.service
systemctl enable openvpn@server2.service
```

### References

<https://www.hugeserver.com/kb/openvpn-multiple-ports/>

## Fixed IP for clients

Edit servers config:

```bash
nano /etc/openvpn/server.conf
```

Uncomment the following line:

```bash
client-config-dir ccd
```

Create the dir:

```bash
mkdir /etc/openvpn/ccd/
```

Create a file with **same CN name used in the certificate**:

```bash
nano /etc/openvpn/ccd/client-cn-name
```

Define the static IP:

```bash
ifconfig-push 10.8.0.2 255.255.0.0
```

Restart server:

```bash
systemctl restart openvpn@server
```

### References

<https://www.itsfullofstars.de/2018/09/openvpn-assign-static-ip-to-client/>

<https://serverfault.com/questions/826560/how-to-set-a-static-ip-client-side-in-openvpn>

## Restrict Client-to-client

Edit server config:

```bash
nano server-cluster.conf
```

Make sure the option **client-to-client** is **disabled**:

```bash
;client-to-client
```

Add the following line in the end of the file to route all traffic to the VPN server:

```bash
push "route 10.8.0.0 255.255.0.0"
```

Configure iptables:

```bash
# Allow all traffic from 10.22.0.100 (K8s master)
iptables -A FORWARD -s 10.22.0.100 -j ACCEPT

# Allow all traffic to 10.22.0.100 (K8s master)
iptables -A FORWARD -d 10.22.0.100 -j ACCEPT

# Allow all traffic between two nodes
iptables -A FORWARD -s 10.22.0.101 -d 10.22.0.102 -j ACCEPT
iptables -A FORWARD -s 10.22.0.102 -d 10.22.0.101 -j ACCEPT

# Drop everything else
iptables -A FORWARD -j DROP
```

### References

<https://backreference.org/2010/05/02/controlling-client-to-client-connections-in-openvpn/>

## Debug

Check service:

```bash
systemctl status openvpn@server.service
```

Monitor packets on interface tun0:

```bash
tcpdump -i tun0 -nn -s0 -v
tcpdump -i tun0 -nn -s0 -v port 6805
```

Monitor ping on interface vpn-cluster with buffer size 512 (it is not set, the “packets dropped by kernel” will always be zero):

```bash
tcpdump -i vpn-cluster -B 4096 -n icmp
```

Check open port:

```bash
netstat -a |grep 1194
```
