Setting up an OpenVPN Server to Access your VPC Private Ressources

Photos via Pexels

What’s a Virtual Private Network?

Companies protect their data by storing it within a Private Network. This may be a server or computers on-premises, or cloud-hosted services. For the importance of securing data, the Network should be secured which means private.

When you use a VPN, you extend that Private Network, making it Virtual. In that way, remote workers are able to securely connect to the company’s network by using VPN connections over the internet. This can be done safely, continuing to keep the company’s data private, by encrypting those connections.

Through a VPN, packets are sent over the Internet through an encrypted tunnel. This tunnel makes it appear as though you are directly connected to the company’s private network.

The following Figure shows a company Private Network with a Remote Worker connected securely over an encrypted tunnel through VPN Access Server. Once connected, the Remote Worker can securely access the company’s network services exactly as though if he was in the Company’s Private Network. The firewall is configured to allow incoming, secure connections to the VPN server.

Nowadays more and more people are using VPN for other purposes such as: encrypting internet traffic and hide the IP address, mostly for privacy reasons, but also for securing sensitive information when connecting from public places or bypassing firewalls and/or restrictions.

The OpenVPN Access Server can be set up using cloud service providers, or on-premises with your own server.

In this article , i will focus on the configuration of our own OpenVPN server on the Cloud so that any remote worker can access the private ressources on the Company’s Virtual Private Cloud(VPC). I’ll be using the notions explained in my previous article : VPC, Bastion Host, SSH Agent. Make sure to check it out for a better understanding before diving further.

Prerequisites

This is how the above infrastructure works :

  1. The OpenVPN Server runs on the OpenVPN server Host, this host has both a public and a private IP address. Because It has a public IP adress, it is exposed to the internet. It is located in the specific subnet named Server’s Subnet. The OpenVPN Server has a Certificate Authority installed on it, this one is responsible for creating and signing certificates for the remote workers and the server in order to allow them to communicate securely over the VPN Tunnel.
  2. The Instance Host is the company’s private Instance that the remote worker is trying to reach via internet through the VPN Tunnel. It doesn’t have any public IP address, which means it cannot be accessible via internet. That makes it reachable only from the VPC or via the VPN Tunnel. It is located in the specific subnet named Instance’s Subnet.
  3. The subnets are in the same VPC so they can communicate which means a remote worker with an IP from the Server’s subnet will be able to communicate via the VPN Tunnel with any private instance on the VPC even if it doesn’t have a public IP address (unreachable via internet).
  4. The OpenVPN server listens for clients/remote workers incoming requests on port 1194.
  5. Clients/remote workers establish communication with the OpenVPN server using the 9999 port as a source port and 1194 as destination port. In that way, clients wont have a random port generated each time they try to establish communication with the OpenVPN Server.
  6. Note that for my gateways i’ve used 254 instead of 1. This is because the OpenVPN virtual interface take the 1 as a gateway. However if this address have already been allocated to the actual gateway of the instance, it wont be available for the VPN’s interface and things wont work.

You can adapt this infrastructure to match your company’s need.

Now, In order to get started, all what you need is your Cloud Provider Account, two Ubuntu18.04 compute instances as described in the VPC of the Figure above. You also need setup the different networking requierement on your VPC as described in the infrastructure and of course you need an SSH access to the OpenVPN Server.

Setting up OpenVPN

sudo suapt update && apt upgrade

Reboot the instance:

systemctl reboot

OpenVPN installation

apt install openvpn easy-rsa

On the Remote Worker Host, install only OpenVPN

apt install openvpn

Public Key Infrastructure and Certificate Authorities

easy-rsais a package that allows the creation of your own Certificate Authority(CA) responsible for generating digital certificates.

The created certificates allow to encrypt, decrypt, authenticate, sign and verify certificates signatures which ensures secure communication and trust between the remote workers (clients) and the OpenVPN Server.

The OpenVPN server will only allow clients with valid certificates to connect to it. Furthermore, it will encrypt data in such a way, that only the client that owns that certificate can decrypt it. By checking digital signatures, clients can validate the authenticity of the server they are connecting to. This helps avoid attacks such as Man in the Middle.

Nowadays companies are facing powerful hackers that are motivated and advanced in the ability to compromise a server, steal cryptographic secrets and then use the data to impersonate the OpenVPN instanc. For this reason, companies should take careful measures to protect their Certificate Authority data.

For the sake of simplicity, we will configure the Certificate Authority on our OpenVPN server.

If you find yourself in the above mentioned situation, then you should learn more about the secrets that need to be protected in a public key infrastructure and keep them on a separate, reasonably secure computer, preferably password encrypted and isolated from the Internet. You should generate your certificate authority on such an isolated environment, create and sign certificates as needed and export the public components only when you have to distribute them (for example client certificates that you can import on your laptop or phone, to be able to connect to the VPN server).

