A virtual private network (VPN) is a protocol used to add security and privacy to private and public networks. VPNs send traffic between two or more devices on a network in an encrypted tunnel. Once a VPN connection is made, all of the network traffic is encrypted on the client’s end. VPNs mask your IP address so that your online actions are virtually untraceable.

It provides encryption and anonymity, and protects your online activities, online shopping, sending emails, and also helps to keep your Web browsing anonymous.

In this tutorial, we will show you how to install and configure the OpenVPN server and Client on Debian 10 server.

Getting Started

Before starting, it is a good idea to update your system’s packages to the latest version.

Run the following command to update and upgrade your system’s packages:

apt-get update -y
apt-get upgrade -y

Once your system is up-to-date, you can proceed to the next step.

Step 1 – Enable IP Forwarding

Next, you will need to enable IP forwarding in your system. IP forwarding allows your operating system to accept the incoming network packets and forward it to the other network if the destination is on another network.

To enable the IP forwarding, edit the file /etc/sysctl.conf:

nano /etc/sysctl.conf

Add the following line:

net.ipv4.ip_forward = 1

Save the file when you are finished. Then, run the following command to apply the changes:

sysctl -p

Step 2 – Install OpenVPN Server

By default, the OpenVPN package is available in the Debian 10 default repository. You can install it with the following command:

apt-get install openvpn -y

Once the installation has been completed, you will also need to copy the easy-rsa directory for managing SSL certificates.

Run the following command to copy easy-rsa directory from /usr/share directory to /etc/openvpn directory.

cp -r /usr/share/easy-rsa /etc/openvpn/

Step 3 – Setup Certificate Authority

Easy RSA uses a set of scripts to generate keys and certificates. First, you will need to configure the Certificate Authority on your system.

To do so, change the directory to /etc/openvpn/easy-rsa and create a new Easy RSA’s configuration file:

cd /etc/openvpn/easy-rsa
nano vars

Add the following lines including your country, city, and preferred email address:

set_var EASYRSA                 "$PWD"
set_var EASYRSA_PKI             "$EASYRSA/pki"
set_var EASYRSA_DN              "cn_only"
set_var EASYRSA_REQ_COUNTRY     "INDIA"
set_var EASYRSA_REQ_PROVINCE    "Gujrat"
set_var EASYRSA_REQ_CITY        "Ahmedabad"
set_var EASYRSA_REQ_ORG         "Tecadmin CERTIFICATE AUTHORITY"
set_var EASYRSA_REQ_EMAIL	"[email protected]"
set_var EASYRSA_REQ_OU          "Tecadmin EASY CA"
set_var EASYRSA_KEY_SIZE        2048
set_var EASYRSA_ALGO            rsa
set_var EASYRSA_CA_EXPIRE	7500
set_var EASYRSA_CERT_EXPIRE     365
set_var EASYRSA_NS_SUPPORT	"no"
set_var EASYRSA_NS_COMMENT	"Tecadmin CERTIFICATE AUTHORITY"
set_var EASYRSA_EXT_DIR         "$EASYRSA/x509-types"
set_var EASYRSA_SSL_CONF        "$EASYRSA/openssl-easyrsa.cnf"
set_var EASYRSA_DIGEST          "sha256"

Save the file when you are finished.

Next, run the following command to initiate the PKI directory.

./easyrsa init-pki

Output:

Note: using Easy-RSA configuration from: ./vars

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

Next, build the CA certificates with the following command:

./easyrsa build-ca

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019

Enter New CA Key Passphrase: 
Re-Enter New CA Key Passphrase: 
Generating RSA private key, 2048 bit long modulus (2 primes)
....................................................................     
..........................................................................................................................................     
e is 65537 (0x010001)
Can't load /etc/openvpn/easy-rsa/pki/.rnd into RNG
140218549745472:error:2406F079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:98:Filename=/etc/openvpn/easy-rsa/pki/.rnd
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]:

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

The above command will generate two files named ca.key and ca.crt. These certificates will be used to sign your server and clients’ certificates.

Step 4 – Generate Server Certificate Files

Next, you will need to generate a keypair and certificate request for your server.

Run the following command to generate the server key named tecadmin-server:

./easyrsa gen-req tecadmin-server nopass

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
Generating a RSA private key
...........................     
...............................................................................................................................................................................................................................................................................................     
writing new private key to '/etc/openvpn/easy-rsa/pki/private/tecadmin-server.key.kOlBTwtY6a'
-----
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) [tecadmin-server]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/tecadmin-server.req
key: /etc/openvpn/easy-rsa/pki/private/tecadmin-server.key

