To the top

Open VPN on Ubuntu

VPN

OpenVPN is a Virtual Private Networking (VPN) solution provided in the Ubuntu Repositories. It is flexible, reliable and secure. It belongs to the family of SSL/TLS VPN stacks (different from IPSec VPNs). This chapter will cover installing and configuring OpenVPN to create a VPN.

Tutorial:

1. | Install Open VPN with bash script | 2. | The installation script |

OpenVPN

openVPN

If you want more than just pre-shared keys OpenVPN makes it easy to set up a Public Key Infrastructure (PKI) to use SSL/TLS certificates for authentication and key exchange between the VPN server and clients. OpenVPN can be used in a routed or bridged VPN mode and can be configured to use either UDP or TCP. The port number can be configured as well, but port 1194 is the official one; this single port is used for all communication. VPN client implementations are available for almost anything including all Linux distributions, OS X, Windows and OpenWRT based WLAN routers.

Server Installation

To install openvpn in a terminal enter:

$ sudo apt install openvpn easy-rsa

Public Key Infrastructure Setup

The first step in building an OpenVPN configuration is to establish a PKI (public key infrastructure). The PKI consists of:

  • a separate certificate (also known as a public key) and private key for the server and each client.
  • a master Certificate Authority (CA) certificate and key, used to sign the server and client certificates.

OpenVPN supports bidirectional authentication based on certificates, meaning that the client must authenticate the server certificate and the server must authenticate the client certificate before mutual trust is established.

Both server and client will authenticate the other by first verifying that the presented certificate was signed by the master certificate authority (CA), and then by testing information in the now-authenticated certificate header, such as the certificate common name or certificate type (client or server).

Certificate Authority Setup

To setup your own Certificate Authority (CA) and generate certificates and keys for an OpenVPN server and multiple clients first copy the easy-rsa directory to /etc/openvpn. This will ensure that any changes to the scripts will not be lost when the package is updated. From a terminal, run:

$ sudo make-cadir /etc/openvpn/easy-rsa

As root user (run: $ sudo -i) change to the newly created directory /etc/openvpn/easy-rsa and run:

# ./easyrsa init-pki

# ./easyrsa build-ca

Server Keys and Certificates

Next, we will generate a key pair for the server:

# ./easyrsa gen-req myservername nopass

Diffie Hellman parameters must be generated for the OpenVPN server. The following will place them in pki/dh.pem:

# ./easyrsa gen-dh

And finally a certificate for the server:

# ./easyrsa gen-req myservername nopass

# ./easyrsa sign-req server myservername

All certificates and keys have been generated in subdirectories. Common practice is to copy them to /etc/openvpn/:

certificates

Client Certificates

The VPN client will also need a certificate to authenticate itself to the server. Usually you create a different certificate for each client.

This can either be done on the server (as the keys and certificates above) and then securely distributed to the client. Or vice versa: the client can generate and submit a request that is sent and signed by the server.

To create the certificate, enter the following in a terminal while being user root:

# ./easyrsa gen-req myclient1 nopass

# ./easyrsa sign-req client myclient1

afterwards copy the following files to the client using a secure method:

  • pki/ca.crt
  • pki/issued/myclient1.crt

As the client certificates and keys are only required on the client machine, you can remove them from the server.

Simple Server Configuration

Along with your OpenVPN installation you got these sample config files (and many more if you check):

# ls -l /usr/share/doc/openvpn/examples/sample-config-files/

Start with copying and unpacking server.conf.gz to /etc/openvpn/server.conf.

Edit /etc/openvpn/myserver.conf to make sure the following lines are pointing to the certificates and keys you created in the section above.

  • ca ca.crt
  • cert myservername.crt
  • key myservername.key
  • dh dh.pem

Complete this set with a ta key in etc/openvpn for tls-auth like:

# openvpn --genkey --secret ta.key

