Mit OpenVPN ins Internet

Vorwort

Ein VPN (Virtual Private Network) ist ja eigentlich eher dazu gedacht, sich von zuhause aus mit einem Firmennetzwerk verbinden zu können. Wer aber seinem Provider misstraut oder Sicherheit durch Verschlüsselung (u.A. auch Anonymität) im Internet erlangen möchte, der sollte sich einen russischen Server mieten und darauf OpenVPN installieren ;-) Quatsch, zu welchen Zwecken auch immer meine Leser ein VPN benutzen möchten fällt nicht in meine Zuständigkeit. Also zur Anleitung:

System

Mein OpenVPN-Server läuft auf einem vServer mit Debian Linux, deshalb bezieht sich auch die Anleitung darauf. Ich und einige Bekannte haben die Clients auf unterschiedlichen Systemen in Verwendung, z.B. Windows XP x86/x64, Windows Vista x86/x64, Windows 7 RC1 x64, Ubuntu x86/x64, das ist aber dank der Verfügbarkeit der auf diese Systeme portierten VPN-Clients kein Problem. Die aktuelle Version der Client-Software muss natürlich noch heruntergeladen werden. Hier noch der Version-String des verwendeten Servers:

OpenVPN 2.1_rc11 x86_64-pc-linux-gnu [SSL] [LZO2] [EPOLL] [PKCS11] built on Sep 18 2008
Developed by James Yonan
Copyright (C) 2002-2008 Telethra, Inc. <sales@openvpn.net>

Für den Windows-Client sollte man darauf achten, dass erst ab Version 2.1_rcXX Windows Vista/7 in der 64-Bit Variante unterstützt wird.

Installation

Server

Der Server-Dienst muss zunächst mal installiert werden (root-Rechte notwendig):

aptitude install openvpn

Nun entpackt man die mitgelieferten Hilfsmittel zur Erstellung der Zertifikate:

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
gunzip /etc/openvpn/server.conf.gz
cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa2
mkdir -p /etc/openvpn/easy-rsa2/keys

Unter verschiedenen Ubuntu-Versionen kann es sein, dass das easy-rsa-Verzeichnis schon vorhanden ist.

Schlüssel und Zertifikate

Grundsätzlich benötigt der Server ein Zertifikat, damit die Clients auch wissen, dass das auch wirklich der Server ist, auf den sie connecten möchten. Meine Methode verlangt, dass für jeden Client ebenfalls ein Zertifikat erstellt wird. Man könnte dies auch mit PAM lösen, so dass Benutzername und Passwort abgefragt werden, doch für einen Auto-Login ist ein Zertifikat/Schlüssel sehr komfortabel und sicher, solange diese nicht gestohlen werden.

Server

Zuerst editiert man die Datei /etc/openvpn/easy-rsa2/vars un passt folgende Zeilen an seine eigenen Daten an:

export KEY_COUNTRY="AT"
export KEY_PROVINCE="STMK"
export KEY_CITY="Your City"
export KEY_ORG="example.net"
export KEY_EMAIL="nefarius@example.net"

Jetzt können die eben gesetzten Umgebungsvariablen der aktuellen Shell zugewiesen werden:

source /etc/openvpn/easy-rsa2/vars

Nun kann der Master-Schlüssel, der den Server identifiziert, erstellt werden:

/etc/openvpn/easy-rsa2/clean-all
/etc/openvpn/easy-rsa2/build-ca
/etc/openvpn/easy-rsa2/build-key-server server

Client(s)

Für die Erstellung der Client-Zertifikate müssen die obrigen Schritte bis zur Erstellung des Master-Server-Zertifikats durchgeführt worden sein. Anschließend lassen sich pro Client mit diesem einfachen Befehl die Zertifikate/Schlüssel erstellen:

/etc/openvpn/easy-rsa2/build-key namedesclients

Hat man Server- und Client-Zertifikate erstellt, muss abschließend noch der Diffie-Hellman-Parameter generiert werden:

/etc/openvpn/easy-rsa2/build-dh

Die Client-Zertifikate und -Schlüssel müssen abschließend an die Client-Rechner verteilt werden.

Konfiguration

TUN oder TAP

