Connecting to my Cloud using OpenVPN

Preface

The todays blog post is one, that I prepared a long while ago. It is part of my journey to the (Oracle) Cloud and even though I tried the following more than a year ago, it is still useful I think. As the title states, I will write about a VPN connection to my cloud environment. Why is this neccessary you may ask. With the Oracle Cloud there are several mechanisms to make a connection to the cloud private and encrypted. You may use a dedicated VPN or Fast Connect, both require somewhat dedicated hardware at the customer site (me). For my private purposes this is not quite feasible. And this may also apply for small buisnesses. So I decided to install a OpenVPN server in my cloud to esatblish a private connection.

The OpenVPN server will be installed on a system in a separate subnet and will route the traffic to the cloud-internal subnet. For my testing purposes I use an always-free compute instance running Oracle Linux 7 for that.

So lets get started. First, I’ll mention the sources that helped my creating this setup. This is basically from OpenVPN community and HowtoForge.

Installation

Most obviously I have to install the OpenVPN server first. This is easy as there is a RPM package for it.

[root@dbamarco-02 yum.repos.d]# yum info openvpn
Loaded plugins: langpacks, ulninfo
Available Packages
Name        : openvpn
Arch        : x86_64
Version     : 2.4.8
Release     : 1.el7
Size        : 522 k
Repo        : ol7_developer_EPEL/x86_64
Summary     : A full-featured SSL VPN solution
URL         : https://community.openvpn.net/
License     : GPLv2
Description : OpenVPN is a robust and highly flexible tunneling application that uses all
            : of the encryption, authentication, and certification features of the
            : OpenSSL library to securely tunnel IP networks over a single UDP or TCP
            : port.  It can use the Marcus Franz Xaver Johannes Oberhumers LZO library
            : for compression.

[root@dbamarco-02 yum.repos.d]# yum install openvpn
Loaded plugins: langpacks, ulninfo
Resolving Dependencies
--> Running transaction check
---> Package openvpn.x86_64 0:2.4.8-1.el7 will be installed
--> Processing Dependency: libpkcs11-helper.so.1()(64bit) for package: openvpn-2.4.8-1.el7.x86_64
--> Running transaction check
---> Package pkcs11-helper.x86_64 0:1.11-3.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=====================================================================================================================================================
 Package                             Arch                         Version                             Repository                                Size
=====================================================================================================================================================
Installing:
 openvpn                             x86_64                       2.4.8-1.el7                         ol7_developer_EPEL                       522 k
Installing for dependencies:
 pkcs11-helper                       x86_64                       1.11-3.el7                          ol7_developer_EPEL                        56 k

Transaction Summary
=====================================================================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 578 k
Installed size: 1.4 M
Is this ok [y/d/N]: y
Downloading packages:
(1/2): pkcs11-helper-1.11-3.el7.x86_64.rpm                                                                                    |  56 kB  00:00:00
(2/2): openvpn-2.4.8-1.el7.x86_64.rpm                                                                                         | 522 kB  00:00:00
-----------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                3.2 MB/s | 578 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : pkcs11-helper-1.11-3.el7.x86_64                                                                                                   1/2
  Installing : openvpn-2.4.8-1.el7.x86_64                                                                                                        2/2
  Verifying  : openvpn-2.4.8-1.el7.x86_64                                                                                                        1/2
  Verifying  : pkcs11-helper-1.11-3.el7.x86_64                                                                                                   2/2

Installed:
  openvpn.x86_64 0:2.4.8-1.el7

Dependency Installed:
  pkcs11-helper.x86_64 0:1.11-3.el7

Complete!

The RPM not only installs the OpenVPN server but also creates a dedicated user for it. The password for this user named “openvpn” should be set as follows.

[root@dbamarco-02 yum.repos.d]# passwd openvpn
Changing password for user openvpn.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

Now I installed the Easy-RSA packages to support the management of RSA keys.

