Betreiben eines Servers über IPv4 ohne öffentliche IPv4-Adresse (DS-Lite)

Datum
Kommentare Keine

Das Betreiben eines Servers hinter dem eigenen DSL- oder Kabel-Router ist normalerweise keine große Sache und dank integrierter Weboberflächen mit einigen Klicks erledigt. Komplizierter ist die Sache bei einem Anschluss, der im sog. Dual-Stack Lite (DS-Lite) läuft. Dabei handelt es sich um einen Anschluss, der nicht über eine öffentliche IPv4-Adresse erreichbar ist. Eine Möglichkeit ist es, das Gerät (den Server, das NAS o. ä.) so zu konfigurieren, dass es über IPv6 aus dem Internet erreichbar ist. Dafür muss es aber (ebenso wie der Router) IPv6-kompatibel sein, was auch heute noch nicht selbstverständlich ist. Auf der anderen Seite muss der Client ebenfalls IPv6 unterstützen (auch nicht selbstverständlich). Praktikabel ist der IPv6 Weg also (noch) nicht.

Als Ausweg gibt es diverse Portmapper, die für relativ viel Geld einzelne IPv6-fähige Geräte auf IPv4 Mappen, sodass diese über eine öffentliche IPv4-Adresse erreichbar sind. Zwei Nachteile wurden hierbei schon genannt: die Kosten sowie die Tatsache, dass sie IPv6-kompatibel sein müssen.

Eine flexiblere und in vielen Fällen auch günstigere Möglichkeit ist der Einsatz eines vServers: Dieser kann dazu genutzt werden, an ihn gestellte Anfragen zu einem per VPN verbundenen Server weiterzuleiten. Hierzu eignet sich hervorragend OpenVPN als einfach umzusetzende VPN-Lösung. Die Umleitung an den Server regelt hierbei ein kleines iptables-Skript. Das Prinzip hiervon verdeutlicht die folgende Zeichnung.

Da der vServer lediglich das VPN bereitstellen und Anfragen umleiten muss, ist der Ressourcenbedarf gering. Somit kommen auch minimal ausgestattete vServer in Frage, die es bereits ab wenigen Cent pro Tag (3 Cent aufwärts, oft prepaid) gemietet werden können.

OpenVPN-Konfiguration

Mit apt-get install openvpn installieren wir OpenVPN.

Erstellung der Zertifikate
Bevor wir uns aber an die eigentliche Konfiguration von OpenVPN machen, müssen wir uns um die Erstellung der nötigen Zertifikate kümmern. Hinweis: Idealserweise erfolgt aus Sicherheitsgründen die Erstellung von Zertifikaten auf einem separaten System, das nur für diesen Zweck genutzt wird.

Neben grafischen Lösungen zur Verwaltung von Zertifikaten (wie z. B. tinyca) bietet sich die easy-rsa-Skriptsammlung an, die unter Debian bei der Installation von OpenVPN unter /usr/share/doc/openvpn/examples/easy-rsa/2.0/ zu finden ist. Unter Ubuntu existiert ein eigenes Paket easy-rsa. Wir wechseln in das Verzeichnis von easy-rsa.

Erstellung der CA

  1. Anpassung der vars-Datei an die eigenene Bedürfnisse. Hier werden Standardwerte konfiguriert, die bei der Erstellung von Zertifikaten zum Einsatz kommen. Die Variable KEY_SIZE sollte auf jeden Fall auf 2048 gesetzt werden (der höhere Rechenaufwand ist selbst für moderne ARM-Boards vertretbar). Des Weiteren können noch die Gültigkeitsdauer der Certificate Authority (CA) und der eigentlichen Zertifikate sowie allgemeine Informationen zur CA (KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG und KEY_EMAIL) angegeben werden. Die weiteren Werte sind für uns nicht weiter interessant.
  2. Wir führen source ./vars zum Laden der eben angepassten Informationen aus.
  3. ./clean-all legt Dateien an, in denen Infos über erzeugte Zertifikate eingetragen werden. (Darf nach der Erstellung der CA auf keinen Fall mehr ausgeführt werden, da dies sonst sämtliche Zertifikate und Schlüssel löscht!)
  4. ./build-ca erzeugt schließlich die CA. Hierbei wird die Konfiguration von eben nochmal durchgegangen. Die meisten können mit Enter bestätigt werden, bei Organizational Unit Name, Common Name und Name kann z. B. CA eingetragen werden.

Erstellung des Server-Zertifikats
Zur Ausstellung von Nutzerzertifikaten brauchen wir ein Server-Zertifikat, mit dem unser OpenVPN-Server arbeiten wird. Dieses erstellen wir mit ./build-key-server openvpn.local. Statt openvpn.local tragen wir unseren Fully Qualified Domain Name (FQDN) ein, sofern denn eine Domain vorhanden ist (falls nicht, ist es auch nicht schlimm: OpenVPN funktioniert auch mit openvpn.local o. Ä.). Neben weiteren optionalen Angaben wird nach einem challenge password gefragt, das wir mit Enter bestätigen, da wir die Signierungs-Anfrage nicht an eine externe CA schicken, sondern jetzt gleich signieren: Sign the certificate? bestätigen wir mit y, ebenso wie die folgende Frage.