Auf dem OpenVPN-Server muss in jedem Fall das IP-Forwarding (Routing) eingestellt sein, damit die Pakete auch weiterkommen und nicht verworfen werden. Es gibt zwei Arten von Devices bei OpenVPN, die für unterschiedliche Anwendungsarten verwendet werden.

tun-Device

Durch den VPN-Tunnel können mit diesem Device alle gängigen Netzwerkprotokolle auf IP-Layer 3 übermittelt werden. So ist es möglich Daten zu kopieren und E-Mails zu lesen, als wäre man in diesem LAN. Durch Routing wird die Übermittlung der Daten durch die verschiedenen Netzwerke geregelt.

Beispiel: Du möchtest über den Tunnel lediglich Surfen, E-Mails abrufen und Chatten, dafür eignet sich das TUN-Device am besten.

tap-Device

Das tap-Device wird verwendet beim Bridging. Die einfachste Form wäre, wenn zwei Netze - das virtuelle VPN-Netz und das lokale Netzwerk - über eine Netzwerk-Brücke miteinander verbunden und im selben Subnetz vereint sind. Auch werden alle Broadcasts durch diese Art von Verbindung durchgelassen. Dies kann beispielsweise bei Netzwerk-Spielen erforderlich sein.

Beispiel: Du willst über den Tunnel auch Netzwerkspiele mit anderen Tunnel-Teilnehmern spielen, auf Windows-Freigaben zugreifen oder LAN-Chats nutzen. Das TAP-Device ermöglicht das dank Tunneln des Broadcast-Traffics.

Server

Jetzt kann man in der /etc/openvpn/server.conf folgende Konfiguration eintragen:

server.conf
# IP Adresse des Interfaces, an das du den Server binden möchtest 
# (auskommentieren, falls an alle gebunden werden soll)
local xxx.xxx.xxx.xxx
 
# Zu verwendendes Protokoll 
# (TCP empfiehlt sich, wenn man hinter einer Firewall sitzt, sonnst 
# ist UDP wegen der Geschwindigkeit vorzuziehen)
proto tcp
 
# Erzeuge das Tunnel-Device (IP Tunnel)
dev tun
 
# Die folgenden Zeilen geben die Pfade zu den Zertifikaten an und
# müssen korrekt sein
ca ./easy-rsa2/keys/ca.crt
cert ./easy-rsa2/keys/server.crt
key ./easy-rsa2/keys/server.key  # Diese Datei muss geheim bleiben
 
# Diffie Hellman Schlüssel
dh ./easy-rsa2/keys/dh1024.pem
 
# Subnetz, welches der Server erzeugen soll 
# (darf keines der vorhandenen privaten Netzwerke sein!)
server 10.8.0.0 255.255.255.0
 
# In dieser Datei speichert der Server die Client-IPs
ifconfig-pool-persist ipp.txt
 
# Gebe dem Client Routen-Informationen mit, damit dieser 
# das private Subnetz findet
push "route 10.8.0.0 255.255.255.0"
 
# Damit wird erzwungen, dass am Client alle Anfragen 
# (DNS, Browser) über den Tunnel laufen
push "redirect-gateway"
 
# Wichtig für Windows-Nutzer:
# trägt das Standardgateway in den TUN/TAP-Adapter ein
push "route 0.0.0.0 0.0.0.0"
 
# Hier werden die Adressen von OpenDNS mitgeschickt, damit 
# die Namensauflösung ebenfalls durch den Tunnel geschieht
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option WINS 208.67.220.220"
 
# Clients können sich auch "sehen", nicht nur 
# die Clients den Server
client-to-client
 
# Pinge alle 10 Sekunden um Verbindung aufrecht zu erhalten
keepalive 10 120
 
# Hash-Algorithmus
auth SHA1
 
# Schnelle und sichere Blowfish-Verschlüsselung
cipher BF-CBC
 
# Kompression
# (wenn angegeben, müssen auch alle Clients dies unterstützen!)
comp-lzo
 
# Bindet laufenden OpenVPN Prozess an Account ohne spezielle Rechte 
# (User und Gruppe müssen existieren)
user openvpn
group openvpn
 
# Verbindung immer gleich halten
persist-key
persist-tun
 
# Optionen fürs Logging
status openvpn-status.log
log-append  openvpn.log
 
# "Verbose" Level - Logge nur Fehler
verb 3

