Introduction
OpenVPN is an open-source project created by James Yonan and was released back in 2002. OpenVPN provides a high level of security using point-to-point or site-to-site connections with custom security protocol.
Prerequisites
- Server with Linux Operating System:
- Ubuntu 16.04|18.04|19.04
- Debian 8|9
- Root access
- IPv4 and IPv6 Address
- If you're unsure what your IP addresses are, you can look them up:
IPv4 address
ip addr show dev eth0 | grep "inet" | awk '{ print $2 }'
The output should be similar to this:
root@ubuntu-2gb-nbg1-1:~# ip addr show dev eth0 | grep "inet" | awk '{ print $2 }'
116.203.180.222/32
Our IPv4 is 116.203.180.222 and it has a /32 subnet mask.
IPv6 address
#IPv6
ip addr show dev eth0 | grep "inet6 " | awk '{ print $2 }'
The output should be similar to this:
root@ubuntu-2gb-nbg1-1:~# ip addr show dev eth0 | grep "inet6" | awk '{ print $2 }'
2a01:4f8:c2c:5fc7::1/64
fe80::9400:ff:fe27:10db/64
Our IPv6 is 2a01:4f8:c2c:5fc7::1 and it has a /64 subnet mask.
The second IPv6, fe80::9400:ff:fe27:10db, is the MAC address (RFC 4291).
Step 1 - Installation and configuration
Step 1.1 Installation
Installing OpenVPN, IPTables, OpenSSL and ca-certificates package.
apt-get install openvpn iptables openssl ca-certificates -y
When 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 have to create PKI and set up CA and server/client certificates
Note: Certificates will expire in 3650 days (10 years), you can change value.
Note: You can change the client certificate name (CLIENT), but don't 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 certificates in 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 certificates we are going to generate key for tls authentication (tls-auth), after that we need to create DH parameters and we gonna use predefined ffdhe2048 group.
openvpn --genkey --secret /etc/openvpn/ta.key
Predefined DHE groups are recommended by the Internet Engineering Task Force (IETF) in RFC 7919. These groups are supposed to be more resistant to attacks than ones randomly generated
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
Step 1.2 Configuration
Now it's time to create the OpenVPN server config.
Settings that you may change:
- port: 1194 (default) or 443
- proto: udp (default) or tcp
Note: It's better to change the port because OpenVPN port 1194 could be blocked. Furthermore, port 443 is ideal for avoiding censorship because OpenVPN traffic looks identical to the regular SSL traffic.
Note: UDP protocol has better performance than the TCP protocol, but it's not so reliable.
nano /etc/openvpn/server.conf
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"
Now is the DNS part, you have a few options to choose from.
- Use default system DNS
- Cloudflare DNS
- Google DNS
- Quad9 DNS
System DNS
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 be similar to this:
185.12.64.1
185.12.64.2
Hetzner (default) DNS
IPV4:
Primary DNS: 185.12.64.1
Alternative DNS: 185.12.64.2
IPV6
Primary DNS: 2a01:4ff:ff00::add:1
Alternative DNS: 2a01:4ff:ff00::add:2
Cloudflare DNS
IPV4:
Primary DNS: 1.1.1.1
Alternative DNS: 1.0.0.1
IPV6
Primary DNS: 2606:4700:4700::1111
Alternative DNS: 2606:4700:4700::1001
Google DNS
IPV4:
Primary DNS: 8.8.8.8
Alternative DNS: 8.8.4.4
IPV6
Primary DNS: 2001:4860:4860::8888
Alternative DNS: 2001:4860:4860::8844
Quad9 DNS
IPV4:
Primary DNS: 9.9.9.9
Alternative DNS: 149.112.112.112
IPV6
Primary DNS: 2620:fe::fe
Alternative DNS: 2620:fe::9
After you choose DNS provider, add them at the end of the file.
Note: You should add both DNS servers (IPv4 and IPv6), the first is primary DNS server and the second is alternative DNS server.
nano /etc/openvpn/server.conf
push "dhcp-option DNS SELECTED-DNS-PROVIDER"
push "dhcp-option DNS SELECTED-DNS-PROVIDER"
After we're done with the DNS part, it's time to continue with the rest of the configuration file.
Add the rest of the configuration at the end of the file.
nano /etc/openvpn/server.conf
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
Now we have to add the firewall rules.
If you are using firewalld:
# 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
If you are using iptables
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 --ddport 1194 to --ddport 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 --ddport 1194 to --ddport 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
Now we need to create a client configuration file.
nano /etc/openvpn/client.txt
Add the whole 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
In the end OpenVPN server configuration it should look similar to this:
Show server.conf file
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
Step 1.3 (Optional)
Some VPS are with disabled IPv4/IPv6 packet forwarding. To enable IPv4 forwarding you should edit /etc/sysctl.conf
nano /etc/sysctl.conf
Search for the following lines:
# 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.
Step 2 - Create OpenVPN client
In order to be easy for us to add a new user, we're going to create a script. The script will have 2 options:
- Add a new user
- Remove an existing user
cd ~
nano openvpn-user-manager.sh
Copy and paste the configuration below:
#!/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
Give permissions:
chmod 755 ~/root/openvpn-user-manager.sh
Note: If you can't connect to the vpn server, reboot the VPS. If the problem exists after reboot, follow the step 1.3.
Step 3 - Using OpenVPN User Manager (openvpn-user-manager.sh)
Run the script:
bash openvpn-user-manager.sh
The output should be 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]:
Conclusion
Your OpenVPN server is now ready. You can browse and enter sites that are restricted or send private files.