Nun erstellen wir mit ./build-dh einen Schlüssel für das Diffie-Hellmann-Verfahren, der sich anschließend in ./keys/dh2048.key befindet.

Im nächsten Schritt erstellen wir einen Pre Shared Key (PSK), der zusätzlich zur Authentifikation auf dem Server und allen Clients verteilt wird. Das wäre im Grund nicht zwingend nötig, verringert aber bei einer fehlgeschlagenen Authentifikation den Rechenaufwand und schwächt somit z. B. DoS-Attaken ab.
openvpn --genkey --secret ./keys/hmac.key

Erstellen des Nutzerzertifikats
Für die Nutzerzertifikate rufen wir einfach ./build-key servername auf — in unserem Fall für unseren Webserver z. B. ./build-key www. Wir beantworten wieder die gestellten Fragen entsprechend unserer Bedürfnisse, vergeben kein challenge password und lassen die Zertifikate signieren.

Jetzt haben wir sämtliche Zertifikate und Schlüssel, die wir brauchen:

  • openvpn.local.crt, openvpn.local.key und dh2048.key nutzen wir auf dem VPN-Server.
  • www.crt, www.key nutzen wir auf dem Webserver.
  • ca.crt hmac.key werden sowohl vom VPN-Server als auch vom Webserver genutzt.
  • Die csr-Dateien brauchen wir nicht mehr.

Server-Konfiguration von OpenVPN

Nehmen wir an, wir wollen OpenVPN über UDP / Port 2345 betreiben. Die OpenVPN-Konfigurationsdatei könnte dann z. B. wie folgt aussehen:

Server-IP: 10.1.2.1
/etc/openvpn/server.conf:


# Port, Layer-3-Kommunikation (TUN) und Protokoll konfigurieren
port 2345
dev tun
proto udp
topology subnet
# Adresspool des VPN-Servers
server 10.1.2.0 255.255.255.0
#
# Zertifikate und Schluessel
dh /etc/openvpn/keys/dh2048.pem
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/openvpn.local.crt
key /etc/openvpn/keys/openvpn.local.key
# TLS-Auth mit PSK (schwaecht DoS-Attaken ab)
tls-auth /etc/openvpn/keys/hmac.key
#
keepalive 10 60
# Komprimierung aktivieren
comp-lzo
persist-key
persist-tun
# nur Clients mit CCD-Konfiguration zulassen
client-config-dir /etc/openvpn/ccd
ccd-exclusive
#
# Logs und Log-Ausgabe-Level konfigurieren
status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3

Diese Konfiguration tragen wir in die Datei /etc/openvpn/server.conf ein. Unser VPN-Server nutzt die IP-Adresse 10.1.2.1 die eben erstellten Schlüssel- und Zertifikatsdateien kopieren wir, wie angegeben, in den Ordner /etc/openvpn/keys/.

Unter /etc/openvpn/ erstellen wir nun einen Ordner ccd, der als Client Config Dir bezeichnet wird und es ermöglicht, nur von den Clients eine Verbindung aufbauen zu lassen, die eine Datei mit ihrem Common Name im ccd-Verzeichnis besitzen.
Für unseren Webserver mit dem Common Name www kann dies z. B. wie folgt aussehen (/etc/openvpn/ccd/www):


ifconfig-push  10.1.2.2 255.255.255.0
push "topology subnet"

Dem Client wird also die IP-Adresse 10.1.2.2 zugewiesen.

Mit openvpn /etc/openvpn/server.conf sollte sich nun der VPN-Server starten lassen.

VPN-Konfiguration auf dem OpenVPN-Client

Auf dem Client legen wir eine Datei /etc/openvpn/client.ovpn mit folgendem Link an:


remote STATISCHEIP 2345
dev tun
proto udp
client
tun-mtu 1500
#
ca ca.crt
cert server.crt
key server.key
# PSK fuer TLS-Auth
tls-auth hmac.key
#
comp-lzo
verb 3

Den Platzhalter STATISCHEIP ersetzen wir durch die statische IP-Adresse unseres vServers. Die angegebenen Schlüssel- und Zertifikatsdateien kopieren wir in den selben Ordner, wie die ovpn-Datei.

Nun tragen wir in /etc/rc.local (überhalb von exit 0) noch folgendes ein:
cd /etc/openvpn && openvpn ./client.ovpn &.
Anschließend sollte bei einem Systemstart automatisch der Tunnel aufgebaut werden. Getestet werden kann dies mit openvpn /etc/openvpn/client.ovpn.

iptables-Konfiguration