Als DNS-Server verwende ich die Adressen 208.67.222.222 und 208.67.220.220 von OpenDNS. Wer sich dort anmeldet, kann sein Servernetzwerk registrieren und so komplett kostenlos Statistiken über den Traffic/Domains erhalten. Ein Feature, das mir persönlich am besten gefällt, ist der wirklich sehr gute Filter, mit dem sich eine Unmenge an Kategorien sperren lässt (Pornographie, Spiele, etc.), also wirklich ideal für Betreiber größerer Netzwerke. Natürlich können „deutlich versiertere Benutzer“ so eine DNS-Sperre leicht umgehen ;-) Dagegen würde ein transparenter Proxy helfen.

Client

Der OpenVPN-Client enthält (egal ob Windows oder Linux) auch ein Verzeichnis für die Konfigurationsdatei (z.B. C:\Program Files (x86)\OpenVPN\config\client.ovpn). Diese sollte mindestens folgende Konfiguration beinhalten:

client.ovpn
# OpenVPN-Instanz als Client starten
client
 
# Je nach Verwendungszweck verwende TUN oder TAP
dev tun
 
# Nutze Protokoll TCP um durch Firewalls zu kommen
# andernfalls sollte man UDP verwenden (höherer Speed)
proto tcp
 
# Adresse und Port des VPN-Servers
remote xxx.xxx.xxx.xxx 443
 
# Endloser Reconnect-Versuch
resolv-retry infinite
 
# Beliebiger lokaler Port
nobind
 
# Verbindung immer gleich halten
persist-key
persist-tun
 
# Falls Proxy vorhanden, hier einstellen
;http-proxy-retry # retry on connection failures
;http-proxy [proxy server] [proxy port]
 
# Pfade zu den Zertifikaten (müssen auf jeden Fall stimmen!)
ca "C:\\Program Files (x86)\\OpenVPN\\easy-rsa\\keys\\ca.crt"
cert "C:\\Program Files (x86)\\OpenVPN\\easy-rsa\\keys\\client.crt"
key "C:\\Program Files (x86)\\OpenVPN\\easy-rsa\\keys\\client.key"
 
# Authentifizierung per Zertifikaten
ns-cert-type server
 
# Hash-Algorithmus
auth SHA1
 
# Schnelle und sichere Blowfish-Verschlüsselung
cipher BF-CBC
 
# Kompression
comp-lzo
 
# Log-Level
verb 3

Nun sollte man bereits eine Verbindung zum Server herstellen können, für weitere Parameter der Konfigurationsdatei siehe Weblinks.

Tips & Tricks

Hier finden sich ein paar Anmerkungen oder alternative Konfigurationen, die auf andere Einsatzszenarien zugeschnitten sind.

Port-Sharing

Da der Großteil der Firewalls/Zwangsproxys nur gesicherte Verbindungen über den einen Port 443 erlaubt, ist man gezwungen, den VPN-Server auf diesen zu binden. Doch was tun, wenn man mit derselben IP eine HTTPS-Verbindung zum darauf lauschenden Webserver herstellen möchte? Kein Problem, OpenVPN hat auch hierfür eine Lösung implementiert: Port-Sharing.

Hierzu ist lediglich eine kleine Modifikation der server.conf notwendig:

# Das zu bindende Interface _muss_ angegeben werden, z.B. die IP von eth0
local xxx.xxx.xxx.xxx
# Das dürfte wohl logisch sein ;)
port 443
# Nun die Magische Zeile
port-share 127.0.0.1 443

Nun wird jeglicher Nicht-VPN-Traffic an den Dienst weitergeleitet, der auf 127.0.0.1:443 lauscht, unser Webserver (in diesem Fall Apache2). Dessen Konfiguration muss nun angepasst werden:

/etc/apache2/ports.conf
NameVirtualHost *:80
Listen 80
 
<IfModule mod_ssl.c>
    # SSL name based virtual hosts are not yet supported, therefore no
    # NameVirtualHost statement here
    Listen 127.0.0.1:443
</IfModule>

Default-Gateway wird nicht geändert

Das Problem sollte eigentlich mit dem TUN/TAP-Treiber ab der Version 9.6 behoben worden sein. Sollte es weiterhin bestehen gibt es hierzu eine Lösung:

# In die client.conf
redirect-gateway def1 bypass-dhcp

Verbindung via UMTS/HSDPA funktioniert nicht