Create your Certificate Authority (CA)

make-cadir ca

Next, acccess your cadirectory

cd ca

Then, edit the vars file:

nano vars

Edit these lines to fit your company’s information

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"

In your ca directory you’ll find openssl-1.0.0.cnf file that you need to link to openssl.cnf file that will be used by your CA.

Source the vars file to set the appropriate environment variables :

source vars

Generate a clean environment :

./clean-all

Generate certificate authority data :

./build-ca

Press ENTER at the prompts to select the pre-filled values.

Generate the Server’s Certificate

./build-key-server server

Press ENTER to select default answers. answer the questions with a yes in order for the server’s certificate to be signed and validated by the CA.

Generate Diffie-Hellman parameters :

./build-dh

Generate the Client’s Certificate

The First Method

Generate a client key and answer with a yes to the questions in order for the CA to sign the certificate.

./build-key client

This key can be imported to phones, computers that we want to authorize to connect to the OpenVPN server. you can generate multiple keys for multiple devices for one client through choosing descriptive names such as : client-phone, client-laptop.

The second Method

If you want to use a key-password based, you can generate it with the following command :

./build-key-pass client

Now, for both methods, copy the required certificates and keys to OpenVPN’s configuration directory:

cp keys/server.crt /etc/openvpn/
cp keys/server.key /etc/openvpn/
cp keys/ca.crt /etc/openvpn/
cp keys/dh2048.pem /etc/openvpn/

Configure the OpenVPN Server

zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf

Next, edit the server.conffile :

nano /etc/openvpn/server.conf

Modify the server line by adding the server’s subnet IP address

# Configure server mode and supply a VPN subnet
# for OpenVPN to draw client addresses from.
# The server will take 10.8.0.1 for itself,
# the rest will be made available to clients.
# Each client will be able to reach the server
# on 10.8.0.1. Comment this line out if you are
# ethernet bridging. See the man page for more info.
;server 10.8.0.0 255.255.255.0
server 10.8.2.0 255.255.255.0

server 10.8.2.0 255.255.255.0 is the server’s subnet address and mask

Important

Make sure to use 10.8.2.254 as a gateway IP for your subnet instead of 10.8.2.1 because if you’re in the same subnet and your gateway is 10.8.2.1 by default the OpenVPN server takes 10.8.2.1 for itself which can cause a conflit as this address is not available.

Next, modify these lines by uncommenting the last line through deleting the “;”.

# If enabled, this directive will configure
# all clients to redirect their default
# network gateway through the VPN, causing
# all IP traffic such as web browsing and
# and DNS lookups to go through the VPN
# (The OpenVPN server machine may need to NAT
# or bridge the TUN/TAP interface to the internet
# in order for this to work properly).
;push "redirect-gateway def1 bypass-dhcp"

Which will lead us to this

# If enabled, this directive will configure
# all clients to redirect their default
# network gateway through the VPN, causing
# all IP traffic such as web browsing and
# and DNS lookups to go through the VPN
# (The OpenVPN server machine may need to NAT
# or bridge the TUN/TAP interface to the internet
# in order for this to work properly).
push "redirect-gateway def1 bypass-dhcp"

Then, in the next block, uncomment the last two lines:

# Certain Windows-specific network settings
# can be pushed to clients, such as DNS
# or WINS server addresses. CAVEAT:
# http://openvpn.net/faq.html#dhcpcaveats
# The addresses below refer to the public
# DNS servers provided by opendns.com.
;push "dhcp-option DNS 208.67.222.222"
;push "dhcp-option DNS 208.67.220.220"

Which will lead us to this

# Certain Windows-specific network settings
# can be pushed to clients, such as DNS
# or WINS server addresses. CAVEAT:
# http://openvpn.net/faq.html#dhcpcaveats
# The addresses below refer to the public
# DNS servers provided by opendns.com.
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"

Then, move on to the following block and uncomment the last two lines:

# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
#
# You can uncomment this out on
# non-Windows systems.
;user nobody
;group nogroup

This will lead us to this

# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
#
# You can uncomment this out on
# non-Windows systems.
user nobody
group nogroup

Finally, save the changes and enable HMAC to ensure data integrity in order to make sure data hasn’t been modified in transit by Man in the Middle attack.

echo -e '\n#Enable HMAC\nauth SHA256' >> /etc/openvpn/server.conf

Generate a key that will be used by HMAC :

openvpn --genkey --secret /etc/openvpn/ta.key

Start the OpenVPN server process :

systemctl start openvpn@server