Wenn der Aufbau des Tunnels funktioniert, müssen wir auf dem vServer noch die iptables-Konfiguration nachholen:

Das iptables-Skript leitet Anfragen an die Ports 80 (HTTP) und 443 (HTTPS) an den per VPN verbundenen Server weiter und kann leicht an die eigenen Bedürfnisse angepasst werden. Während der Arbeit am Skript ist bei einem Zugriff über SSH Vorsicht geboten, ansonsten ist es schnell passiert, dass man sich vom SSH-Zugang selbst aussperrt!

Zunächst wird einiges an “Vorarbeit” erledigt und kurzzeitig die Filterketten auf ACCEPT gesetzt, bis das Regelwerk formuliert wurde sowie ggf. schon vorhandene Regeln zurückgesetzt:


# temporaer Default Policy auf ACCEPT setzen und Filterketten zuruecksetzen:
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F

Zudem wird das Loopback Interface (lo) von der Firewall-Konfiguration ausgeschlossen:

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Anschließend werden der SSH-Zugang und DNS sowie ggf. ICMP zugelassen:

# SSH zulassen
# Fuer alle IP-Adressen auf Port 22
# (kann zur Sicherheit weiter eingeschraenkt und auf einen anderen Port gestellt werden)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
#
# ICMP zulassen (z.B. fuer Ping)
# iptables -A OUTPUT -p icmp -j ACCEPT
# iptables -A INPUT -p icmp -j ACCEPT
#
# DNS zulassen
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j ACCEPT

Nun werden Anfragen an OpenVPN zugelassen (der Interface-Name (venet0) muss entsprechend des auf dem vServer genutzten angepasst werden):

# OpenVPN zulassen
iptables -A OUTPUT -o venet0 -p udp --sport 2345 -j ACCEPT
iptables -A INPUT -i venet0 -p udp --dport 2345 -j ACCEPT

Im nächsten Schritt werden die umzuleitenden Dienste konfiguriert — in diesem Fall HTTP und HTTPS:

# HTTP zulassen
iptables -A FORWARD -d 10.1.2.2 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 10.1.2.2 -p tcp --sport 80 -j ACCEPT
iptables -t nat -F PREROUTING
iptables -t nat -A PREROUTING -d STATISCHEIP -p tcp --dport 80 -j DNAT --to-destination 10.1.2.2
#
# HTTPS zulassen
iptables -A FORWARD -d 10.1.2.2 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 10.1.2.2 -p tcp --sport 443 -j ACCEPT
iptables -t nat -A PREROUTING -d STATISCHEIP -p tcp --dport 443 -j DNAT --to-destination 10.1.2.2

Danach müssen IP Forwarding und NAT aktiviert werden. Die folgenden auskommentierten Zeilen sind nur nötig, wenn der VPN-Server als Gateway für z. B. Systemupdates genutzt wird.

# Forwarding aktivieren
echo "1" > /proc/sys/net/ipv4/ip_forward
#
# NAT zulassen
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
# -----------------------
# Noetig, wenn VPN-Server als Gateway genutzt wird:
# Ausgehenden HTTP(S)-Datenverkehr erlauben (z. B. fuer Updates)
# iptables -A FORWARD -s 10.1.2.2 -p tcp --dport 80 -j ACCEPT
# iptables -A FORWARD -d 10.1.2.2 -p tcp --sport 80 -j ACCEPT
# iptables -A FORWARD -s 10.1.2.2 -p tcp --dport 443 -j ACCEPT
# iptables -A FORWARD -d 10.1.2.2 -p tcp --sport 443 -j ACCEPT
# iptables -A FORWARD -p icmp -j ACCEPT
# iptables -A FORWARD -p udp --dport 53 -j ACCEPT
# -----------------------

Abschließend erfolgt ein sehr wichtiger Schritt: Die Default Policy der Filterketten INPUT, FORWARD und OUTPUT wird auf DROP gesetzt und damit die Firewall-Funktion aktiviert:

# Default Policy auf DROP setzen
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

Nun muss das iptables-Regelwerk nur noch beim Serverstart automatisch geladen werden. Hierzu können wir uns einen Dienst anlegen; unter Debian reicht es aber auch aus, einen Eintrag in /etc/rc.local zu erstellen, der das Skript beim Systemstart ausführt: /etc/firewall.sh. Zusätzlich muss die Datei natürlich noch mit chmod u+x firewall.sh ausführbar gemacht werden.

Wenn bis hierin alles geklappt hat, ist nun der Webserver im lokalen Netz per IPv4-Adresse aus dem Internet erreichbar. Vielleicht noch ein kleiner Schönheitsfehler: Es fehlt nur noch ein Domain-Name, der auf unseren Server zeigt ;).

Autor

Kommentare

Keine Kommentare

Kommentare

Geben Sie Ihren Kommentar hier ein. * Eingabe erforderlich. Sie müssen die Vorschau vor dem Absenden ansehen.





← Älter Neuer →