Viele Anbieter von Mobilfunk-Internet Zugängen verwenden eine DialUp/PPP-Mixtur, mit der OpenVPN per Default nicht klar kommt. Das Ändern des Gateways über UMTS bzw. HSDPA Verbindungen kann allerdings mit einer kleinen Anpassung der Client-Konfiguration erzwungen werden:

# unbedingt auskommentieren und statt dessen die folgenden 3 Direktiven verwenden!
;redirect-gateway
redirect-gateway def1
route-method exe
route-delay 2

BitTorrent DHT/PEX funktioniert nicht, Downloads sind langsam

Sollte man auf die Idee kommen, durch diesen Tunnel BitTorrent Daten zu schleusen, kann (oder wird) die Geschwindigkeit langsamer sein als ohne Tunnel. Das liegt daran, dass beim Großteil der eingesetzten Internetverbindungen das UPnP des Routers bereits alle nötigen Ports öffnet (oder man kein/e NAT/Firewall hat) und somit DHT und die essentiellen eingehenden Verbindungen freie Bahn haben. Unser Tunnel ist so wie er konfiguriert ist nicht auf eingehende Verbindungen getrimmt, das lässt sich aber leicht mit diesen iptables-Regeln auf dem Server ermöglichen:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 30913 -j DNAT --to 10.8.0.6
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 30913 -j DNAT --to 10.8.0.6

Wobei 30913 jener Port ist, auf dem auch der Torrent-Client lauscht (je nach Client individuell einstellbar) und 10.8.0.6 die VPN-IP des Nutzers mit dem Wunsch nach den Bitströmen ;-) Wenn mehrere VPN-Nutzer Torrent-Traffic tunneln wollen, müssen verschiedene Ports an deren IPs vergeben werden.

MASQUERADE funktioniert nicht auf meinem System!

Das Problem

Wer mit seiner Maschine Netzwerk-Traffic aus verschiedenen (virtuellen) Netzen in die Weiten des Internets routen will, verwendet dafür üblicherweise die Standardlösung:

iptables -t nat -A POSTROUTING -o venet0:0 -s 10.8.0.0/24 -j MASQUERADE

wobei 10.8.0.0/24 für das private Subnetz in CIDR-Notation steht. MASQUERADE teilt dem Kernel mit, dass die Source-IP der aus dem 10.8.0.0/24-Netz kommenden Pakete auf die des Interfaces venet0:0 umgeschrieben werden soll. Die Pakete aus dem fremden Netz werden also „maskiert“, damit sie auch wieder den Weg zurück aus dem Internet finden. Kommt ein Antwort-Paket zurück, wird der Vorgang umgekehrt und das Paket an die „Ur-IP“ aus dem privaten Subnetz weiter geroutet.

Aufgrund eines fehlenden Modules schlägt das in der Welt von OpenVZ fehl.

Die Lösung

Das bedeutet jedoch keinesfalls das Ende aller Tage, mit SNAT (Source Network Address Translation) lässt sich das gewünschte Szenario ebenfalls aufbauen:

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j SNAT --to-source 186.20.153.46

Neben dem Ausgangs-Interface ist noch die Angabe der Source-IP notwendig, die der des Interfaces entspricht. Für bequeme Administratoren habe ich den Befehl etwas erweitert:

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j SNAT --to-source $(ifconfig venet0:0 | grep -i 'inet' | cut -d: -f2 | awk '{ print $1}')

Die IP von venet0:0 wird automatisch eingetragen, bei Bedarf ist der Bezeichner gegen das gewünschte Interface zu wechseln. Viel Erfolg beim Tunneln :-)

Route einrichten

Damit man auch ins Internet gelangen kann, muss man der Server-Firewall (in diesem Fall iptables) noch eine Regel mit geben und das IP-Forwarding aktivieren. Damit folgende Änderungen auch nach dem Reboot bestehen, sollte man sie am besten in die /etc/rc.local eintragen.

# initialize natting for openvpn
iptables -t nat -F POSTROUTING
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE

Nun sollte man problemlos ins Internet gelangen können. Falls man das mit seinem privaten Internetanschluss testen möchte, sollte unter http://www.wieistmeineip.at/ die IP-Adresse des eth0-Interfaces des Servers aufscheinen.

Quellen

Kommentare