Dezentrales HA Servercluster-VPN mit PeerVPN


Um hochverfügbare Dienste zu hosten, empfiehlt es sich, Server bei mehreren Hostern in verschiedenen, geografisch verteilten Rechenzentren zu betreiben. Die Server-to-Server-Kommunikation innerhalb des Serverclusters sollte dabei verschlüsselt stattfinden. Das lässt sich am einfachsten über ein Cluster-eigenes VPN erreichen - also ein privates Netzwerk, das nur dem sicheren Informationsaustausch der Server untereinander dient. Ich habe mich nach einer passenden VPN-Lösung für ein Projekt umgesehen und habe die für mich perfekte Softwarelösung gefunden: PeerVPN von Tobias Volk.

PeerVPN hebt sich von der Vielzahl der OpenSource VPN Projekte durch folgende Eigenschaften ab:

  • PeerVPN ist klein und einfach. Die Einrichtung ist für geübte in weniger als einer Minute erledigt und bedarf keiner Einarbeitung.
  • PeerVPN bildet ein voll vermaschtes Peer-to-Peer Netzwerk. Das heißt: Auf einen zentralen Server (Single Point of Failure!) kann verzichtet werden.
  • Authentifizierung via Shared Key

Installation unter Debian Jessie

Im folgenden erkläre ich die Installation von PeerVPN unter Debian 8 (Jessie). Die Vorgehensweise lässt sich in den meisten Fällen auch auf alle anderen Debian-basierten Linux-Distributionen übertragen (z.B. Ubuntu Server).

Wir werden PeerVPN aus dem offiziellen Quellcode auf GitHub selbst kompilieren. Das ist schnell erledigt und überraschend schmerzfrei. Dafür benötigen wir zunächst einige Pakete, die nachinstalliert werden müssen, falls sie nicht schon auf dem System installiert sind:

apt update && apt install git build-essential

Quellcode herunterladen:

git clone https://github.com/peervpn/peervpn/
cd peervpn

PeerVPN benötigt OpenSSL 1.0 oder LibreSSL, um zu funktionieren. Debian Jessie kommt mit OpenSSL 1.0. Leider ist PeerVPN aktuell nicht mit dem neueren OpenSSL 1.1 kompatibel, welches in künftigen Debian Stable Releases enthalten sein wird. Stattdessen kann LibreSSL genutzt werden.

Kompilieren mit OpenSSL 1.0

Wer Debian Jessie oder eine andere Linux-Distribution mit OpenSSL 1.0 verwendet, kann das libssl-dev Paket installieren, und PeerVPN direkt kompilieren:

apt install libssl-dev

Quellcode kompilieren:

make -j2

(-j2 zum Kompilieren mit 2 CPU-Kernen, -j4 für 4 Kerne etc.)

Kompilieren mit LibreSSL

Wenn kein OpenSSL 1.0 verfügbar ist oder LibreSSL verwendet werden soll, kann PeerVPN problemlos auch mit LibreSSL kompiliert werden. Dafür wird im heruntergeladenen Git-Verzeichnis die Datei “build.sh” mit diesem Inhalt angelegt:

#!/bin/sh

libressl_version=libressl-2.5.1
libressl_archive=${libressl_version}.tar.gz

if [ -f ${libressl_archive} ]
then
    :
else
    wget -O ${libressl_archive} https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${libressl_archive}
fi

if [ -f ${libressl_archive} ]
then
    :
else
    echo wget failed.
    return -1
fi

libressl_lib=${libressl_version}/crypto/.libs/libcrypto.a
if [ -f $libressl_lib ]
then
    :
else
    tar -xzf ${libressl_archive}
    cd ${libressl_version} && ./configure && make && cd ..
fi

cc -O2 -I${libressl_version}/include peervpn.c -o peervpn ${libressl_version}/crypto/.libs/libcrypto.a && echo success!

(Script auf GitHub Gist)

Das Script lädt LibreSSL herunter und generiert eine statisch gelinkte Version von PeerVPN. Achtet darauf, dass im Script eine aktuelle LibreSSL-Version angegeben ist! (https://www.libressl.org/)

PeerVPN auf dem System installieren:

cp peervpn /usr/local/bin

PeerVPN konfigurieren

Konfigurationsverzeichnis erstellen:

mkdir /etc/peervpn

Im Konfigurationsverzeichnis wird die Datei “vpn.conf” angelegt:

networkname PEERVPN
psk meinsupergeheimerschlüssel
interface peervpn0
port 7000
ifconfig4 10.0.2.1/24
initpeers host2.domain.tld 7000 host3.domain.tld 7000
  • networkname: Frei wählbarer Netzwerkname
  • psk: Schlüssel, gemeinsamer, geheimer Schlüssel, über den sich die Teilnehmer authentifizieren
  • interface: Interface-Name für das zu erstellende Netzwerk-Interface
  • port: Port, der für die Kommunikation zwischen den Nodes genutzt werden soll
  • ifconfig4: IP-Adresse des jeweiligen Servers im VPN. (Individuell für jeden Host!)
  • initpeers: Auf einem der Hosts werden über “initpeers” alle anderen Hosts definiert. Das ist notwendig, damit die Teilnehmer beim Start des Netzwerks untereinander bekannt gemacht werden können. Syntax: initpeers <host> <hostport> <host> <hostport> ...

Systemd-Service

Auf jedem der Teilnehmerhosts wird außerdem ein Systemd-Service eingerichtet, welcher PeerVPN nach dem Systemstart automatisch initiiert:

Datei /etc/systemd/system/peervpn@.service anlegen:

[Unit]
Description=PeerVPN Node (%i)
After=syslog.target network.target
ConditionPathExists=/etc/peervpn/%i.conf

[Service]
Type=simple
ExecStart=/usr/local/bin/peervpn /etc/peervpn/%i.conf

[Install]
WantedBy=multi-user.target

VPN Service Aktivieren und starten:

systemctl enable peervpn@vpn.service
systemctl start peervpn@vpn.service

Test

Nachdem PeerVPN auf allen Hosts installiert und gestartet wurde, kann es einige Sekunden dauern, bis sich die Teilnehmer untereinander vernetzt haben. Den aktuellen Vernetzungsstatus eines Teilnehmers kann u.A. via

systemctl status peervpn@vpn.service

abrufen. Im Log wird mitprotokolliert, zu wie vielen anderen Hosts eine Verbindung besteht.

Ein einfacher Verbindungstest kann via ping erfolgen:

ping 10.0.2.1
ping 10.0.2.2
...

Bestehende Dienste wie z.B. Webserver oder Datenbankserver können nur an die jeweilige 10.0.2.x -IP-Adresse des Hosts gebunden werden, sodass sie nur über das VPN erreichbar sind.