Step 5 – Sign the Server Key Using CA

Next, you will need to sign the tecadmin-server key using your CA certificate:

Run the following command to sign the server key:

./easyrsa sign-req server tecadmin-server

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019

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 365 days:

subject=
    commonName                = tecadmin-server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/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:'tecadmin-server'
Certificate is to be certified until Feb 16 05:00:50 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/tecadmin-server.crt

Next, verify the generated certificate file with the following command:

openssl verify -CAfile pki/ca.crt pki/issued/tecadmin-server.crt 

If everything is fine, you should get the following output:

pki/issued/tecadmin-server.crt: OK

Next, run the following command to generate a strong Diffie-Hellman key to use for the key exchange:

./easyrsa gen-dh

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
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 /etc/openvpn/easy-rsa/pki/dh.pem

After creating all certificate files, copy them to the /etc/openvpn/server/ directory:

cp pki/ca.crt /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp pki/private/tecadmin-server.key /etc/openvpn/server/
cp pki/issued/tecadmin-server.crt /etc/openvpn/server/

Step 6 – Generate Client Certificate and Key File

Next, you will need to generate the key and certificate file for the client.

First, run the following command to build the client key file:

./easyrsa gen-req client nopass

You should see the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
Generating a RSA private key
......................................................     
...     
writing new private key to '/etc/openvpn/easy-rsa/pki/private/client.key.e38GUtzHie'
-----
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) [client]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/client.req
key: /etc/openvpn/easy-rsa/pki/private/client.key

Next, sign the client key using your CA certificate:

./easyrsa sign-req client client

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019


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 365 days:

subject=
    commonName                = client


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/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:'client'
Certificate is to be certified until Feb 16 05:11:19 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/client.crt

Next, copy all client certificate and key file to the /etc/openvpn/client/ directory:

cp pki/ca.crt /etc/openvpn/client/
cp pki/issued/client.crt /etc/openvpn/client/
cp pki/private/client.key /etc/openvpn/client/

Step 7 – Configure OpenVPN Server

Next, create a new OpenVPN configuration file inside /etc/openvpn/ directory:

nano /etc/openvpn/server.conf

Add the following lines:

port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/tecadmin-server.crt
key /etc/openvpn/server/tecadmin-server.key
dh /etc/openvpn/server/dh.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1"

push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
duplicate-cn
cipher AES-256-CBC
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
auth SHA512
auth-nocache
keepalive 20 60
persist-key
persist-tun
compress lz4
daemon
user nobody
group nogroup
log-append /var/log/openvpn.log
verb 3

Save the file when you are finished.

Step 8 – Start OpenVPN Service

OpenVPN is now installed and configured. You can now start the OpenVPN service and enable it to start after the system reboot using the following command:

systemctl start [email protected]
systemctl enable [email protected]

Run the following command to verify the status of OpenVPN service:

systemctl status [email protected]

You should get the following output:

[email protected] - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2020-02-21 15:38:31 UTC; 4s ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
 Main PID: 3044 (openvpn)
   Status: "Initialization Sequence Completed"
    Tasks: 1 (limit: 2359)
   Memory: 1.3M
   CGroup: /system.slice/system-openvpn.slice/[email protected]
           └─3044 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --config /etc/openvpn/server.

Feb 21 15:38:31 debian10 systemd[1]: Starting OpenVPN connection to server...
Feb 21 15:38:31 debian10 systemd[1]: Started OpenVPN connection to server.

Once the OpenVPN service started successfully, it will create a new network interface named tun0. You can check it with the following command:

ip a show tun0

You should get the new interface tun0 in the following output:

59: tun0:  mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::90:e3c0:5f1a:27f5/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

Step 9 – Generate Client Configuration

Next, create a new OpenVPN client configuration file named client.ovpn. You will require this file to connect your OpenVPN server from the client system.

nano /etc/openvpn/client/client.ovpn

Add the following lines:

client
dev tun
proto udp
remote vpn-server-ip 1194
ca ca.crt
cert client.crt
key client.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

Save the file when you are finished.

Step 10 – Configure Routing using UFW

By default, the UFW firewall is not installed in Debian 10. You can install it with the following command:

apt-get install ufw -y

After installing the UFW firewall, you will need to add firewall rules to enable masquerading so that your VPN clients access to the Internet.

First, you will need to configure UFW to accept the forwarded packets. You can do it by editing the file /etc/default/ufw:

