Open VPN Server
History
For a few weeks, I've been playing with the idea some data I've been using for my projects use to store on a server so that devices and I can also access them from outside can view or edit.
My first idea seemed very simple for me and actually ‘pretty forward’:
I own a Fritz!Box 6591, this has a VPN from home
Service integrated, so I should be able to use that to my
Connecting home network to my servers.
My Provider (Vodafone)
Cable DE) has one (as in the meantime all the others)
DS-Lite connection assigned, so my Fritz!Box has no
public IPv4 address more.
For us of course no problem thought
I just use IPv6 – my servers are all per
IPv6 accessible and are also addressed mainly via IPv6...
The alternative for me is NAT-T (I think at least).
Quickly set up IPSec on servers using StrongSwan, PKI set up and generates certificates so that the devices also can be tidy and especially secure.
So we're done. - No, unfortunately not. There is no connection for any reason.
Fritz!Box
tested, everything correctly adjusted I think... Also the servers
controlled... all good, but still no signs of a connection.
The logs looked at, but there is no connection.
Maybe
the problem lies with DynDNS (MyFritz) – all addresses static
made (are valid at least 24h) but also here no success.
After 2 days trouble shooting and shortly before the nervous breakdown, I encounter an article by AVM (Source 2) that says that Fritz!Box does not support VPN via IPv6...
All work for free, but lesson learned – always look at the technical specifications before you start something.
I now have a public IPv4 address free of charge from Vodafone
obtained. Now VPN also works (alternatively it works
also via IPv4 with DS Lite) – but I have now
decided to use Open VPN as it besides the possibility of
“pure” IPv6 also significantly configured and managed
can be.
The Fritz!Box story, however, we do not forget, we will deal with the subject in a later post.
Disclaimer
We set up an OpenVPN server together here, which is accessible everywhere. a faulty configuration or incorrect use may result in security risks arising in worst case leading to the control loss of the server (if the OpenVPN z. running with root permissions and configured unprotected can be used).
I therefore accept no liability for this contribution. This is
a tutorial on how to implement an OpenVPN server, but not
Patent recipe for the best or most brilliant solution.
Otherwise a lot of fun when putting on.
What's the target?
Objective of the whole project, it will be to a web server via VPN
to access which is not to be on the Internet. All
Home networking devices are to be connected to a web server with specific
Access data (this subproject is part of a larger
Projects I describe in a later post
).
In this case, all home network devices
(192.168.178.0/24) Access to the Web server (and other servers/devices
in the 10.0.0.0/24 network), but no device from the 10.0.0.0/24 network gets
Access to our home network as it is not needed for me
and so my home network remains protected. When a device comes from
10.0.0/24 network would want to my home network, rejects the home
Gateway later this package. It is possible without difficulty, however, the whole
Adding or completely turning history (home network has no
Access to the VPN network, but by VPN you have access to the
Home network, for this the routing is simply “rotated”).
What is needed
As hardware I use:
- VPS Server (rented by Netcup) – later serving as OpenVPN Server and houses a web server I want to access my home network)
- A Raspberry Pi 2 – the Raspi serves us as a VPN gateway. Traffic
becomes from the home network when the destination address in the network area
10.0.0/24 is forwarded to the VPN server.
Networks used:
- Home network: 192.168.178.0/24 – Standard Fritz!Box Net
- Remote (server) network: 10.0.0.0/24 – this address can only be used locally and is not routed externally anyway.
Software used:
- OpenVPN (Community) – (as VPN Server/Client)
- UFW (as a simple general firewall)
- IP Tables (follows the home network packages later into the 10.0.0/24 network).
VPN server
First we install a small PKI (Public Key Infrastructure) to be able to issue and sign certificates. With these we will then authenticate to the OpenVPN server.
In the optimal case, this CA will be in a separate VM or a non- stored from the Internet accessible server, but for simplicity half, we install the PKI in a folder under
mkdir /opt/easyRSA && cd /opt/easyRSA
Next we download easyRSA (source 3) – currently in version 3.0.8
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
After that we unpack easyRSA and create our CA (Certificate
Authority – this later signifies our certificates and is considered to be
“Confidence Centre”)
tar zxvf EasyRSA-3.0.8.tgz && cd EasyRSA-3.0.8
In order to correctly issue the certificates, some data (such as
Land) are inserted in the certificates, for which we use a file
by EasyRSA and customize them
cp vars.example vars && vi vars
The following data is now adjusted here (the rhombs (#) before the respective rows must be removed).
set_var EASYRSA_REQ_COUNTRY "DE"set_var EASYRSA_REQ_PROVINCE "yourProvince"set_var EASYRSA_REQ_CITY "yourCity"set_var EASYRSA_REQ_ORG "yourOrg"set_var EASYRSA_REQ_EMAIL "your@mail.de"set_var EASYRSA_REQ_OU "your OU"
EasyRSA will create several certificates for us to
generates the SSL Suite is needed, so we need to make sure
that SSL is installed
openssl version
The output should look like this:
OpenSSL 1.1.1k 25 Mar 2021
If OpenSSL is installed, we can initialize the PKI:
./easyrsa init-pki
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /opt/easyRSA/EasyRSA-3.0.8/pki
Now we create the CA – two important files are generated:
ca. – the public certificate of CA. With we will later inform our openVPN server that it is part of the web-of-trust is and can “confide” our certificates.
ca.key – the private key of the CA used to sign certificates and keys of this CA:
Attention: This key should be private!
./easyrsa build-ca nopass
During this process you will be asked for a CA name, here
you can enter what you want or leave the field blank.
The CA is now ready and can create certificates for us.
As
Next we create a Cert Request to create new certificates
to authenticate our clients. You can
either download easyRSA on the client and there
create the request or copy the certificate of VPN later
Server to client.
./easyrsa gen-req server nopass
The parameter nopass prevents a password from being queried later when using the request
Next
import (only if you have the CA on another server) and
we sign the request (.req File) – My request is called server if
you have chosen another, should of course be adjusted
:
./easyrsa import-req ./pki/reqs/server.req server ./easyrsa sign-req server server
When signing, only the data must be confirmed (yes) and then the certificate is obtained.
Last post
we create another Diffie-Hellman key. This will be later
needed to secure the key between client and server
exchange.
./easyrsa gen-dh
This process can take a little time.
Install and Set up VPN Server
Now we have a working CA including our certificates, so we can now install and configure the OpenVPN server
apt install openvpn
We now copy all required certificates from PKI to the OpenVPN Server Directory
cp ./pki/issued/server.crt /etc/openvpn/server/server.crt
cp ./pki/ca.crt /etc/openvpn/server/ca.crt
cp ./pki/private/server.key /etc/openvpn/server/server.key
cp ./pki/dh.pem /etc/openvpn/server/dh.pem
Now we generate a key to verify our connection later (TLS-Auth / HMAC if you want to google)
cd /etc/openvpn/server && openvpn --genkey --secret ta.key
Now we have all important certificates for basic
running the VPN server available, so we now configure it:
First we copy the example Server Configuration, to the OpenVPN directory:
zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
In this you can adapt in principle, but we change the following:
port 443proto tcpca /etc/openvpn/server/ca.crtcert /etc/openvpn/server/server.crtkey /etc/openvpn/server/server.keydh /etc/openvpn/server/dh.pemtopology subnetserver 10.0.0.0 255.255.255.0tls-auth /etc/openvpn/server/ta.key 0;cipher AES-256-CBCdata-ciphers AES-256-CBCdata-ciphers-fallback AES-256-CBCuser ovpn #der User muss per adduser --disabled-login erstellt werdengroup ovpnstatus /var/log/openvpn/openvpn-status.loglog-append /var/log/openvpn/openvpn.logverb 6 #Falls bei euch Fehler auftreten, werden diese im Log sehr detailgenau angezeigtmute 10;explicit-exit-notify 1
Next we instruct the server to forward IPv4 packages:
sysctl -w net.ipv4.ip_forward=1
Lastly, we add a route so that the server knows where the packages must be routed from the 10.0.0/24 network
ip route add 10.0.0.0/24 dev tun0
To create users we need a file with the “growing” parameters
vi /etc/openvpn/client.txt
With the following content
client
dev tun
proto tcp
sndbuf 0
rcvbuf 0
tun-mtu 1500
mssfix 1420
remote <<deine öffentliche Adresse des VPN Server>> 443
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA1
auth-nocache
cipher AES-256-CBC
setenv opt block-outside-dns
key-direction 1
verb 6
Next we add a client to the VPN server, for this we create the following script
mkdir /etc/openvpn/userControl && cd /etc/openvpn/userControl && vi userControl.sh
Script:
!/usr/bin/env bash
if readlink /proc/$$/exe | grep -q "dash"; then
echo "Bitte verwende Bash - SH funktioniert nicht"
exit
fi
if [[ "$EUID" -ne 0 ]]; then
echo "Das Script muss als root ausgefuehrt werden!"
exit
fi
newclient ()
{
cp /etc/openvpn/client.txt ~/$1.ovpn echo "" >> ~/$1.ovpn
cat /etc/openvpn/server/ca.crt >> ~/$1.ovpn echo "" >> ~/$1.ovpn
echo "" >> ~/$1.ovpn sed -ne '/BEGIN CERTIFICATE/,
$ p' /opt/easyRSA/EasyRSA-v3.0.8/pki/issued/$1.crt >> ~/$1.ovpn echo "" >> ~/$1.ovpn
echo "" >> ~/$1.ovpn cat /opt/easyRSA/EasyRSA-v3.0.8/pki/private/$1.key >> ~/$1.ovpn
echo "" >> ~/$1.ovpn echo "" >> ~/$1.ovpn sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/ta.key >> ~/$1.ovpn
echo "" >> ~/$1.ovpn }
if [[ -e /etc/openvpn/server.conf ]];
then while :
do clear echo "" echo "Bitte waehlen?"
echo " 1) Benutzer hinzufuegen"
echo " 2) Benutzer entfernen"
echo " 3) UserControl schliessen"
read -p "Option waehlen [1-3]: " option
case $option in 1) echo echo "Benutze keine umlaute oder special characters!"
read -p "Name: " -e CLIENT
cd /opt/easyRSA/EasyRSA-v3.0.8/ EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full
$CLIENT nopass newclient "$CLIENT" echo
echo "Nutzer $CLIENT hinzugefuegt, Speicherpfad: " ~/"$CLIENT.ovpn" exit ;;
2)
NUMBEROFCLIENTS=$(tail -n +2 /opt/easyRSA/EasyRSA-v3.0.8/pki/index.txt | grep -c "^V")
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
echo echo "Keine Benutzer vorhanden!"
exit
fi
echo
echo "Welchen Benutzer moechtest du entfernen?:" tail -n +2 /opt/easyRSA/EasyRSA-v3.0.8/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
if [[ "$NUMBEROFCLIENTS" = '1' ]];
then read -p "Waehle einen Benutzer aus [1]: "
CLIENTNUMBER else
read -p "Waehle einen Benutzer aus [1-$NUMBEROFCLIENTS]: "
CLIENTNUMBER
fi
CLIENT=$(tail -n +2 /opt/easyRSA/EasyRSA-v3.0.8/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
echo read -p "Moechtest du den Benutzer wirklich Loeschen? $CLIENT? [y/N]: " -e REVOKE if [[ "$REVOKE" = 'y' || "$REVOKE" = 'Y' ]];
then
cd /opt/easyRSA/EasyRSA-v3.0.8/ ./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 /opt/easyRSA/EasyRSA-v3.0.8/pki/crl.pem /etc/openvpn/crl.pem
chown ovpn:ovpn /etc/openvpn/crl.pem
echo echo "Zertifikat fuer den Benutzer $CLIENT zerstoert!"
else
echo echo "Zertifikat fuer $CLIENT wurde nicht widerrufen!"
fi
exit ;;
3) exit ;;
esac
done
else
clear
echo "OpenVPN ist nicht installiert."
echo "OpenVPN muss installiert sein!"
echo "https://blog.justinritter.de" fi
If you need to adjust your firewall to forward traffic from the tunnel (e.g. to the Internet)
With the script you can now create a user. You receive a .ovpn file, which for example also for the OpenVPN Connect client but the configuration is currently not compatible with TLS-Auth (HMAC) – If your Android/IOS/Windows client if you want to use TLS Auth in the Configs disable, then the mobile client also works.
The server can now be started and is ready for use
sudo service openvpn@server restart
Set up Raspberry Pi
Here is unfortunately a little “play around” asked, in my case have I used an old Raspberry Pi 2, this I had to hand update as the repos have led to old SSL versions among others. However, the Raspi 2 also works perfectly...
First we install OpenVPN
apt install openvpn
After installation copy the client Config
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/
Here, too, you can adapt everything for you, all data but have to match the VPN server – I change here:
proto tcp
user ovpn #Benutzer kann per adduser --disabled-login erstellt werden
group ovpn
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/raspberry.crt
key /etc/openvpn/server/raspberry.key
remote-cert-tls server
tls-auth /etc/openvpn/server/ta.key 1
cipher AES-256-CBC
# Silence repeating messages
mute 10
# Output a short status file showing
# current connections, truncated
# and rewritten every minute.
status /var/log/openvpn/openvpn-status.log
# By default, log messages will go to the syslog (or
# on Windows, if running as a service, they will go to
# the "\Program Files\OpenVPN\log" directory).
# Use log or log-append to override this default.
# "log" will truncate the log file on OpenVPN startup,
# while "log-append" will append to it. Use one
# or the other (but not both).
;log /var/log/openvpn/openvpn.log
log-append /var/log/openvpn/openvpn.log
Finally, all certificates have to be copied for the client.
The
File raspberry.crt removes you from the .ovpn File ->
the certificate from and adds the content
into the file.
The raspberry.key file is copied from the section .
Finally, the files ca.crt and ta.key – they copy them from the server and also insert them in the folder.
Finally we add a routing rule so that the RaspberryPi can act as a gateway and messages from our Home network (network 192.168.178.0/24) translated to 10.0.0/24 we have:
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
And so the Raspberry Pi knows that he has the traffic for
10.0.0/24 must be pushed through its tunnel and not over the default
Route (with me to the Fritz!Box (192.168.178.1)) – the 10.0.0.3 you must
probably customize – here comes the VPN address of the RaspberryPi’s
pure (you can see under “ip a”)
sudo ip route add 10.0.0.0/24 via 10.0.0.3 dev tun0
Now the client has to be started
sudo service openvpn@client restart
The VPN server receives the IP 10.0.0.1 by default – this IP should now be able to pin it
ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=5.4 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=11.9 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=8.8 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=4.5 ms
64 bytes from 10.0.0.1: icmp_seq=5 ttl=64 time=9.9 ms
If this doesn't work, try a local ping on the VPN first Server to see if the IP Stack for the VPN Tunnel ever works (ping 10.0.0.1) – If so, you can see if your Raspi also has a 10 address ($ ip a). In the case of you can be under
tail -f /var/log/openvpn/openvpn-status.log
view the current status in exact minutes, or under
tail -f /var/log/openvpn/openvpn.log
by setting “Verb” in the server and client.conf View detailed log and possibly go to troubleshooting.
Special attention would be given to firewall (closed ports)/ (UFW, IP Tables), these have first steps made many problems.
If you get a connection to the server (ping successfully) – but, for example, does not get access to the web server, your web server listens to all interfaces (at Apache2 e.g. by the List Directive
Configuring Fritz!Box for access to the VPN tunnel
If other devices also access the VPN tunnel (and services in other subnet), then the Fritz!Box must also know where Packages with the target address are forwarded in the 10.0.0/24 network have to. A static route is created in the Fritz!Box.
First, the web interface of the Fritz!Box must be opened, so you can enter in the browser
http://192.168.178.1
After login must be under home network -> network -> Network settings -> Static routing table an IPv4 route be inserted. In our case, the following must be entered in the mask are:
IPv4-Netzwerk: 10.0.0.0
Subnetzmaske: 255.255.255.0
Gateway: <<Hier muss die Adresse des RaspberryPi rein>> - z.B 192.168.178.4
Finally put the hook on “IPv4 route active” so that the route is directly applied and confirm
The Fritz!Box now directs all packages that are have address from the 10.0.0.0/24 network, to the specified gateway on. From there, the Raspberry Pi will implement the packages and through send the tunnel (The 192.168.178.x will not be behind the tunnel more routed as this is local, so we have on the Raspberry Pi the gateway that uses its own address and the VPN server “probably” that he wants to have the data. Alternatively, this can also on the VPN server (as prerouting rule).
Addendum: Connection to the local Subnet
As a supplement, I now add the possibility to access the home network from the server (192.168.178.0/24).
Um...
To realize access, OpenVPN must first know that our
Gateway (Raspberry Pi) – which makes 192.168.178.0/24 network accessible.
To do this, we need to work on the OpenVPN server
vi /etc/openvpn/ccd/<<Zertifikatsname des RaspberryPi>>
create a file with the following inhal
ifconfig-push 10.0.0.2 255.255.255.0
push "route 10.0.0.0 255.255.255.0"
iroute 192.168.178.0 255.255.255.0
“ifconfig-push 10.0.0.2 255.255.255.0” -> Does the client imemr have the address 10.0.0.2
‘push
“route 10.0.0.0 255.255.255.0′′” –> Tells the client that he packages
with target 10.0.0/24 to run through the VPN tunnel
‘iroute
192.168.178.0 255.255.255.0” -> Tells the OpenVPN server that the
client, also the network 192.168.178.0/24 routed and packages with the target,
to be sent to GW
Finally, the following must be commented in the Config:
#client-config-dir ccd
#client-to-client
route 192.168.178.0 255.255.255.0 10.0.0.2
Now the ping into the net 192.168.178.0/24 should be possible:
ping 192.168.178.4
PING 192.168.178.4 (192.168.178.4) 56(84) bytes of data.
64 bytes from 192.168.178.4: icmp_seq=1 ttl=64 time=22.7 ms
64 bytes from 192.168.178.4: icmp_seq=2 ttl=64 time=21.6 ms
64 bytes from 192.168.178.4: icmp_seq=3 ttl=64 time=23.9 ms
64 bytes from 192.168.178.4: icmp_seq=4 ttl=64 time=22.6 ms
64 bytes from 192.168.178.4: icmp_seq=5 ttl=64 time=25.3 ms
--- 192.168.178.4 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
Sources for reading
Source 2:
https://avm.de/service/wissensdatenbank/dok/FRITZ-Box-6360/1306_Sind-VPN-Connections-zur-FRITZ-Box-mit-IPv6-or-DS-Lite-mobar/
Source 3: https://github.com/OpenVPN/easy-rsa/releases
Back…