Raspberry PI VPN Server

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:
VPN Infrastruktur
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?

Raspberry PI
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/

  • Raspberry PI
  • USB Tastatur
  • USB Maus
  • Micro SD Card
  • Netzgerät für USB
  • HDMI Kabel und Monitor
  • Internet Zugang
  • 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.

  • EASY_RSA: Pfad zum easy-rsa Verzeichnis. Gegenüber Vorgängervserionen hat sich dieses bei Jessie geändert
  • KEY_SIZE, CA_EXPIRE: Key-Size und -gültigkeitsdauer
  • KEY_CONFIG: zeigt auf die openssl.cnf Datei
  • KEY_COUNTRY, usw. anpassen
  • KEY_NAME: VPN Name
  • KEY_CN: Common Name entspricht dem Domain Namen. Bei Heimnetzen ohne fixer IP Adresse ist dies meistens der DynDNS Name.
  • 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/easy­rsa/ /etc/openvpn
    # cd /etc/openvpn/easy­rsa
    # vi vars
    ... ...
    # tree.
    # export EASY_RSA="`pwd`"
    export EASY_RSA="/etc/openvpn/easy­rsa"
    ... ...
    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 openssl­1.0.0.cnf openssl.cnf

    CA „raspi“einrichten

    Hinweis:
    Vor der Verwendung der Scripts muss die Datei „vars“ eingelesen werden!!

    # source vars
    # ./build­ca 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:

    # ./build­key­server 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/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:'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 🙁

    # ./build­dh 
    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/easy­rsa/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/sample­config­files/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 "dhcp­option 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 "redirect­gateway def1"
    client­to­client
    duplicate­cn
    keepalive 10 120
    tls­auth ta.key 0
    cipher AES­128­CBC
    comp­lzo
    user nobody
    group nogroup
    persist­key
    persist­tun
    status /var/log/openvpn­status.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
    Router VPN Portforwarding

    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:

  • ca.crt … Zertifikat der CA
  • sp01.crt … Zertifikat des Clients
  • sp01.key … Client Key (Client private key)
  • sp01.ovpn … Client Open VPN Profil
  • ta.key … Open VPN TLS authentication secret
  • Im Open VPN Client auf dem Smartphone das sp01.ovpn Profilfile importieren und die Verbindung aufbauen.
    Open VPN Client Profile
    Open VPN Client Verbindung