[root@dbamarco-02 ~]# yum install easy-rsa
Loaded plugins: langpacks, ulninfo
ol7_UEKR5                                                                            | 2.8 kB  00:00:00
ol7_addons                                                                           | 2.8 kB  00:00:00
ol7_developer                                                                        | 2.8 kB  00:00:00
ol7_developer_EPEL                                                                   | 3.4 kB  00:00:00
ol7_ksplice                                                                          | 2.8 kB  00:00:00
ol7_latest                                                                           | 3.4 kB  00:00:00
ol7_oci_included                                                                     | 2.9 kB  00:00:00
ol7_optional_latest                                                                  | 2.8 kB  00:00:00
ol7_software_collections                                                             | 2.8 kB  00:00:00
(1/15): ol7_UEKR5/x86_64/updateinfo                                                  |  32 kB  00:00:00
(2/15): ol7_addons/x86_64/primary_db                                                 | 147 kB  00:00:00
(3/15): ol7_developer/x86_64/updateinfo                                              | 5.0 kB  00:00:00
(4/15): ol7_developer/x86_64/primary_db                                              | 503 kB  00:00:00
(5/15): ol7_ksplice/updateinfo                                                       | 5.3 kB  00:00:00
(6/15): ol7_addons/x86_64/updateinfo                                                 |  84 kB  00:00:00
(7/15): ol7_latest/x86_64/group_gz                                                   | 148 kB  00:00:00
(8/15): ol7_ksplice/primary_db                                                       | 709 kB  00:00:00
(9/15): ol7_latest/x86_64/updateinfo                                                 | 2.7 MB  00:00:00
(10/15): ol7_optional_latest/x86_64/updateinfo                                       | 901 kB  00:00:00
(11/15): ol7_optional_latest/x86_64/primary_db                                       | 4.1 MB  00:00:00
(12/15): ol7_developer_EPEL/x86_64/primary_db                                        |  12 MB  00:00:00
(13/15): ol7_UEKR5/x86_64/primary_db                                                 |  11 MB  00:00:00
(14/15): ol7_software_collections/x86_64/primary_db                                  | 4.8 MB  00:00:00
(15/15): ol7_latest/x86_64/primary_db                                                |  19 MB  00:00:00
Resolving Dependencies
--> Running transaction check
---> Package easy-rsa.noarch 0:3.0.6-1.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

======================================================================================================================
 Package                                     Arch        Version           Repository                            Size
======================================================================================================================
Installing:
 easy-rsa                                    noarch      3.0.6-1.el7       ol7_developer_EPEL                    35 k

Transaction Summary
======================================================================================================================
Install  1 Package

Total download size: 35 k
Installed size: 90 k
Is this ok [y/d/N]: y
Downloading packages:
easy-rsa-3.0.6-1.el7.noarch.rpm                                                                |  35 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : easy-rsa-3.0.6-1.el7.noarch                                                                        1/1
  Verifying  : easy-rsa-3.0.6-1.el7.noarch                                                                        1/1

Installed:
  easy-rsa.noarch 0:3.0.6-1.el7

Complete!

Now that Easy-RSA is installed, it needs to be configured. For me this is a two-step process. First, initialize it and second, create a CA that will be later used to sign the certificates.

[root@dbamarco-02 ~]# /usr/share/easy-rsa/3/easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /root/pki

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa build-ca

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017

Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
Generating RSA private key, 2048 bit long modulus
..................................................................+++
............+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:DBAMarco CA

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/root/pki/ca.crt

Key preparation

Now I need to create at least two certificates, one for the server and one for the client(s). It is up to use to devide if every client should get its own certificate or if one certificate is used by all clients or maybe groups of clients. These are used just for authentication purposes later on. All certificates are created, then signed and lastly verified.

For the server certificate:

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa gen-req dbamarco-server nopass

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
......................................................................+++
......................................................................+++
writing new private key to '/root/pki/private/dbamarco-server.key.SqM4X4HaS0'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [dbamarco-server]:

Keypair and certificate request completed. Your files are:
req: /root/pki/reqs/dbamarco-server.req
key: /root/pki/private/dbamarco-server.key

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa sign-req server dbamarco-server

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 1080 days:

subject=
    commonName                = dbamarco-server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /root/pki/safessl-easyrsa.cnf
Enter pass phrase for /root/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'dbamarco-server'
Certificate is to be certified until Mar  3 14:38:45 2023 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /root/pki/issued/dbamarco-server.crt

[root@dbamarco-02 ~]# openssl verify -CAfile pki/ca.crt pki/issued/dbamarco-server.crt
pki/issued/dbamarco-server.crt: OK

And for the client, quite similar:

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa gen-req dbamarco-client01 nopass

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
.........................................+++
....+++
writing new private key to '/root/pki/private/dbamarco-client01.key.HSe2CqSAMX'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [dbamarco-client01]:

