Ressourcen des Heimnetzwerkes von unterwegs zu nutzen, das wäre eine feine Sache. Wenn sich das Heimnetz so darstellt, als ob man sich direkt zu Hause im Netzwerk befindet, das wäre ebenfalls praktisch. Ja, und dann wäre da noch die Sache mit der Sicherheit. Der Zugang soll für bestimmte Clients limitiert sein und die übertragenen Daten werden verschlüsselt.
Geringer Energieverbrauch und budgetschonende Anschaffungskosten stehen auch auf der Wunschliste.
Ziemlich viele Anforderungen für eine kostengünstige Lösung.
Abbildung der Infrastrukur:
Ein VPN (Virtual Private Network) stellt auf Basis zumeist öffentlicher Netze einen authentifizierten, verschlüsselten Tunnel in ein Zielnetz zur Verfügung. So kann zum Beispiel per Smartphone oder einem anderen Client eine Verbindung über das Internet in das eigene Netz zu Hause hergestellt werden.
Warum habe ich mich für einen Raspberry Pi entschieden?
Der Raspberry Pi verbraucht wenig Energie und mit der GPIO Steckleiste ist er hervorragend für diverse elektronische Basteleien geeignet, welche zum Beispiel mit Hilfe von Python oder einer anderen Programmiersprache angesteuert werden können.
Im Gegensatz zu einem herkömmlichen PC ist ein Raspberry PI mit den Zubehörteilen doch um einiges günstiger in der Anschaffung. Allerdings darf man nicht die Leistung eines PCs erwarten.
Der Raspberry besteht nur aus der Platine, dh. man hat alle Freiheiten bei der Wahl eines Gehäuses und vieles mehr.
Der Raspberry PI wird mit LINUX betrieben und bietet dadurch viele Möglichkeiten für dessen Einsatz.
Was wird alles an Hardware benötigt?
https://www.raspberrypi.org/products/
Betriebssystem Raspbian
Als Betriebsystem verwende ich Raspbian Release 8.0 (Jessie). Die Installation erfolgt mit Hilfe von NOOB und wird auf www.raspberrypi.org beschrieben. In diesem Beitrag behandle ich das weitere Setup für den VPN Server.
Im Zuge der Raspbian Installation wurde ein Benutzer „pi“ erstellt. Unter diesem Account erfolgen alle weiteren Aktivitäten.
Check der Betriebssystem Release:
$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 8.0 (jessie) Release: 8.0 Codename: jessie
Statische IP Adresse
Das Netzwerk verwendet als Standardeinstellung DHCP, ich möchte aber eine fixe IP Adresse vergeben. Hier hat sich in der Version Raspbian Jessie das Setup geändert.
Ich kenne den Eintrag einer fixen IP Adresse eigentlich nur bei den Netzwerkscripts in folgender Form:
iface eth0 inet static address 192.168.168.10 netmask 255.255.255.0 gateway 192.168.168.254
Bei Raspbian Jessie werden am Ende der Datei /etc/dhcpcd.conf folgende Einträge hinzugefügt. Der Router ist Gateway und DNS Server, wobei ich zusätzlich den Google DNS eintrage:
# vi /etc/dhcpcd.conf ... ... interface eth0 static ip_address=192.168.168.10/24 static routers=192.168.168.254 static domain_name_servers=192.168.168.254 8.8.8.8
Einstellen der korrekten Zeitzone
Falls die Zeitzone nicht systemweit eingestellt werden soll, kann dies durch einen Eintrag der TZ Variable in der .bash_profile Datei im HOME-Verzeichnis des Benutzers beeinflusst werden. Das Programm tzselect liefert interaktiv mögliche Werte für die TZ Variable.
Ich möchte aber eine systemweite Einstellung mit Hilfe von raspi-config vornehmen.
„/usr/bin/raspi-config“ – Internationalisation Options“ – „Change Timezone“ – Europa – Wien
Software Pakete
Im nächsten Schritt wird zuerst die Paketindex Datei mit den Quellen synchronisiert. Danach werden die Pakete auf den aktuellen Stand gebracht.
$ sudo apt-get update $ sudo apt-get upgrade
Für ein allfälliges Troubleshooting gehört für mich das Tool „lsof“ mit an Board:
$ sudo apt-get install lsof
Erforderliche Pakete für den VPN Server:
$ sudo apt-get install openvpn openssl
Raspberry Pi VPN Server einrichten
Nach einem Reboot ist der Raspberry PI per SSH auf der statischen IP Adresse 192.168.168.10 erreichbar und es kann mit dem eigentlichen Setup des VPN-Servers begonnen werden.
Für die Erstellung der Private/Public Keys und der Zertifikate werden von Raspbian Jessie bereits vorgerfertigte Scripte und Konfigurationsfiles mitgeliefert. Mit deren Hilfe wird im Hintergrund eine CA erstellt, welche für das Unterzeichnen der Certificate Signing Requests der VPN Clients verwendet wird. In der Datei „vars“ müssen nur die Basiseinstellungen angepasst werden.
Hinweis:
Bei den nächsten Konfigurationsschritten kam es beim Aufruf von „build-ca“ zu einem „routines:STR_COPY:variable has no value“ Fehler.
Durch Hinzufügen der Variablen KEY_ALTNAMES in „vars“ wurde das Problem behoben.
Datei „vars“
# cp -a /usr/share/easyrsa/ /etc/openvpn # cd /etc/openvpn/easyrsa # vi vars ... ... # tree. # export EASY_RSA="`pwd`" export EASY_RSA="/etc/openvpn/easyrsa" ... ... export KEY_SIZE=2048 # In how many days should the root CA key expire? export CA_EXPIRE=3650 # In how many days should certificates expire? export KEY_EXPIRE=3650 # These are the default values for fields # which will be placed in the certificate. # Don't leave any of these fields blank. export KEY_COUNTRY="AT" export KEY_PROVINCE="NO" export KEY_CITY="Maincity" export KEY_ORG="it-technet.info" export KEY_EMAIL="call@it-technet.info" export KEY_OU="Consulting" # X509 Subject Field export KEY_NAME="MYVPN" ... ... # If you'd like to sign all keys with the same Common Name, uncomment the KEY_CN export below # You will also need to make sure your OpenVPN server config has the duplicate cn option set export KEY_CN="mydomain.dyndns.org" export KEY_ALTNAMES="dummy"
Im easy-rsa Verzeichnis wird ein Link zur openssl.cnf Datei erstellt:
# cd /etc/openvpn/easy-rsa # ln -s openssl1.0.0.cnf openssl.cnf
CA „raspi“einrichten
Hinweis:
Vor der Verwendung der Scripts muss die Datei „vars“ eingelesen werden!!
# source vars # ./buildca raspi Generating a 2048 bit RSA private key ............................................................................... ....................................................................+++ .................................+++ writing new private key to 'ca.key' 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. Country Name (2 letter code) [AT]: State or Province Name (full name) [NO]: Locality Name (eg, city) [Maincity]: Organization Name (eg, company) [it-technet.info]: Organizational Unit Name (eg, section) [Consulting]: Common Name (eg, your name or your server's hostname) [mydomain.dyndns.org]: raspi Name [MYVPN]: Email Address [call@it-technet.info]:
Server Key plus Server Zertifikat erstellen. Der Common Name entspricht dem Domain Namen:
# ./buildkeyserver mydomain.dyndns.org Generating a 2048 bit RSA private key .+++ .................................+++ writing new private key to 'mydomain.dyndns.org.key' 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. Country Name (2 letter code) [AT]: State or Province Name (full name) [NO]: Locality Name (eg, city) [Maincity]: Organization Name (eg, company) [it-technet.info]: Organizational Unit Name (eg, section) [Consulting]: Common Name (eg, your name or your server's hostname) [mydomain.dyndns.org]: Name [MYVPN]: Email Address [call@it-technet.info]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /etc/openvpn/easyrsa/openssl1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'AT' stateOrProvinceName :PRINTABLE:'NO' localityName :PRINTABLE:'Maincity' organizationName :PRINTABLE:'it-technet.info' organizationalUnitName:PRINTABLE:'Consulting' commonName :PRINTABLE:'mydomain.dyndns.org' name :PRINTABLE:'MYVPN' emailAddress :IA5STRING:'call@it-technet.info' Certificate is to be certified until Dec 18 14:27:01 2025 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
Diffie-Hellman-Key-Exchange
Über das Diffie-Hellman-Key-Exchange-Verfahren (DH) lassen sich kryptographische Schlüssel sicher über unsichere Kanäle aushandeln. Die Erstellung des Diffie-Hellmann Keys hat auf meinem Raspberry etwas gedauert 🙁
# ./builddh Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time ......+.+...........+.................+..................++*++*
VPN DoS unterbinden
Open VPN bietet die Möglichkeit mittels HMAC (hash-based message authentication code) DoS zu verhindern. Daher wird wie folgt ein HMAC Key erzeugt.
# openvpn genkey secret keys/ta.key
Bereitstellung der Keys und Zertifikate
Schlüssel und Zertifikate werden in das openvpn Verzeichnis kopiert.
# cd /etc/openvpn/easyrsa/keys # cp -p ca.crt mydomain.dyndns.org.crt mydomain.dyndns.org.key dh2048.pem ta.key /etc/openvpn/
Raspberry Pi VPN Server Konfigurationsdatei erstellen
Die mit Raspbian mitgelieferte OpenVPN Konfigurationsdatei wird für das eigene Netz angepasst:
# zcat /usr/share/doc/openvpn/examples/sampleconfigfiles/server.conf.gz > /etc/openvpn/server.conf # cd /etc/openvpn # vi server.conf dev tun proto udp #Some people prefer to use tcp. Don't change it if you don't know. port 1194 ca ca.crt cert mydomain.dyndns.org.crt # SWAP WITH YOUR CRT NAME key mydomain.dyndns.org.key # SWAP WITH YOUR KEY NAME dh dh2048.pem # If you changed to 2048, change that here! server 10.8.0.0 255.255.255.0 # server and remote endpoints ifconfig 10.8.0.1 10.8.0.2 # Add route to Client routing table for the OpenVPN Server push "route 10.8.0.1 255.255.255.255" # Add route to Client routing table for the OpenVPN Subnet push "route 10.8.0.0 255.255.255.0" # your local subnet push "route 192.168.168.0 255.255.255.0" # SWAP THE IP NUMBER WITH YOUR RASPBERRY PI NETWORK # Set primary domain name server address to the SOHO Router # If your router does not do DNS, you can use Google DNS 8.8.8.8 push "dhcpoption DNS 192.168.168.254" # This should already match your router address and not need to be changed. # Override the Client default gateway by using 0.0.0.0/1 and # 128.0.0.0/1 rather than 0.0.0.0/0. This has the benefit of # overriding but not wiping out the original default gateway. push "redirectgateway def1" clienttoclient duplicatecn keepalive 10 120 tlsauth ta.key 0 cipher AES128CBC complzo user nobody group nogroup persistkey persisttun status /var/log/openvpnstatus.log 20 log /var/log/openvpn.log verb 1
IP Forwarding aktivieren
Zwischen den beiden LINUX Network Devices „eth0“ und „tun0“ werden IPv4 Pakete weitergeleitet.
# vi /etc/sysctl.conf ... ... # Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward=1 ... ... # sysctl -p
Zugehörige IP Tables Regeln definieren:
iptables -A INPUT -i tun+ -j ACCEPT iptables -A FORWARD -i tun+ -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -t nat -F POSTROUTING iptables -t nat -A POSTROUTING s 10.8.0.0/24 -o eth0 -j MASQUERADE
Damit die Regeln automatisch beim Bootvorgang aktiviert werden, wird eine neue iptables Konfig Datei in /etc definiert. Diese wird vor der Aktivierung der Netzwerkinterfaces eingelesen.
# iptables-save > /etc/iptables.up.rules # cat /etc/iptables.up.rules # Generated by iptables-save v1.4.21 on Tue Dec 22 09:10:34 2015 *nat :PREROUTING ACCEPT [261:40272] :INPUT ACCEPT [212:37765] :OUTPUT ACCEPT [99:7524] :POSTROUTING ACCEPT [99:7524] -A POSTROUTING s 10.8.0.0/24 -o eth0 -j MASQUERADE COMMIT # Completed on Tue Dec 22 09:10:34 2015 # Generated by iptables-save v1.4.21 on Tue Dec 22 09:10:34 2015 *filter :INPUT ACCEPT [994:114117] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [584:59688] -A INPUT -i tun+ -j ACCEPT -A FORWARD -i tun+ -j ACCEPT -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT COMMIT # Completed on Tue Dec 22 09:10:34 2015
# cd /etc/network/if-pre-up.d/ # vi iptables #!/bin/bash /sbin/iptables-restore < /etc/iptables.up.rules # chmod ug+x iptables
Jetzt den Raspberry Pi neu starten. Nach dem Reboot gibt es einen openvpn Prozess der auf dem UDP Port 1194 horcht sowie ein zusätzliches tun0-Networkdevice.
# ps ax|grep openvpn 1520 ? Ss 0:00 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --config /etc/openvpn/server.conf # lsof -i -p 1520 -Pn -a COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME openvpn 1520 nobody 4u IPv4 11605 0t0 UDP *:1194 # ip a show dev tun0 3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> 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
Router VPN Port Forwarding
Im nächsten Schritt muss auf dem Internet Router ein Port-Forwarding für das VPN UDP Port definiert werden.
Externes UDP Port 1194 auf intern 192.168.168.10 Port 1194
VPN Client Zertifikat
Zum Schluss benötigen wir noch ein Zertifikat für einen VPN Client. Für jeden weiteren Client wird analog ein zusätzliches Zertifikat erzeugt.
# cd /etc/openvpn/easy-rsa/ # source ./vars NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys # ./build-key sp01 Generating a 2048 bit RSA private key ................+++ ........................................................................................................................+++ writing new private key to 'sp01.key' ----- 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. ----- Country Name (2 letter code) [AT]: State or Province Name (full name) [NO]: Locality Name (eg, city) [Maincity]: Organization Name (eg, company) [it-technet.info]: Organizational Unit Name (eg, section) [Consulting]: Common Name (eg, your name or your server's hostname) [sp01]: Name [MYVPN]: Email Address [call@it-technet.info]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'AT' stateOrProvinceName :PRINTABLE:'NO' localityName :PRINTABLE:'Maincity' organizationName :PRINTABLE:'it-technet.info' organizationalUnitName:PRINTABLE:'Consulting' commonName :PRINTABLE:'sp01' name :PRINTABLE:'MYVPN' emailAddress :IA5STRING:'call@it-technet.info' Certificate is to be certified until Dec 30 10:43:01 2025 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
VPN Client Profildatei
Ein VPN Client verwendet für den Verbindungsaufbau ein Profildatei, welche im nächsten Schritt erstellt wird.
Hinweis:
Ich musste für den OpenVPN Client im Profil die Cipher Suite auf AES-128-CBC einstellen, da es sonst beim Verbindungsaufbau zu folgendem Fehler beim VPN Server gekommen ist:
Sat Jan 2 22:42:40 2016 89.144.239.163:39424 WARNING: 'cipher' is used inconsistently, local='cipher AES-128-CBC', remote='cipher BF-CBC'
Profildatei sp01.ovpn erstellen:
dev tun client proto udp remote mydomain.dyndns.org 1194 ca ca.crt cert sp01.crt key sp01.key resolv-retry infinite route-method exe route-delay 30 route-metric 512 route 0.0.0.0 0.0.0.0 nobind persist-key persist-tun comp-lzo verb 3 cipher AES-128-CBC
Auf dem Smartphone habe ich den OpenVPN Client installiert und in einem eigenen Verzeichnis folgende Files hinterlegt:
Im Open VPN Client auf dem Smartphone das sp01.ovpn Profilfile importieren und die Verbindung aufbauen.