After configuring the overall OpenVPN client and server infrastructure, my clients can connect to a VPN. The client can access server resources and vice versa. While the server gets normally always the same IP assigned, the client IP address is assigned dynamically from a pool of IP addresses. Meaning: there is no guarantee that the client always gets the same IP address. Normally, this is not a problem, as the client connects to consume server resources. Such like a web site, or git repository. In my case, the architecture is that the OpenVPN server acts as a proxy to internal services. The web site, git repository, etc are running on the client. Therefore, the server must be able to connect to the client using a fix address.
To make this work, each time a client connects, the same IP must be assigned to. OpenVPN allows to assign a static IP to a client.
In /etc/openvpn create folder ccd. Ccd stands for client config directory, meaning: it contains the configuration for a client.
Edit file server.conf and add line “client-config-dir ccd“
# EXAMPLE: Suppose the client
# having the certificate common name "Thelonious"
# also has a small subnet behind his connecting
# machine, such as 192.168.40.128/255.255.255.248.
# First, uncomment out these lines:
3. Create a configuration file for each client and put into directory ccd. As file name, use the same name for the client as used in the CN field of the client certificate.
ifconfig-push IP MASK
ifconfig-push 10.8.0.2 255.255.255.255
sudo mkdir /etc/openvpn/ccd
sudo touch /etc/openvpn/ccd/client1
sudo vim /etc/openvpn/server.conf
Uncomment the line containing client config parameter
sudo vim /etc/openvpn/ccd/client1
ifconfig-push 10.8.0.2 255.255.255.255
Restart OpenVPN service on server
sudo /etc/init.d/openvpn restart
Client with automatic assignment of IP: 10.8.0.6
After restart of OpenVPN server: IP is now 10.8.0.2
While setting up OpenVPN I came accross some common errors or workarounds that make life easier. To make it easier to remember these I have documented them in this blog. Maybe they are useful for others as well.
Remove pass phrase
In case you want to remove the pass phrase from the server key to make it easiert to start the OpenVPN server part, use the following command:
You’ll have to enter one more time the pass phrase of the key, and then a new server.key file is written without the pass phrase. You can see this when looking into the key files.
With pass phrase:
Note: file starts with: BEGIN ENCRYPTED PRIVATE KEY
Without pass phrase:
Note: file starts with: BEGIN RSA PRIVATE KEY
Run OpenVPN as a service on Linux
After installing openvpn via yum on AWS AMI Linux, a service script is also installed. How the file works and can be activated is written in the file itself:
The file should already be copied by yum to /etc/rc.d/init.d/openvpn
Activate the service
Check whether or not openvpn is already configured to run as a service. For each run level, the status is either on or off. In case of on, openvpn is already configured to run as a service. In this example, opevpn is not configured to run as a service in any runlevel.
sudo chkconfig --add openvpn
sudo chkconfig openvpn on
OpenVPN will now be started as a service in the run levels 2, 3, 4 and 5. Output of openvpn is then written to /var/log/messages
sudo tail -f /var/log/messages
To start and control openvpn via systemd. Check status of openvpn.
sudo systemctl status openvpn
Edit service configuration
sudo vim /etc/default/openvpn
Insert the client configuration to start automatically. Here, I am going to start client1.conf:
sudo systemctl start openvpn
sudo systemctl status openvpn
Solving common OpenVPN connection error message
Some information on how to solve common OpenVPN error message on the server and client. Most occur when trying to start OpenVPN for the first time.
Client starts connecting but no connection is established.
TLS Error: cannot locate HMAC in incoming packet from [AF_INET]
Server is configured to use ta.key.
Copy the ta.key into the openvpn configuration directory and specify its location in the conf file.
Cipher final failed
OpenVPN server accepts a client connection, but communication fails.
Authenticate/Decrypt packet error: cipher final failed
Server and client are using different algorithms for encryption and decryption. On the server, the log gives more information:
WARNING: 'cipher' is used inconsistently, local='cipher AES-256-CBC', remote='cipher BF-CBC'
Server uses AES-256-CBC, while the client is using BF-CBC. Adjust the client configuration in client.conf. Insert cipher AES-256-CBC in client.conf
Other parameters to adjust
During first startup, some warning message may be written on the server log. Most common they refer to link-mtu, cipher, keysize or comp-lzo.
WARNING: 'link-mtu' is used inconsistently, local='link-mtu 1557', remote='link-mtu 1542'
WARNING: 'keysize' is used inconsistently, local='keysize 256', remote='keysize 128'
WARNING: 'comp-lzo' is present in remote config but missing in local config, remote='comp-lzo'
Adjust the parameters in the client.conf file so that they match the server configuration. Also good to check this way if a not controlled/configured client is connecting to your server.
Configure the client to use the same mtu size as the server. Insert parameter link-mtu into client.conf.
Keysize used by client and server should be the same. Insert parameter keysize into client.conf.
After configuring and running both the OpenVPN server and client, it’s a good idea to test if the VPN is working. This involves some tests on both the server and client.
After the server is started, a new interface should be created. Run ifconfig to get a list of all available interfaces. In case tun is configured in the conf file as device type, a new interface with name tun0 is created.
Check server log for client connection
In case OpenVPN is started as a service, the log can be found at /var/log/messages. If you start it directly on the command line, the log will be shown on the shell. When a client connects, the log of the server shows the connection information.
tail -f /var/log/messages
The last lines show client1, meaning that the client not only connected, but is also correctly identified as client1. The connection is working.
Start OpenVPN and the client will try to connect to the server specified in the client.conf file. Client connecting and receiving IP.
After the connection was established, the client is also creating a new interface named tun0. Here a client named client1 connects and receives the IP 10.8.0.6.
Easiest way to test that client and server can talk to each other is to ping both. Just run a ping from the server to the client IP, and from the client to the server IP. For this, the VPN IP address must be used (e.g. 10.8.0.x).
OpenVPN uses certificates to authenticate the server and clients. Therefore, the client needs to have a valid client certificate. This certificate needs to be issued by the CA server that also issued the certificate of the OpenVPN server. In my case, this server is installed together with the OpenVPN server on the AWS EC2 instance. The process to create the client certificate is the same as with the server certificate, only the certificate type must be client, or: TLS Web Client Authentication. This is done by specifying the client parameter in the generate certificate request command.
Depending whether or not easy-rsa or any other tool to generate a certificate request is available on the client, the request can be generated directly on the client. The vantage by creating the request on the client is that the private key will stay on the client. In my example, I’ll make use of the already available infrastructure on the OpenVPN server and generate the client request and certificate on the server and copy later the generated artifacts over to the client.
Create client certificate
Log in to the CA (OpenVPN) server and issue a client certificate request. The name of the client will be client1. Note that you can use a different name, like the FQDN of the client.
sudo ./easyrsa gen-req client1
As with the server certificate, give a passphrase and common name.
Next: sign the client1 certificate by the CA.
sudo ./easyrsa sign-req client client1
You need to confirm the signing request by entering yes and informing the pass phrase of the CA certificate.
The client certificate is now issued.
Private key: easy-rsa/pki/private/client1.key
Public certificate: easy-rsa/pki/issued/client1.crt
Move these files to the OpenVPN client.
OpenVPN client Installation
The client going to connect to the OpenVPN server running on AWS EC2 is a Raspberry Pi. The RP uses a Debian based Linux, therefore apt is used to install software. On the RP, install OpenVPN. Easy-rsa is not needed, as the CA is running on the EC2 instance.
sudo apt-get update
sudo apt-get install openvpn
Create a openvpn directory. Can be in /etc/ or in your user’s home. Put the client’s public certificate and privte key there. To use HMCA for additional security, copy the ta.key file from the server there too.
Copy the OpenVPN sample client configuration to your openvpn directory and edit the file client.conf.
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf .
Adjust the following lines to point to the correct server (AWS EC2) and local certificates and key. Example:
remote server.domain.com 1194
tls-auth /home/tobias/openvpn/ta.key 1
The tls-auth parameter is needed in case the server is configured to use HCMA. The shared key ta.key from the server is needed for this to work.
Start OpenVPN client
To start the OpenVPN as client, run the executable and pass the path to the configuration file as parameter.
You need to provide the pass phrase of the client1 private key.
The client will automatically connect to the OpenVPN server defined in the client.conf file (remote parameter) and the given port (1194). Make sure that on AWS EC2, this port is accessible for the client.
If all works, the client connects to the server and gets an internal IP assigned.
Recently I got some new hardware that I will use to run some useful software. To use the software from anywhere, I’ll need to have remote access. As I cannot do DMZ or port forwarding with my new internet provider, I decided to connect my home server using VPN to a access machine running on AWS.
The AWS EC2 Linux computer will serve as my entry point. Services running on the RP at home connected via VPN can be accessed from EC2. Other computers at my home cannot be accessed, as the IP is different and no route is configured.
This setup comes with several architectural questions to solve:
How to ensure the communication is secure?
How to guarantee the tunnel is up?
How to enable access from EC2 to the services running on the client?
The client must be assigned the same IP for the services be accessible from EC2
How to give access to the services from the internet?
The three top question will be answered in my next blogs about how to set up OpenVPN server and client. The first question is the easiest to answer: by using a VPN solution. I am going to use OpenVPN and this blog is about how to setup OpenVPN. I’ll cover the installation on the EC2 instance and on the Raspberry Pi, as well as the initial setup with the certificates, server and client configuration and how to connect. Starting the client and server as service keeps them running and in case the connection fails, an automatic reconnect is attempted. The EC2 instance can access the services running on the client automatically. The last two questions will be answered sometimes later.
Install OpenVPN on EC2
The OpenVPN software is available in yum on EC2 Linux AMI. You may need to enable the REPL repository. I assume you did this already. The packages to install a openvpn and easy-rsa.
sudo yum update
sudo yum install openvpn easy-rsa
This will also install a public key to install a package and ask for your permission to do so.
The easy-rsa package is needed to set up a certificate authority. In case you do have a CA available, you can use your CA to generate the certificates used by OpenVPN. For those that do not have a CA available, take the easy-rsa functionality.
The command above installs easy-rsa 3.x. With 3.x, the way how to use easy-rsa and to set up a CA and issue the certificates changed. You can see in detail how to use easy-rsa 3.x at the documentation available at the GitHub project site.
OpenVPN uses certificates, and easy-rsa issues those certificates. Basically, you have two components of easy-rsa to deal with:
Configuration of OpenVPN is put and read from /etc/openvpn. Easy-rsa software should be in a separate folder, like /home/ec2-user/easy-rsa, but to keep all in one place I’ll put easy-rsa inside the /etc/openvpn directory.
Note: for real productive usage, don’t do this. Separate easy-rsa executables and config files.
Copy easy-rsa to your selection location. For this, first find out where easy-rsa is installed.
repoquery -l easy-rsa
Location is /usr/share/easy-rsa/3.0.3. I’ll copy these files to /etc/openvpn/easy-rsa.
Follow the steps outlined at the easy-rsa git site. For the following steps, go into the directory where easy-rsa is installed.
sudo ./easyrsa init-pki
This will create the CA certificate to sign certificate requests. In other words: whoever gets access to the private key of the CA created in this step, can create new valid OpenVPN clients for your setup. Take care of the CA certificate and key.
sudo ./easyrsa build-ca
You’ll need to enter:
PEM pass phrase
The passphrase is used to unlock the private key and is an additional level of security. Even when someone gets a copy of the private key of your CA, without the pass phrase the key is not usable. The common name is used to identify the CA. I used the FQDN of my web server. After execution these two commands, the CA is initialized and can be used to issue certificates.
Generate Diffie-Hellman parameters.
sudo ./easyrsa gen-dh
Generate OpenVPN server certificate
The OpenVPN server needs a certificate issued by the CA to identify itself against the clients. This is a nice “feature” when using PKI. Server and client can validate the other side. Both need just to trust the CA certificate for this. The difference between the two certificates (client and server) is the included type. This is done by including an additional value in the certificate specifying the type of certificate:
TLS Web Server Authentication for the server and
TLS Web Client Authentication for the client
Which kind of certificate is going to be issued is specified by the easy-rsa command when creating the certificate request.
Generate certificate request
Create a certificate request containing the identity information of the server and let this request be signed by the CA. By specifying the server parameter, the request is for a server and the CA will include the value TLS Web Server Authentication in the extension.
sudo ./easyrsa gen-req server
As with the CA certificate, inform a pass phrase that adds additional security to the private key and a common name to uniquely identify the server. I used server as CN. Of course, it could also have been openvpn.mydomain.com or something else.
Send the request to the CA and sign it to issue a valid certificate. With that, the CA information is added to the CA, making it official and clients that connect to OpenVPN server will know if they can trust the server. Only when trust is verified, a connection will be established between the server and client.
sudo ./easyrsa sign-req server server
You’ll need to confirm the request by typing yes and the pass phrase.
The following certificate is needed to harden the overall security of OpenVPN. As OpenVPN is using TLS, it makes sense to add HMAC to validate integrity of the packages received. For this to work, a shared secret key is needed. This key will be written to a file named ta.key.
Take a sample configuration file as a template. Can be found in the doc folder of openvpn. The sample configuration file for the server is server.conf, and for the client, client.conf.
ls -1 /usr/share/doc/openvpn-2.4.4/sample/sample-config-files/
Copy server.conf to /etc/openvpn and edit the file.
sudo cp /usr/share/doc/openvpn-2.4.4/sample/sample-config-files/server.conf /etc/openvpn/
sudo vim /etc/openvpn/server.conf
Adjust the path to the ca, cert, key and dh files
These parameters inform OpenVPN where the certificates and Keys are stored. The CA cert ca.crt is used to validate the client certificates. They must be issued by this CA. The server.crt and server.key are used by the OpenVPN server to encrypt traffic and authenticate itselfs against clients. Diffie hellman dh.pem is used to provide Perfect Forward Secrecy.
Start OpenVPN server
To start the OpenVPN server and to test the current setup, run the following command:
sudo openvpn /etc/openvpn/server.conf
During startup, you need to provide the passphrase of the server certificate.
If all works, OpenVPN starts without erros: Initialization Sequence Completed. After this, the server is waiting for clients to connect.
If someone is reading my blogs for the last years you may remember that I have once written about setting up OpenVPN for accessing SUP on AWS. That blog was all about Windows and is outdated. I wrote it in 2012. But, as I published it once at SAP Community Network, it is not available anymore. SAP lost it during their last migration.