Keypair and certificate request completed. Your files are:
req: /root/pki/reqs/dbamarco-client01.req
key: /root/pki/private/dbamarco-client01.key

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa sign-req client dbamarco-client01

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a client certificate for 1080 days:

subject=
    commonName                = dbamarco-client01


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /root/pki/safessl-easyrsa.cnf
Enter pass phrase for /root/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'dbamarco-client01'
Certificate is to be certified until Mar  3 14:43:28 2023 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /root/pki/issued/dbamarco-client01.crt

[root@dbamarco-02 ~]# openssl verify -CAfile pki/ca.crt pki/issued/dbamarco-client01.crt
pki/issued/dbamarco-client01.crt: OK

Now I need another key, this time aDiffie-Hellman key that will be used to generate the session keys.

[root@dbamarco-02 ~]#  /usr/share/easy-rsa/3/easyrsa gen-dh

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
.........+.......................................................................................................................................+..............................................................................................+.................+.................................................................................................................................................................................+..................................................................................+......................................+....................................................................................................+..............................................................................................+...............+......................................................................................+.+...........................................................+...................................................+...............+..........................................................................................................................................................................................................................................................................................................................................................................................+.................+...............................................................................................+...........................................................................................+.................+...................................................................................+......................................................+..........................................................+................+....................+.......................................................................................................................+...................................+..................................................................................................................................+................................................................................................................................+......................................................................+.................................................................................+.......+..................+........................+.............................................................................+....................................................................................+..............................................................................................+...............................................................................................+................................................+.................+...................................+........................................................................................................................................................................................+...............................................................+..........................+................+.............................................................................................................................+.........................................................................+...................+...................................................+........................................................................................................................+...........................................................+.................................................................................................................+............................................................+..............................................................................................................................................................................................................................................................................................................................+..............................................................................+...............................................+........+..............................+................................................................................................................+..............................................................................................................................................+..................................................................................+.....................................................+..............................+.....................................................................................................................................................................................................+.................................................................................................................................+.............................................................................................................................................................................................................+..........................................................................................................+.....................................+.....................................................+.............................................................................................+.....................................................+..................+.+..................................................................................+.................................................................+............+..............................+.......................................+.......................................................+.............................................................................+....................................................................................................................................................................................................+.................................................................................................................................................................................................+....................................................................................................................................................................................................................................................+...........................+.............................................................+................................................................................................................+..................................................................................................................................................................................+...............................................................................................................................................................................................................................................+.....................................................................+...................................................................................................................................................................................................................................................................................+.....................+...........+................+.............+................................+..................................................................................................................................................................................................................................................................................................+................................................................................................................................+....................................................................................................................+.............................................................................................................+..........................+.......................+................................................+.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................+............................................................+...............................................................................................................................................................................................................................................................+.........+.....................................................................................................+.............+.............................................................................................................................+...................................................................................................................+.....+...........................................+.............................................................................................................................................................+..+....................................+........+....................................................................................................................................+..................................................................................................................................................................................................+....................+.....................................................+.................................................................................+..............................+...........................+................................+............................................+...............................................................................................................+...................................................................................................................................................+.....................................................+.....................+...........................................................................+..............+...........+..............+......................................................................................................................................................+..........................................................................................................................................................................................................................................+...........................................+.....................................................................................................................................................+.................................+........+.............................................+...................................+................................................................................+.................................................................................................+..................................................................+..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................++*++*

DH parameters of size 2048 created at /root/pki/dh.pem

All these keys are now copied (or moved) to the appropriate OpenVPN folder:

[root@dbamarco-02 ~]# cp pki/ca.crt /etc/openvpn/server/
[root@dbamarco-02 ~]# cp pki/issued/dbamarco-server.crt /etc/openvpn/server/
[root@dbamarco-02 ~]# cp pki/private/dbamarco-server.key /etc/openvpn/server/
[root@dbamarco-02 ~]# cp pki/dh.pem /etc/openvpn/server/

[root@dbamarco-02 ~]# cp pki/ca.crt /etc/openvpn/client/
[root@dbamarco-02 ~]# cp pki/issued/dbamarco-client01.crt /etc/openvpn/client/
[root@dbamarco-02 ~]# cp pki/private/dbamarco-client01.key /etc/openvpn/client/

The structure in the OpenVPN tree should now look similar to this:

