...
Most of the information found here is an amalgamation from these tutorials: https://www.digitalocean.com/community/tutorials/how-to-set-up-and-configure-an-openvpn-server-on-centos-8 and https://vitux.com/how-to-install-openvpn-on-almalinux-8-centos-8-or-rocky-linux-8/ and https://openvpn.net/community-resources/how-to/ https://kifarunix.com/assign-static-ip-addresses-for-openvpn-clients/ https://www.paulligocki.com/auto-connect-openvpn-client-startup-raspian/
About OpenVPN and Easy-RSA
...
Code Block |
---|
;cipher AES-256-CBC cipher AES-256-GCM |
Right after this line, add an auth
directive to select the HMAC message digest algorithm. For this, SHA256
is a good choice:
Code Block |
---|
auth SHA256 |
Next, find the line containing a dh
directive, which defines Diffie-Hellman parameters. Since we’ve configured all the certificates to use Elliptic Curve Cryptography, there is no need for a Diffie-Hellman seed file. Comment out the existing line that looks like dh dh2048.pem
or dh dh.pem
. The filename for the Diffie-Hellman key may be different than what is listed in the example server configuration file. Then add a line after it with the contents dh none
:
Code Block |
---|
;dh dh2048.pem
dh none |
Next, we want OpenVPN to run with no privileges once it has started, so we need to tell it to run with a user and group of nobody. To enable this, find and uncomment the user nobody
and group nobody
lines by removing the ;
sign from the beginning of each line:
Code Block |
---|
user nobody
group nobody |
Modify the cert
and key
lines in the server.conf
configuration file so that they point to the appropriate jujitsu.crt
and jujitsu.key
files. :
Code Block |
---|
cert jujitsu.crt
key jujitsu.key |
When you are finished, save and close the file.
You have now finished configuring your OpenVPN general settings. In the next step, we’ll customize the server’s networking options.
Adjusting the OpenVPN Server Networking Configuration
There are some aspects of the server’s networking configuration that need to be tweaked so that OpenVPN can correctly route traffic through the VPN. The first of these is IP forwarding, a method for determining where IP traffic should be routed. This is essential to the VPN functionality that your server will provide.
To adjust your OpenVPN server’s default IP forwarding setting, open the /etc/sysctl.conf
file using vi
or your preferred editor:
Code Block |
---|
sudo vi /etc/sysctl.conf |
Then add the following line at the top of the file:
Code Block |
---|
net.ipv4.ip_forward = 1 |
Save and close the file when you are finished.
To read the file and load the new values for the current session, type:
Code Block |
---|
sudo sysctl -p
net.ipv4.ip_forward = 1 |
Now your OpenVPN server will be able to forward incoming traffic from one ethernet device to another. This setting makes sure the server can direct traffic from clients that connect on the virtual VPN interface out over its other physical ethernet devices. This configuration will route all web traffic from your client via your server’s IP address, and your client’s public IP address will effectively be hidden.
In the next step you will need to configure some firewall rules to ensure that traffic to and from your OpenVPN server flows properly.
Firewall Configuration
So far, you’ve installed OpenVPN on your server, configured it, and generated the keys and certificates needed for your client to access the VPN. However, you have not yet provided OpenVPN with any instructions on where to send incoming web traffic from clients. You can stipulate how the server should handle client traffic by establishing some firewall rules and routing configurations.
Assuming you followed the prerequisites at the start of this tutorial, you should already have firewalld
installed and running on your server. To allow OpenVPN through the firewall, you’ll need to know what your active firewalld
zone is. Find this with the following command:
Code Block |
---|
sudo firewall-cmd --get-active-zones
docker
interfaces: docker0
public
interfaces: eth1 eth0 |
If you do not see a trusted
zone that lists the tun0
interface, run the following commands to add the VPN device to that zone:
Code Block |
---|
sudo firewall-cmd --zone=trusted --add-interface=tun0
sudo firewall-cmd --permanent --zone=trusted --add-interface=tun0 |
Next, add the openvpn
service to the list of services allowed by firewalld
within your active zone, and then make that setting permanent by running the command again but with the --permanent
option added:
Code Block |
---|
sudo firewall-cmd --permanent --add-service openvpn
sudo firewall-cmd --permanent --zone=trusted --add-service openvpn |
To apply the changes on the firewall, run:
Code Block |
---|
sudo firewall-cmd --reload |
You can now check that the service was added correctly with the following command:
Code Block |
---|
sudo firewall-cmd --list-services --zone=trusted
openvpn |
Next, we’ll add a masquerade rule to the firewall. Masquerading allows your OpenVPN server to translate your OpenVPN clients’ addresses into the server’s own public address, and then do the reverse with traffic that is sent back to clients. This process is also known as Network Address Translation (NAT).
Add masquerade rules with the following commands:
Code Block |
---|
sudo firewall-cmd --add-masquerade
sudo firewall-cmd --add-masquerade --permanent |
You can check that the masquerade was added correctly with this command:
Code Block |
---|
sudo firewall-cmd --query-masquerade
yes |
Next, you’ll need to create the specific masquerade rule for your OpenVPN subnet only. You can do this by first creating a shell variable (DEVICE
in our example) which will represent the primary network interface used by your server, and then using that variable to permanently add the routing rule:
Code Block |
---|
DEVICE=$(ip route | awk '/^default via/ {print $5}')
sudo firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o $DEVICE -j MASQUERADE |
Be sure to reload firewalld
so that all your changes take effect:
Code Block |
---|
sudo firewall-cmd --reload |
The commands with the --permanent
flag will ensure that the rules will persist across reboots. The firewall-cmd --reload
command makes sure that all the outstanding changes to the firewall are applied. With the firewall rules in place, we can start the OpenVPN service on the server.
Starting OpenVPN
OpenVPN runs as a systemd service, so we can use systemctl
for managing it. We will configure OpenVPN to start up at boot so you can connect to your VPN at any time as long as your server is running. To do this, enable the OpenVPN service by adding it to systemctl
:
Code Block |
---|
sudo systemctl -f enable openvpn-server@server.service |
Then start the OpenVPN service:
Code Block |
---|
sudo systemctl start openvpn-server@server.service |
Double check that the OpenVPN service is active with the following command. You should see active (running)
in the output:
Code Block |
---|
sudo systemctl -f enable openvpn-server@server.service
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-server@server.service → /usr/lib/systemd/system/openvpn-server@.service.
[mtb@sierra easy-rsa]$ sudo systemctl start openvpn-server@server.service
[mtb@sierra easy-rsa]$ sudo systemctl status openvpn-server@server.service
● openvpn-server@server.service - OpenVPN service for server
Loaded: loaded (/usr/lib/systemd/system/openvpn-server@.service; enabled; vendor prese>
Active: active (running) since Mon 2022-07-25 09:37:32 UTC; 25s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 2127755 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 49268)
Memory: 1.0M
CGroup: /system.slice/system-openvpn\x2dserver.slice/openvpn-server@server.service
└─2127755 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --s>
Jul 25 09:37:32 sierra openvpn[2127755]: Could not determine IPv4/IPv6 protocol. Using AF>
Jul 25 09:37:32 sierra openvpn[2127755]: Socket Buffers: R=[212992->212992] S=[212992->21>
Jul 25 09:37:32 sierra openvpn[2127755]: UDPv4 link local (bound): [AF_INET][undef]:1194
Jul 25 09:37:32 sierra openvpn[2127755]: UDPv4 link remote: [AF_UNSPEC]
Jul 25 09:37:32 sierra openvpn[2127755]: GID set to nobody
Jul 25 09:37:32 sierra openvpn[2127755]: UID set to nobody
Jul 25 09:37:32 sierra openvpn[2127755]: MULTI: multi_init called, r=256 v=256
Jul 25 09:37:32 sierra openvpn[2127755]: IFCONFIG POOL: base=10.8.0.4 size=62, ipv6=0
Jul 25 09:37:32 sierra openvpn[2127755]: IFCONFIG POOL LIST
Jul 25 09:37:32 sierra openvpn[2127755]: Initialization Sequence Completed
lines 1-23/23 (END) |
We’ve now completed the server-side configuration for OpenVPN. Next, you will configure your client machine and connect to the OpenVPN Server.
Creating the Client Configuration Infrastructure
Creating configuration files for OpenVPN clients can be somewhat involved, as every client must have its own config and each must align with the settings outlined in the server’s configuration file. Rather than writing a single configuration file that can only be used on one client, this step outlines a process for building a client configuration infrastructure which you can use to generate config files on-the-fly. You will first create a “base” configuration file then build a script which will allow you to generate unique client config files, certificates, and keys as needed.
Get started by creating a new directory where you will store client configuration files within the client-configs
directory you created earlier:
Code Block |
---|
mkdir -p ~/client-configs/files |
Next, copy an example client configuration file into the client-configs
directory to use as your base configuration:
Code Block |
---|
cp /usr/share/doc/openvpn/sample/sample-config-files/client.conf ~/client-configs/base.conf |
Open this new file using vi
or your preferred text editor:
Code Block |
---|
vi ~/client-configs/base.conf |
Inside, locate the remote
directive. This points the client to your OpenVPN server address — the public IP address of your OpenVPN server. If you decided to change the port that the OpenVPN server is listening on, you will also need to change 1194
to the port you selected:
Code Block |
---|
. . .
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote your_server_ip 1194
. . . |
Be sure that the protocol matches the value you are using in the server configuration:
Code Block |
---|
proto udp |
Next, uncomment the user
and group
directives by removing the ;
sign at the beginning of each line:
Code Block |
---|
# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody |
Find the directives that set the ca
, cert
, and key
. Comment out these directives since you will add the certs and keys within the file itself shortly:
Code Block |
---|
# 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 |
Similarly, comment out the tls-auth
directive, as you will add ta.key
directly into the client configuration file (and the server is set up to use tls-crypt
):
Code Block |
---|
# If a tls-auth key is used on the server
# then every client must also have the key.
;tls-auth ta.key 1 |
Mirror the cipher
and auth
settings that you set in the /etc/openvpn/server/server.conf
file:
Code Block |
---|
cipher AES-256-GCM
auth SHA256 |
Next, add the key-direction
directive somewhere in the file. You must set this to “1” for the VPN to function correctly on the client machine:
Code Block |
---|
key-direction 1 |
Finally, add a few commented out lines. Although you can include these directives in every client configuration file, you only need to enable them for Linux clients that ship with an /etc/openvpn/update-resolv-conf
file. This script uses the resolvconf
utility to update DNS information for Linux clients.
Code Block |
---|
; script-security 2
; up /etc/openvpn/update-resolv-conf
; down /etc/openvpn/update-resolv-conf |
If your client is running Linux and has an /etc/openvpn/update-resolv-conf
file, uncomment these lines from the client’s configuration file after it has been generated.
Save and close the file when you are finished.
Next, we’ll create a script that will compile your base configuration with the relevant certificate, key, and encryption files and then place the generated configuration in the ~/client-configs/files
directory. Open a new file called make_config.sh
within the ~/client-configs
directory:
Code Block |
---|
vi ~/client-configs/make_config.sh |
Inside, add the following content:
Code Block |
---|
#!/bin/bash
# First argument: Client identifier
KEY_DIR=~/client-configs/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-crypt>') \
${KEY_DIR}/ta.key \
<(echo -e '</tls-crypt>') \
> ${OUTPUT_DIR}/${1}.ovpn |
Save and close the file when you are finished.
Before moving on, be sure to mark this file as executable by typing:
Code Block |
---|
chmod 700 ~/client-configs/make_config.sh |
This script will make a copy of the base.conf
file you made, collect all the certificate and key files you’ve created for your client, extract their contents, append them to the copy of the base configuration file, and export all of this content into a new client configuration file. This means that, rather than having to manage the client’s configuration, certificate, and key files separately, all the required information is stored in one place. The benefit of using this method is that if you ever need to add a client in the future, you can run this script to quickly create a new config file and ensure that all the important information is stored in a single, easy-to-access location.
Please note that any time you add a new client, you will need to generate new keys and certificates for it before you can run this script and generate its configuration file. You will get some practice using this script in the next step.
Generating Client Configurations
If you followed along with the guide, you created a client certificate and key named foxtrot.crt
and foxtrot.key
, respectively, in Step 6. You can generate a config file for these credentials by moving into your ~/client-configs
directory and running the script you made at the end of the previous step:
Code Block |
---|
cd ~/client-configs
./make_config.sh foxtrot |
This will create a file named foxtrot.ovpn
in your ~/client-configs/files
directory:
Code Block |
---|
ls files
foxtrot.ovpn |
You need to transfer this file to the device you plan to use as the client.
Installing the Client Configuration
This section covers how to install a client VPN profile on macOS, Linux, and iOS, and Android. None of these client instructions are dependent on one another, so feel free to skip to whichever is applicable to your device.
The OpenVPN connection will have the same name as whatever you called the .ovpn
file. In regards to this tutorial, this means that the connection is named foxtrot.ovpn
, aligning with the first client file you generated.
macOS
Installing
Tunnelblick is a free, open source OpenVPN client for macOS. You can download the latest disk image from the Tunnelblick Downloads page. Double-click the downloaded .dmg
file and follow the prompts to install.
Towards the end of the installation process, Tunnelblick will ask if you have any configuration files. Answer I have configuration files and let Tunnelblick finish. Open a Finder window and double-click foxtrot.ovpn
. Tunnelblick will install the client profile. Administrative privileges are required.
Connecting
Launch Tunnelblick by double-clicking the Tunnelblick icon in the Applications folder. Once Tunnelblick has been launched, there will be a Tunnelblick icon in the menu bar at the top right of the screen for controlling connections. Click on the icon, and then the Connect client1 menu item to initiate the VPN connection.
Linux
Installing
If you are using Linux, there are a variety of tools that you can use depending on your distribution. Your desktop environment or window manager might also include connection utilities.
The most universal way of connecting, however, is to just use the OpenVPN software.
On Ubuntu or Debian, you can install it just as you did on the server by typing:
Code Block |
---|
sudo apt update
sudo apt install openvpn |
Copy
On CentOS you can enable the EPEL repositories and then install it by typing:
Code Block |
---|
sudo yum install epel-release
sudo yum install openvpn |
Copy
Configuring
Check to see if your distribution includes an /etc/openvpn/update-resolv-conf
script:
Code Block |
---|
ls /etc/openvpn |
Copy
Code Block |
---|
Outputupdate-resolv-conf |
Next, edit the OpenVPN client configuration file you transfered:
Code Block |
---|
vi client1.ovpn |
Copy
If you were able to find an update-resolv-conf
file, uncomment the three lines you added to adjust the DNS settings:
client1.ovpn
Code Block |
---|
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf |
If you are using CentOS, change the group
directive from nogroup
to nobody
to match the distribution’s available groups:
client1.ovpn
Code Block |
---|
group nobody |
Save and close the file.
Now, you can connect to the VPN by just pointing the openvpn
command to the client configuration file:
Code Block |
---|
sudo openvpn --config foxtrot.ovpn |
Copy
This should connect you to your VPN.
Automatic client start
To ensure that OVPN starts on boot with the proper configuration, move the foxtrot.ovpn
file to /etc/openvpn/client/client.conf and make sure the permissions are set to 600 and owned by root.
Raspberry Pi
How to have an OpenVPN client connect on system Startup. How to set up a persistant OpenVPN client connection on Raspian.
Ensure *.conf file is located in /etc/openvpn/
*.ovpn files will not work, they will need to be renamed to *.conf.
Renaming a ovpen file to conf is ok and does work.
Edit /etc/default/openvpn
Ensure a similar line below exist.
Ensure the value does not have an extension.
Ensure the value matches the certificate name.
AUTOSTART=”ClientName”
Example: Lets say there is a client certificate called LocationB and the config/settings file is called LocationB.ovpn.
Copy LocationB.ovpn into /etc/openvpn/LocationB.conf
Then add a line into /etc/default/openvpn
AUTOSTART=”LocationB”
Client Fixed IP addresses
OpenVPN clients will be assigned a dynamic IP address when connecting unless we force a static configuration.
OpenVPN has the ability to assign clients specific IP addresses from the IP pool defined. To achieve this, it uses three types of client IP address selection algorithms. These include, in the order in which they are used;
Use of
--client-connect script
. This involves execution of the specified script that generates file containing static IP addresses on the server when a client connects. This method is usually the first choice to be considered.Use of
--client-config-dir
. This involves the use of a file which contains static IP addresses for the clients as per their client certificate common name (CN) (second choice).Use of
--ifconfig-pool
for the allocation for dynamic IP (last choice).
For more information, consult man openvpn
.
In this guide, we are going to use the second option, where by we will configure our OpenVPN server to read a specific file, that contains the client common names and mapped IP addresses. This ensures that, a connecting client is assigned static IP address based on the common name defined on their client certificate.
Create a File to Store Static IP addresses
The use of the client-config-dir
option, requires that the static IP addresses to be assigned to connecting clients be stored in a file that can be read by OpenVPN server.
Therefore, open the OpenVPN server configuration file, /etc/openvpn/server/server.conf
, and set your path to static IP assignment file as the value for the client-config-dir
parameter.
Code Block |
---|
vi /etc/openvpn/server/server.conf |
Code Block |
---|
...
# EXAMPLE: Suppose you want to give
# Thelonious a fixed VPN IP address of 10.9.0.1.
# First uncomment out these lines:
client-config-dir /etc/openvpn/ccd
... |
In this demo, we set the path to store static/fixed IP addresses assignment file to, /etc/openvpn/ccd
.
Code Block |
---|
mkdir /etc/openvpn/ccd
chown root:openvpn /etc/openvpn/ccd
chmod 750 /etc/openvpn/ccd |
Assign Static IP Addresses to OpenVPN Clients
For every OpenVPN client that you want to assign static IP address to, you need to extract the common name from that specific client certificate.
In our demo, we have the OpenVPN client jujitsu. To extract the common names from the clients certificate, use openssl
command as shown below. Be sure to replace the clients certificates.
Code Block |
---|
openssl x509 -subject -noout -in ~/client-configs/keys/jujitsu.crt |
Code Block |
---|
subject=CN = jujitsu |
Once you have the common name for the client, you can then assign static IP addresses using the ifconfig-push
option. For example, to assign the client using the certificate with jujitsu
as common name an IP address, 10.8.0.50
, this is how the assignment is done;
Code Block |
---|
echo "ifconfig-push 10.8.0.50 255.255.255.0" > /etc/openvpn/ccd/jujitsu |
Set the proper file permissions:
Code Block |
---|
chown root:openvpn /etc/openvpn/ccd/*
chmod 640 /etc/openvpn/ccd/* |
Note that, how you assign the static IP addresses depends on the topology you configured your OpenVPN server. In our, case, we set the topology to subnet;
Code Block |
---|
# Network topology
...
topology subnet |
Restart OpenVPN Server;
Code Block |
---|
systemctl restart openvpn-server@server |
Be sure to always check the logs;
Code Block |
---|
tail -f /var/log/openvpn/openvpn.log |
And if none of that works…edit this file:
Code Block |
---|
/etc/openvpn/server/ipp.txt |