Edit /etc/sysctl.conf and uncomment (= remove the # from start of the line) the following line to enable IP forwarding:

#net.ipv4.ip_forward=1

Then reload sysctl.

# sysctl -p /etc/sysctl.conf

Exit from root privileges:

# exit

$

That is the minimum you have to configure to get a working OpenVPN server. You can use all the default settings in the sample server.conf file. Now start the server (command: openvpn@CONFIGFILENAME).

$ sudo systemctl start openvpn@myserver

You will find logging and error messages in the journal. For example, if you started a templatized service openvpn@server you can filter for this particular message source with:

$ sudo journalctl -u openvpn@myserver -xe

The same templatized approach works for all of systemctl:

$ sudo systemctl status openvpn@myserver

openvpn@myserver.service - OpenVPN connection to myserver
Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
Active: active (running) since Thu 2021-10-20 11:15:15 UTC; 10s ago
	Docs: man:openvpn(8)
		https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
		https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 4138 (openvpn)
Status: "Initialization Sequence Completed"
	Tasks: 1 (limit: 533)
Memory: 1.0M
CGroup: /system.slice/system-openvpn.slice/openvpn@myserver.service
		└─4138 /usr/sbin/openvpn --daemon ovpn-myserver --status /run/openvpn/myserver.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/myserver.conf --writepid /run/

Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: /sbin/ip addr add dev tun0 local 10.8.0.1 peer 10.8.0.2
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: /sbin/ip route add 10.8.0.0/24 via 10.8.0.2
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: Could not determine IPv4/IPv6 protocol. Using AF_INET
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: Socket Buffers: R=[212992->212992] S=[212992->212992]
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: UDPv4 link local (bound): [AF_INET][undef]:1194
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: UDPv4 link remote: [AF_UNSPEC]
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: MULTI: multi_init called, r=256 v=256
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: IFCONFIG POOL: base=10.8.0.4 size=62, ipv6=0
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: IFCONFIG POOL LIST
Oct 20 11:15:16 eoan-vpn-server ovpn-myserver[4138]: Initialization Sequence Completed
						

Now check if OpenVPN created a tun0 interface:

$ sudo ip addr show dev tun0

5: tun0:  mtu 1500 qdisc fq_codel 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::b5ac:7829:f31e:32c5/64 scope link stable-privacy 
		valid_lft forever preferred_lft forever
						

Client Installation

There are various different OpenVPN client implementations with and without GUIs. For now we use commandline/service based OpenVPN client for Ubuntu which is part of the very same package as the server. So you have to install the openvpn package again on the client machine:

$ sudo apt install openvpn

Simple Client Configuration

This time copy the client.conf sample config file to /etc/openvpn/:

Copy the following client keys and certificate files you created in the section above to e.g. /etc/openvpn/ and edit /etc/openvpn/client.conf to make sure the following lines are pointing to those files.

  • ca ca.crt
  • cert myclient1.crt
  • key myclient1.key
  • tls-auth ta.key 1

And you have to specify the OpenVPN server name or address. Make sure the keyword client is in the config. That’s what enables client mode.

  • client
  • remote vpnserver.example.com 1194

Now start the OpenVPN client with the same templatized mechanism:

$ sudo systemctl start openvpn@client

You can check status as you did on the server:

$ sudo systemctl status openvpn@client

openvpn@client.service - OpenVPN connection to client
Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
Active: active (running) since Thu 2021-10-20 12:22:15 UTC; 6s ago
	Docs: man:openvpn(8)
		https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
		https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 3616 (openvpn)
Status: "Initialization Sequence Completed"
	Tasks: 1 (limit: 533)
Memory: 1.3M
CGroup: /system.slice/system-openvpn.slice/openvpn@client.service
		└─3616 /usr/sbin/openvpn --daemon ovpn-client --status /run/openvpn/client.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/client.conf --writepid /run/openvp

Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: ROUTE_GATEWAY 192.168.122.1/255.255.255.0 IFACE=ens3 HWADDR=52:54:00:3c:5a:88
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: TUN/TAP device tun0 opened
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: TUN/TAP TX queue length set to 100
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: /sbin/ip link set dev tun0 up mtu 1500
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: /sbin/ip addr add dev tun0 local 10.8.0.6 peer 10.8.0.5
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: /sbin/ip route add 10.8.0.1/32 via 10.8.0.5
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Oct 20 12:22:16 eoan-vpn-client ovpn-client[3616]: Initialization Sequence Completed
					

And you can check on the client if it created a tun0 interface:

$ sudo ip addr show dev tun0

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::5a94:ae12:8901:5a75/64 scope link stable-privacy 
		valid_lft forever preferred_lft forever
					

Check if you can ping the OpenVPN server:

$ ping 10.8.0.1

PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.

64 bytes from 10.8.0.1: icmp_req=1 ttl=64 time=0.920 ms

Check if you can ping the OpenVPN server:

$ ip route

default via 192.168.122.1 dev ens3 proto dhcp src 192.168.122.114 metric 100

10.8.0.1 via 10.8.0.5 dev tun0

10.8.0.5 dev tun0 proto kernel scope link src 10.8.0.6

192.168.122.0/24 dev ens3 proto kernel scope link src 192.168.122.114

192.168.122.1 dev ens3 proto dhcp scope link src 192.168.122.114 metric 100