[root@dbamarco-02 ~]# tree /etc/openvpn/
/etc/openvpn/
├── client
│   ├── ca.crt
│   ├── dbamarco-client01.crt
│   └── dbamarco-client01.key
└── server
    ├── ca.crt
    ├── dbamarco-server.crt
    ├── dbamarco-server.key
    └── dh.pem

2 directories, 7 files

Configuration

Now I can finally start to prepare my OpenVPN server. I start with the example configuration file. All the parameters are well documented inside this example file.

[root@dbamarco-02 ~]# cp /usr/share/doc/openvpn-2.4.8/sample/sample-config-files/server.conf /etc/openvpn/server/

For my server I adapted the settings for the keys to match the ones I just created, of cause set the IP for my server, push the route to my private cloud subnet to the clients and allowed for duplicate client certificates which in turn allows multiple clients to use the same certificate. Otherwise I would need to create a dedicated certificate per client. Finally my configuration looks like this:

# required
server 10.8.0.0 255.255.255.0

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/dbamarco-server.crt
key /etc/openvpn/server/dbamarco-server.key  # This file should be kept secret
dh /etc/openvpn/server/dh.pem
;tls-auth ta.key 0 # This file is secret
user nobody
group nobody
push "route 10.0.1.0 255.255.255.0" # route to Cloud Subnet

# optional / of interrest
;push "redirect-gateway def1 bypass-dhcp"
duplicate-cn    # one certificate for multiple clients
compress lz4-v2
push "compress lz4-v2"

Last but not least, I have to do some changes at the OS level. IP-forwarding needs to be enabled, so that my OpenVPN server can route packets from clients to the private subnet. Also, I need some firewall rules to allow OpenVPN traffic.

[root@dbamarco-02 ~]# grep forward /etc/sysctl.conf
[root@dbamarco-02 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@dbamarco-02 ~]# sysctl -p
net.ipv4.ip_forward = 1

[root@dbamarco-02 ~]# firewall-cmd --permanent --add-service=openvpn
success
[root@dbamarco-02 ~]# firewall-cmd --permanent --zone=trusted --add-service=openvpn
success
[root@dbamarco-02 ~]# firewall-cmd --permanent --zone=trusted --add-interface=tun0
success
[root@dbamarco-02 ~]# firewall-cmd --permanent --add-masquerade
success
[root@dbamarco-02 ~]# SERVERIP=$(ip route get 1.1.1.1 | awk 'NR==1 {print $(NF-2)}')
[root@dbamarco-02 ~]# firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s  10.8.0.0/24 -o $SERVERIP -j MASQUERADE
success
[root@dbamarco-02 ~]# firewall-cmd --reload
success

Finally, I can now start the OpenVPN server.

[root@dbamarco-02 ~]# systemctl start openvpn-server@server

The “@server” defines the configuration file, that will be used to operate the OpenVPN server. My file was named “server.conf”.

Client Connection

The client needs a configuration file too. I need to define the keys again and of cause the public IP of my OpenVPN server.

[root@dbamarco-02 ~]# cat /etc/openvpn/client/client.ovpn
client
dev tun
proto udp

remote 123.123.123.2 1194   # ofuscated

ca ca.crt
cert dbamarco-client01.crt
key dbamarco-client01.key

;cipher AES-256-CBC
;auth SHA512
;auth-nocache
;tls-version-min 1.2
;tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256

resolv-retry infinite
compress lz4
nobind
persist-key
persist-tun
mute-replay-warnings
verb 3

The clients will need this configuration file and the keys and certificates. I created an archive containing all the required files. This archive can then be downloaded and propagated to the clients.

[root@dbamarco-02 ~]# cd /etc/openvpn/client/
[root@dbamarco-02 client]# tar czvf /tmp/dbamarco-client01.tgz *
ca.crt
client.conf
dbamarco-client01.crt
dbamarco-client01.key

Now I can finally setup my Windows box. The OpenVPN client can be downloaded from the OpenVPN website. Once it is installed, I extract the archive containing the client configuration to C:/Users/<username>/OpenVPN/config/ and rename the file “client.conf” to “client.ovpn”. Otherwise the OpenVPN client will not be able to find the configuration.

Lastly, I import the configuration and establish the connection to my cloud network.

Import client profile/configuration
Imported client profile, ready to connect
VPN connection established

Now that I am connected to my OpenVPN server, I can reach my compute instance, that is running in the private subnet.

C:\> ssh -I .ssh/id_rsa opc@10.0.1.5
[opc@dbamarco-02 ~]$

That’s it. Hope it will help someone at some point.