nano /etc/default/ufw

Change the following line:

DEFAULT_FORWARD_POLICY="ACCEPT"

Save and close the file. Then, open the /etc/ufw/before.rules file:

nano /etc/ufw/before.rules

Add the following lines at the end of the file:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/16 -o ens3 -j MASQUERADE
COMMIT

Save the file when you are finished.

Note: Replace ens3 with the name of your public network interface.

Next, allow the default OpenVPN port 1194 and OpenSSH with the following command:

ufw allow 1194/udp
ufw allow OpenSSH

Next, reload the UFW firewall using the following command:

ufw disable
ufw enable

Step 11 – Connect OpenVPN from Client

First, log in to the client machine and install the OpenVPN package with the following command:

apt-get install openvpn -y

Next, you will need to download the OpenVPN client configuration files from the OpenVPN server to the client machine.

On the client machine, run the following command to download all the client configuration file:

scp -r [email protected]:/etc/openvpn/client .

Once downloaded, change the directory to the client and run the following command to connect to the OpenVPN server:

cd client
openvpn --config client.ovpn

You should see the following output:

Fri Feb 21 15:39:18 2020 TCP/UDP: Preserving recently used remote address: [AF_INET]69.87.218.145:1194
Fri Feb 21 15:39:18 2020 Socket Buffers: R=[212992->212992] S=[212992->212992]
Fri Feb 21 15:39:18 2020 UDP link local: (not bound)
Fri Feb 21 15:39:18 2020 UDP link remote: [AF_INET]69.87.218.145:1194
Fri Feb 21 15:39:18 2020 TLS: Initial packet from [AF_INET]69.87.218.145:1194, sid=6d27e1cb 524bd8cd
Fri Feb 21 15:39:18 2020 VERIFY OK: depth=1, CN=Easy-RSA CA
Fri Feb 21 15:39:18 2020 VERIFY OK: depth=0, CN=tecadmin-server
Fri Feb 21 15:39:18 2020 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA
Fri Feb 21 15:39:18 2020 [tecadmin-server] Peer Connection Initiated with [AF_INET]69.87.218.145:1194
Fri Feb 21 15:39:19 2020 SENT CONTROL [tecadmin-server]: 'PUSH_REQUEST' (status=1)
Fri Feb 21 15:39:19 2020 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology net30,ping 20,ping-restart 60,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
Fri Feb 21 15:39:19 2020 OPTIONS IMPORT: timers and/or timeouts modified
Fri Feb 21 15:39:19 2020 OPTIONS IMPORT: --ifconfig/up options modified
Fri Feb 21 15:39:19 2020 OPTIONS IMPORT: route options modified

After a successfull connection, OpenVPN will assign an IP address to your system. You can check it with the following command:

ip a show tun0

Output:

4: tun0:  mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::7226:57b1:f101:313b/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

You can also check the OpenVPN server log to verify the connection status:

tail -f /var/log/openvpn.log 

You should see the following output:

Fri Feb 21 15:39:18 2020 45.58.34.83:37445 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA
Fri Feb 21 15:39:18 2020 45.58.34.83:37445 [client] Peer Connection Initiated with [AF_INET]45.58.34.83:37445
Fri Feb 21 15:39:18 2020 client/45.58.34.83:37445 MULTI_sva: pool returned IPv4=10.8.0.6, IPv6=(Not enabled)
Fri Feb 21 15:39:18 2020 client/45.58.34.83:37445 MULTI: Learn: 10.8.0.6 -> client/45.58.34.83:37445
Fri Feb 21 15:39:18 2020 client/45.58.34.83:37445 MULTI: primary virtual IP for client/45.58.34.83:37445: 10.8.0.6
Fri Feb 21 15:39:19 2020 client/45.58.34.83:37445 PUSH: Received control message: 'PUSH_REQUEST'
Fri Feb 21 15:39:19 2020 client/45.58.34.83:37445 SENT CONTROL [client]: 'PUSH_REPLY,redirect-gateway def1,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology net30,ping 20,ping-restart 60,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM' (status=1)
Fri Feb 21 15:39:19 2020 client/45.58.34.83:37445 Data Channel: using negotiated cipher 'AES-256-GCM'
Fri Feb 21 15:39:19 2020 client/45.58.34.83:37445 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Fri Feb 21 15:39:19 2020 client/45.58.34.83:37445 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key

Conclusion

Congratulations! you have successfully installed and configured the OpenVPN server and Client on Debian 10 server. You can now access the internet securely and protect your identity.