Tutorial on installing OpenVPN on Ubuntu server
Prerequisites
- Ubuntu or Debian Linux Server
- Root access
- IP Address – Find your IPv4 and IPv6 addresses.
- To view the system’s IP address, you can use the following command:
ip addr show dev eth0
In the command above,
eth0
is the name of the interface, which may be different on your Linux system.
How to set up and configure an OpenVPN Server on Ubuntu
We enter the following command to install the OpenVPN, IPTables, OpenSSL, and CA certificate bundles:
apt-get install openvpn iptables openssl ca-certificates -y
After the installation is complete, we need to download easy-rsa.
wget -O ~/easyrsa.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.6/EasyRSA-unix-v3.0.6.tgz 2>/dev/null || curl -Lo ~/easyrsa.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.6/EasyRSA-unix-v3.0.6.tgz
tar xzf ~/easyrsa.tgz -C ~/
mv ~/EasyRSA-v3.0.6/ /etc/openvpn/
mv /etc/openvpn/EasyRSA-v3.0.6/ /etc/openvpn/easy-rsa/
rm -f ~/easyrsa.tgz
After downloading easy-rsa, we must create the PKI and configure the CA and Server/Client certificates.
Note: Certificates expire in 3650 days (10 years); you can change this value. Note: You can change the name of the client certificate (CLIENT), but do not use special characters.
cd /etc/openvpn/easy-rsa/
./easyrsa init-pki
./easyrsa --batch build-ca nopass
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full CLIENT nopass
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
Now we move the certificates to the OpenVPN folder and change their owner and group permissions.
cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn
chown nobody:nogroup /etc/openvpn/crl.pem
After moving the certificates, we want to generate an authentication key using tls (tls-auth). After that, we need to create the DH parameters, and we will use the predefined group ffdhe2048
.
openvpn --genkey --secret /etc/openvpn/ta.key
DHE Groups: Defined DHE groups are recommended by the Internet Engineering Task Force (IETF) in RFC 7919. These groups are intended to be more resilient against attacks compared to randomly generated groups.
echo '-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----' > /etc/openvpn/dh.pem
Now it’s time to create the OpenVPN server configuration.
Server Configuration File
The settings you might want to change:
- port:
1194
(default) or443
- proto:
udp
(default) ortcp
Note: It’s best to change the port because OpenVPN port 1194 might be blocked. Furthermore, port 443 is ideal for preventing censorship. Note: The UDP protocol offers better performance than the TCP protocol, but it is not as reliable.
nano /etc/openvpn/server.conf
Add the following configuration:
port 1194
proto udp
dev tun
sndbuf 0
rcvbuf 0
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh.pem
auth SHA512
tls-auth /etc/openvpn/ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
local 116.203.180.222 #Here you should add the server ipv4 address
ifconfig-pool-persist /etc/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
server-ipv6 2a01:4f8:c2c:5fc7:80::/112 #Here you should add the server ipv6 address
tun-ipv6
push tun-ipv6
ifconfig-ipv6 2a01:4f8:c2c:5fc7::1 2a01:4f8:c2c:5fc7::2 #Here you should add the server ipv6 address
push "route-ipv6 2a01:4f8:c2c:5fc7:2::/64" #Here you should add the server ipv6 address
push "route-ipv6 2000::/3"
DNS Configuration
Now it’s time for DNS. You should choose one of the following options:
- Use the Default System DNS
- Cloudflare DNS
- Google DNS
Default System DNS: To find your system’s DNS, use:
grep -v '#' /run/systemd/resolve/resolv.conf | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
The output should look similar to this (example from the original text):
213.133.98.98
213.133.99.99
213.133.100.100
After selecting the DNS provider, add them to the end of the file by entering the following command:
Apply the changes by adding the following lines (replace SELECTED-DNS-PROVIDER
with your chosen IP addresses):
push "dhcp-option DNS SELECTED-DNS-PROVIDER"
push "dhcp-option DNS SELECTED-DNS-PROVIDER"
The DNS is set up.
Continuing the Server Configuration
After finishing the DNS part, it’s time to continue the configuration.
nano /etc/openvpn/server.conf
Apply the following changes (add them to the end of the file):
keepalive 10 120
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
client-to-client
status /etc/openvpn/openvpn-status.log
verb 3
crl-verify /etc/openvpn/crl.pem
Adding Firewall Rules
Now we must add firewall rules.
Using Firewalld
If you are using Firewalld, add the following codes:
# We are not going to use --add-service=openvpn because that would only work with default port and protocol
firewall-cmd --zone=public --add-port=1194/udp
firewall-cmd --zone=trusted --add-source=10.8.0.0/24
firewall-cmd --permanent --zone=public --add-port=1194/udp
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
# Set NAT for the VPN subnet
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to SERVER_IP
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to SERVER_IP
firewall-cmd --permanent --direct --add-rule ipv6 filter FORWARD_direct 0 -i tun0 -o eth0 -j ACCEPT
Using IPTables
If you are using iptables, enter the following codes:
iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
#Note: If you use tcp protocol you must change -p udp to -p tcp and --dport 1194 to --dport 443
iptables -A INPUT -i eth0 -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
#Note: If you use tcp protocol you must change -p udp to -p tcp and --dport 1194 to --dport 443
ip6tables -A INPUT -i eth0 -p udp --dport 1194 -j ACCEPT
ip6tables -A INPUT -i tun0 -j ACCEPT
ip6tables -A FORWARD -i tun0 -o eth0 -s 2a01:4f8:c2c:5fc7:80::/112 -m state --state NEW -j ACCEPT
Save IPTables:
iptables-save > /etc/iptables.rules
ip6tables-save > /etc/ip6tables.rules
Creating a Client Configuration File
Now we must create a client configuration file.
nano /etc/openvpn/client.txt
Copy and paste the entire configuration:
client
dev tun
proto udp
sndbuf 0
rcvbuf 0
tun-mtu 1500
mssfix 1420
remote 116.203.180.222 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512
auth-nocache
cipher AES-256-CBC
setenv opt block-outside-dns
key-direction 1
verb 3
Final OpenVPN Server Configuration Review
In the end, the OpenVPN server configuration (server.conf
) should look like this (with Cloudflare DNS as an example):
port 1194
proto udp
dev tun
sndbuf 0
rcvbuf 0
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh.pem
auth SHA512
tls-auth /etc/openvpn/ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
local 116.203.180.222 #Here you should add the server ipv4 address
ifconfig-pool-persist /etc/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 1.0.0.1"
#ipv6 support
server-ipv6 2a01:4f8:c2c:5fc7:80::/112 #Here you should add the server ipv6 address
tun-ipv6
push tun-ipv6
ifconfig-ipv6 2a01:4f8:c2c:5fc7::1 2a01:4f8:c2c:5fc7::2 #Here you should add the server ipv6 address
push "route-ipv6 2a01:4f8:c2c:5fc7:2::/64" #Here you should add the server ipv6 address
push "route-ipv6 2000::/3"
push "dhcp-option DNS 2606:4700:4700::1111"
push "dhcp-option DNS 2606:4700:4700::1001"
keepalive 10 120
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
client-to-client
status /etc/openvpn/openvpn-status.log
verb 3
crl-verify /etc/openvpn/crl.pem
Enabling Packet Forwarding
Some VPS instances have IPv4 / IPv6 packet forwarding disabled. To enable packet forwarding, you need to edit /etc/sysctl.conf
:
Find the following lines and uncomment them as shown below:
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
#net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.forwarding=1
Then, run the following command:
sysctl -p
Creating an OpenVPN User Manager
To add a new user, we are going to create a new script. This script has 2 options:
- Add a new user
- Remove an existing user
cd ~
nano openvpn-user-manager.sh
Copy and paste the following configuration:
#!/usr/bin/env bash
if readlink /proc/$$/exe | grep -q "dash"; then
echo "This script needs to be run with bash, not sh."
exit
fi
if [[ "$EUID" -ne 0 ]]; then
echo "Sorry, you need to run this as root"
exit
fi
newclient () {
# Generates the custom client.ovpn
cp /etc/openvpn/client.txt ~/$1.ovpn
echo "<ca>" >> ~/$1.ovpn
cat /etc/openvpn/easy-rsa/pki/ca.crt >> ~/$1.ovpn
echo "</ca>" >> ~/$1.ovpn
echo "<cert>" >> ~/$1.ovpn
sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/easy-rsa/pki/issued/$1.crt >> ~/$1.ovpn
echo "</cert>" >> ~/$1.ovpn
echo "<key>" >> ~/$1.ovpn
cat /etc/openvpn/easy-rsa/pki/private/$1.key >> ~/$1.ovpn
echo "</key>" >> ~/$1.ovpn
echo "<tls-auth>" >> ~/$1.ovpn
sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/ta.key >> ~/$1.ovpn
echo "</tls-auth>" >> ~/$1.ovpn
}
if [[ -e /etc/openvpn/server.conf ]]; then
while :
do
clear
echo ""
echo "What do you want to do?"
echo " 1) Add a new user"
echo " 2) Remove an existing user"
echo " 3) Exit"
read -p "Select an option [1-3]: " option
case $option in
1)
echo
echo "Please don't use special characters, only clear words."
read -p "Client name: " -e CLIENT
cd /etc/openvpn/easy-rsa/
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass
newclient "$CLIENT"
echo
echo "Client $CLIENT added, configuration is available at:" ~/"$CLIENT.ovpn"
exit
;;
2)
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
echo
echo "We were not able to find existing clients!"
exit
fi
echo
echo "Select the existing client certificate you want to revoke:"
tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
read -p "Select one client [1]: " CLIENTNUMBER
else
read -p "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
fi
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
echo
read -p "Do you actually desire to revoke the access of the client? $CLIENT? [y/N]: " -e REVOKE
if [[ "$REVOKE" = 'y' || "$REVOKE" = 'Y' ]]; then
cd /etc/openvpn/easy-rsa/
./easyrsa --batch revoke $CLIENT
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
rm -f pki/reqs/$CLIENT.req
rm -f pki/private/$CLIENT.key
rm -f pki/issued/$CLIENT.crt
rm -f /etc/openvpn/crl.pem
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
chown nobody:nogroup /etc/openvpn/crl.pem
echo
echo "Certificate for the client $CLIENT is revoked!"
else
echo
echo "Certificate revocation for client $CLIENT aborted!"
fi
exit
;;
3)
exit
;;
esac
done
else
clear
echo "OpenVPN is not installed."
echo "Install OpenVPN first"
echo "https://community.hetzner.com/tutorials/install-and-configure-openvpn-on-ubuntu-and-debian"
fi
Save the file, then apply the necessary permissions with the following command:
chmod 755 openvpn-user-manager.sh
Note: If you cannot connect to the VPN server, restart the VPS.
Using the OpenVPN User Manager (openvpn-user-manager.sh
):
Run the script:
bash openvpn-user-manager.sh
The output should look similar to this:
OpenVPN is installed.
What do you want to do?
1) Add a new user
2) Remove an existing user
3) Exit
Select an option [1-3]:
It was that simple to install OpenVPN on Ubuntu or Debian. The output of the command above clearly shows that you can define a new user, remove an existing user, and more. We hope this tutorial was useful for you.