Setting up an OpenVPN Server to Access your VPC Private Ressources
What’s a Virtual Private Network?
Based on the OpenVPN documentation, a Virtual Private Network (VPN) provides you a securely encrypted connection to your company’s network over the Internet.
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
For this article, I’ll be building the following infrastructure using Flexible Engine Cloud Provider. You can use any Cloud Provider you want.
This is how the above infrastructure works :
- 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.
- 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.
- 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).
- The OpenVPN server listens for clients/remote workers incoming requests on port 1194.
- 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.
- 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
First, use the SSH-Agent with your OpenVPN server’s corresponding private key as described in my previous article and on the Figure above in order to log into the OpenVPN server. Once it’s done, run the following :
sudo suapt update && apt upgrade
Reboot the instance:
systemctl reboot
OpenVPN installation
On the Server,install OpenVPN and easy-rsa:
apt install openvpn easy-rsa
On the Remote Worker Host, install only OpenVPN
apt install openvpn
Public Key Infrastructure and Certificate Authorities
The public key infrastructure have been explained in detail in my Certificate Authority article.
easy-rsa
is 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)
First , use the SSH-Agent with your Server’s corresponding private key to log on to the Server then create the ca
directory and copy the easy-rsa tools to it
make-cadir ca
Next, acccess your ca
directory
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
Your OpenVPN server need a certificate, to build it, run the following
./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
On your Server, you need to use the created CA to create and sign the certificates. There is two main methods for generating the client’s key, you need to choose only one method because running both commands for the same client’s key will invalidate 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
First, extract the template configuration file :
zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
Next, edit the server.conf
file :
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
The OpenVPN server will act as an intermediary between the remote workers devices and the rest of the VPC instances. To be able to do this, we need to enable IP forwarding.
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)
.ovpn
files will contain all the required information (settings, keys and certificates) to connect to the OpenVPN server. Create the directory where these files will be stored on the Server.
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-server
with 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
If you get errors such as the famous “ no route to host “ error. You need to check that you don’t have more then one OpenVPN virtual interface active at once. For example tun0 and tun1
. You need to ensure that you have no tun
interface active before launching your OpenVPN client.
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 :
Troubleshooting reaching systems over the VPN tunnel
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)