Configure the Server to Route Our Internet Packets

echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/local.conf

Apply the new setting using the following command

sysctl --system

A technique known as masquerading has to be configured to allow network address translation. For this, we first have to find out the name of the current interface that routes our packets

ip route

This will show that the default route goes through “dev eth0”. Let’s configure network address translation through eth0 :

iptables -t nat -A POSTROUTING -s 10.8.2.0/24 -o eth0 -j MASQUERADE

Forwarding traffic for anyone on the network opens the door for possible abuses. Let’s limit forwarding only to packets that come through the VPN tunnel (presumably whoever/whatever goes through the tunnel is authorized and authenticated).

iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.2.0/24 -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -j REJECT

But these settings would be lost after a reboot. Let’s make them persistent:

apt install iptables-persistent

When prompted to “Save current IPv4 rules?”, select the default answer “Yes”. IPv6 rules are irrelevant since we are not using it so you should answer “No”.

Note :

10.8.2.0/24 is the private IP address of your Server’s subnet VPC.Based on this network address, the clients IP addresses will be defined and attributed.

Generate Client Profiles (.ovpn Files)

mkdir clientprofiles

Copy a template config file :

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf clientprofiles/client.ovpn

Start editing the file :

nano clientprofiles/client.ovpn

Modify these lines to set the client’s source port

# Most clients don’t need to bind to
# a specific local port number.
#nobind
lport 9999

Scroll down and find the following text:

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote my-server-1 1194
;remote my-server-2 1194

Replace my-serverwith the public IP address of your server. For example :

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote 203.0.113.2 1194
;remote my-server-2 1194

Scroll down until you find :

# SSL/TLS parms.
# See the server config file for more
# description. It's best to use
# a separate .crt/.key file pair
# for each client. A single ca
# file can be used for all clients.
ca ca.crt
cert client.crt
key client.key

Comment the last three lines :

# SSL/TLS parms.
# See the server config file for more
# description. It's best to use
# a separate .crt/.key file pair
# for each client. A single ca
# file can be used for all clients.
;ca ca.crt
;cert client.crt
;key client.key

Those lines indicate the path to the certificate and key files. We will be adding these inside our .ovpn file. This makes transferring .ovpn profiles much easier since we’ll have to deal with just one file instead of a profile file and three additional files for each client.

Enable HMAC in the client configuration:

echo -e '\n#Enable HMAC\nauth SHA256' >> clientprofiles/client.ovpn

Add the key to the OpenVPN client profile.

echo "<key>
`cat keys/client1.key`
</key>" >> clientprofiles/client.ovpn

Add the client certificate:

echo "<cert>
`cat keys/client1.crt`
</cert>" >> clientprofiles/client.ovpn

Add the CA certificate:

echo "<ca>
`cat keys/ca.crt`
</ca>" >> clientprofiles/client.ovpn

And finally, add the TLS key:

echo "<tls-auth>
`cat /etc/openvpn/ta.key`
</tls-auth>" >> clientprofiles/client.ovpn

Now, as a remote worker, you can use rsync command to get your certificate on the OpenVPN server.

rsync -avz OpenVPNServer:/path-to-certificate /etc/openvpn/client

OpenVPNServer is defined in the config file as described in my previous article on SSH Agent.

Because you’ve installed the OpenVPN client on your machines ( as described in the first steps above) you just need to run the following commands :

sudo su
cd /etc/openvpn/client

Start your OpenVPN client using the following command :

openvpn --config name_of_certificate.ovpn

If these steps will successfully work for you, you can open a new CLI and SSH to your private instances using their corresponding private addresses because you’ll be virtually present in your VPC.

Troubleshooting

This kind of error is due to the fact that if multiple tun interfaces are active and all of them are configured to use the same gateway 10.8.0.1 to reach the same network (Public IP of the OpenVPN Server). The router will don’t know what to do and which one to choose so it will automatically reject your packet.

You can check this conflict by running :

ip route

To check routes that your VPN packet have taken through a tunnel :

sudo apt-get update -y
sudo apt-get install -y traceroute
traceroute 10.8.3.50

10.8.3.50 is your Instance’s private IP. You should get the following result :

traceroute to 10.8.3.50 (10.8.3.50), 30 hops max, 60 byte packets
1 _gateway (10.8.2.1) 12.193 ms * *
2 * * *
3 10.8.3.50 (10.8.3.50) 12.007 ms 12.077 ms 11.969 ms

References :

Reach OpenVPN clients directly from a private network

Use-cases for the OpenVPN Access Server product

Creating configuration files for server and clients

Setting up your own Certificate Authority (CA)

How to Create a VPN Server with OpenVPN

Client OpenVPN

2x HOW TO

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store