How to Setup an OpenVPN Server on Azure

How to Setup an OpenVPN Server on Azure

In this article, I will provide detailed steps to setup an OpenVPN server in Azure.

Prerequisites

  • Ubuntu 16.04 VM deployed in Azure at least with one NIC which has public IP address enabled.
  • User with sudo privilege on Ubuntu 16.04 VM.
  • VM private IP address doesn't overlap with subnet 172.16.0.0/24

Step 1: Install OpenVPN & Easy-RSA

sudo apt-get update
apt-get install openvpn easy-rsa

Step 2: Setup CA

Create CA directory

make-cadir ~/openvpn-ca

Open vars file to configure the settings

cd ~/openvpn-ca
vi vars

Find and modify below settings

export KEY_COUNTRY="YOUR_COUNTRY"
export KEY_PROVINCE="YOUR_PROVINCE"
export KEY_CITY="YOUR_CITY"
export KEY_ORG="YOUR_ORG"
export KEY_EMAIL="YOUR_EMAIL@YOUR_DOMAIN.SUFFIX"
export KEY_OU="YOUR_OU"

export KEY_NAME="YOUR_KEY_NAME"

After saving modified vars file, setup CA by typing below commands

cd ~/openvpn-ca
source vars
# 
./clean-all
./build-ca

Step 3: Create Server Certificates

./build-key-server ovpn
KEY_SIZE=4096 ./build-dh
openvpn --genkey --secret keys/ta.key

Step 4: Configure OpenVPN Service

Copy certificates to /etc/openvpn

cd ~/openvpn-ca/keys
sudo cp ca.crt ovpn.crt ovpn.key ta.key dh4096.pem /etc/openvpn
sudo adduser --system --shell /usr/sbin/nologin --no-create-home openvpn

Create server side configuration file

sudo vi /etc/openvpn/server.conf

Add following content to server.conf

# OpenVPN listening address
local 10.0.1.6
# OpenVPN listening port
port 32768 
# tcp/udp
proto udp
dev tun
ca ca.crt
cert ovpn.crt
key ovpn.key
dh dh4096.pem
# OpenVPN network
server 172.16.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
# Redirect all traffics to OpenVPN
push "redirect-gateway def1 bypass-dhcp"
keepalive 10 120
# This file is secret
tls-auth ta.key 0
# Cipher settings
cipher AES-256-CBC
auth SHA512
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA
comp-lzo
user openvpn 
group nogroup
persist-key
persist-tun
log        /var/log/openvpn.log
log-append  openvpn.log
verb 4 

ESC, type ":wq" to save the file.

Step 5: Configure Iptables and Routing

Configure iptables so that it can work under Azure environment, since all traffics will be routed from public IP address to the private IP address bound to a specific NIC, replace ethx with the real NIC device name.

# iptables configuration for openvpn
sudo iptables -A INPUT -i ethx -p udp -m state --state NEW -m udp --dport 32768 -j ACCEPT
sudo iptables -A INPUT -i tun+ -j ACCEPT
sudo iptables -A FORWARD -i tun+ -j ACCEPT
sudo iptables -A OUTPUT -o tun+ -j ACCEPT
sudo iptables -A FORWARD -i tun+ -o ethx -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i ethx -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o ethx -j MASQUERADE

Permanently enable the IP forwarding by editing /etc/sysctl.conf and adding the following line

sudo vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
:wq
sudo sysctl -p /etc/sysctl.conf

If the VM has multiple NICs and their IPs are all in same subnets

sudo bash -c "echo '200 ethx-rt' >> /etc/iproute2/rt_tables"
sudo vi /etc/network/interfaces.d/ethx.cfg

Add following configuration to ethx.cfg

auto ethx
iface ethx inet dhcp
    post-up ip route add 10.0.1.0/24 dev ethx src 10.0.1.6 table ethx-rt
    post-up ip route add default via 10.0.1.1 dev ethx table ethx-rt
    post-up ip rule add from 10.0.1.6/32 table ethx-rt
    post-up ip rule add to 10.0.1.6/32 table ethx-rt
    post-up ip rule add from 172.16.0.0/24 table ethx-rt

NOTE: Please replace ethx with the real NIC name.

Step 6: Start and Enable OpenVPN Service

Start openvpn service

sudo systemctl start openvpn@server
sudo systemctl status openvpn@server

Check openvpn service's status

● openvpn@server.service - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/openvpn@.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-05-18 11:57:04 UTC; 11h ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 1921 ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/ope
 Main PID: 1999 (openvpn)
   CGroup: /system.slice/system-openvpn.slice/openvpn@server.service
           └─1999 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/ope

May 18 11:57:03 <server> systemd[1]: Starting OpenVPN connection to server...
May 18 11:57:04 <server> systemd[1]: Started OpenVPN connection to server.

If everything is OK, enable openvpn service so that it can start automatically when reboot OS

sudo systemctl enable openvpn@server

Step 7: Generate Client Profile and Connect to OpenVPN Service

Create a shell script to generate client profile

vi genprofile.sh

Add following lines into genprofile.sh

cd ~/openvpn-ca
source vars
./build-key --batch $1
cd ~/client-configs
./make_config.sh $1

Press "ESC", type ":wq" to save the file

chmod +x genprofile.sh

Create a new directory called "client-configs"

mkdir client-configs
mkdir client-configs/files
cd client-configs

Create a base client configuration file "base.conf"

vi base.conf

Add following lines into it

client
dev tun
proto udp
remote <YOUR_OPENVPN_PUBLIC_IP_OR_DNS_NAME> 32768
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
remote-cert-tls server
key-direction 1
cipher AES-256-CBC
auth SHA512
comp-lzo
verb 3

ESC, type ":wq" to save the file. Now create a script file called make_config.sh

vi make_config.sh

Add following content into the file

#!/bin/bash

# First argument: Client identifier

KEY_DIR=~/openvpn-ca/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

ESC, type ":wq" to save the file

chmod +x make_config.sh

Step 8: Connect to OpenVPN server from client side

From OpenVPN server, run

./genprofile.sh <profile name>

Above command will generate a client profile and save it into ~/client-configs/files, copy/download this profile to client side, from OpenVPN, import this profile and connect.

The client should have OpenVPN connection established and it should redirect all traffics to OpenVPN now.