Openvpn

Aus Gentoo Linux Wiki

Wechseln zu: Navigation, Suche
Dieser Artikel ist Teil der Security Sammlung.
Firewall Dienste absichern Verschlüsselung alphabetischer Security Index


Inhaltsverzeichnis

[Bearbeiten] Einleitung

Der folgende Artikel basiert auf openvpn-2.0.6. Er beschreibt, wie zwei Systeme (VPN-Client/-Server), die über ein unsicheres Medium miteinander verbunden sind, sicher miteinander kommunizieren können.
Informationen: http://openvpn.net/howto.html

Szenario
192.168.1.10 192.168.1.1 88.88.88.1 99.99.99.1 192.168.2.1 192.168.2.10 VPN-Client ----------------> NAT-Router1 ------------> NAT-Router2 --------|-> VPN-Server LAN ...INTERNET... LAN |-> HTTP-Server (.11) |-> weitere Server...

Auf die Konfiguration der NAT-Router wird hier nicht eingegangen. Wichtig ist v.a., dass auf NAT-Router2 ein Portforwarding von Port udp/1194 zum VPN-Server eingetragen wird. Voraussetzung für das Funktionieren ist ferner, dass Pakete zwischen VPN-Client und VPN-Server geroutet werden, was in Firmennetzen nicht unbedingt der Fall ist ("proxy"). Wie man eine openvpn-Verbindung über einen http-proxy-Server leiten kann, ist hier beschrieben: http://openvpn.net/howto.html#http

[Bearbeiten] Vorarbeiten: Client+Server

Code: Client+Server: Installieren von openvpn
emerge -av net-misc/openvpn

In der Kernel-Konfiguration muss der tun-Treiber aktiviert sein, am besten als Modul. Das Modul wird von openvpn automatisch geladen, es braucht nicht in /etc/modules.autoload/kernel-2.6xxx eingetragen zu werden.

Client+Server: Kernel Konfiguration
Device Drivers --->
   Network device support --->
    <M> Universal TUN/TAP device driver support

Kernel kompilieren make make modules_install usw.

[Bearbeiten] Server

[Bearbeiten] Generierung der Private-Keys und X509-Zertifikate

Die Datei "/etc/openvpn/easy-rsa/vars" enthält grundlegende Variablen, die von den Scripten zur Zertifikatserstellung (s.u.), die in openvpn mit enthalten sind, ausgewertet werden. Falls diese nicht vorhanden sein sollte, muss diese aus "/usr/share/openvpn" kopiert werden, da andernfalls individuelle Einstellungen nach einem Update von openvpn verloren gehen.

Code: vars-File kopieren
cd /etc/openvpn
mkdir easy-rsa
cd easy-rsa
cp /usr/share/openvpn/easy-rsa/vars ./ -v
# `/usr/share/openvpn/easy-rsa/vars' -> `./vars'
ln -sv /usr/share/openvpn/easy-rsa/{build-ca|build-key|build-dh|build-key-server|clean-all|pkitool|openssl.cnf}


Danach kann die Datei "vars" angepasst werden. Überflüssige Kommentarzeilen können hierbei gelöscht werden, was zur Übersichtlichkeit beträgt.

Datei: /etc/openvpn/easy-rsa/vars
export EASY_RSA="/etc/CertAuth"
export KEY_CONFIG="$EASY_RSA/openssl.cnf"
export KEY_DIR="$EASY_RSA/keys"
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
export KEY_SIZE=2048   # 1024 wäre nicht ganz so sicher und 4096 ist noch übertrieben
export CA_EXPIRE=9999  # ca. 27,4 Jahre Gültigkeit
export KEY_EXPIRE=9999
export KEY_COUNTRY="DE"
export KEY_PROVINCE="Deutschland"
export KEY_CITY="Ostfildern"
export KEY_ORG="SK"               # Firmennamen besser "anonym" lassen
export KEY_EMAIL="root@localhost" # besser eine neutrale Mailadresse verwenden


[Bearbeiten] Key/Zertifikat der Certificate-Authority (CA)

Der Private-Key der CA dient dazu, Server- und Client-Zertifikate zu signieren. Um die Sicherheit nicht zu gefährden, muss er unter allen Umständen geheim bleiben. Er sollte sich auf einem Standalone-Rechner befinden, zu dem nur befugte Personen Zugang haben. Zwecks einfacherer Darstellung befindet sich die CA in diesem Artikel auf dem VPN-Server. Um die Sicherheit auch in diesem Falle zu gewährleisten, wird der CA-Private-Key durch ein Kennwort geschützt und nach Erstellung der Server-/Client-Zertifikate auf zwei externe Medien (USB-Stick+DVDRAM) verschoben, die im Safe zu deponieren sind.

Code: CA-Zertifikat/Key generieren
cd /etc/openvpn/easy-rsa
source vars # nach jeder Änderung in "vars" muss die Datei "gesourced" werden.
./clean-all # evtl. vorhandene Zertifikatsdateien in KEY_DIR werden gelöscht!!
./build-ca --pass  # Zugriff auf CA-Private-Key wird durch ein Passwort geschützt
# Passwort -> kein triviales Kennwort verwenden!
# "Organizational Unit Name" -> leer lassen
ls /etc/openvpn/easy-rsa/keys/ca* # ca.crt (Zertifikat) ca.key (Private-Key)
openssl x509 -in /etc/openvpn/easy-rsa/keys/ca.crt -text -noout | less # Zertifikat prüfen
openssl rsa  -in /etc/openvpn/easy-rsa/keys/ca.key -text -noout | less # Key anschauen


[Bearbeiten] Key/Zertifikat des VPN-Servers

Bei der Erstellung des Server-Zertifikats ist es wichtig, einen "individuellen" Common Name zu vergeben, der Ihre VPN-Verbindung eindeutig kennzeichnet. Die Bezeichnung sollte trotzdem "anonym" sein, um möglichst wenig Informationen über Ihre Systeme nach außen preiszugeben. Der Common Name taucht in der Client-Konfigurationsdatei wieder auf und dient dazu, man-in-the-middle-Angriffe zu verhindern: http://openvpn.net/howto.html#secnotes

Code: Server-Zertifikat und -Key generieren
./build-key-server xyz-Server # xyz-Server: individuelle, aber "anonyme" Bezeichnung
# "challenge password" -> leer lassen
# "An optional company name" -> leer lassen
# "Sign the certificate? [y/n]" -> y
# "1 out of 1 certificate requests certified, commit?" -> y
rm /etc/openvpn/easy-rsa/keys/server.csr # wird nicht benötigt, da Key/Zertifikat zugleich erstellt werden
ls /etc/openvpn/easy-rsa/keys/server.*   # server.crt server.key
# Ersetze "server" durch den gewählten Common Name (z.B. "xyz-Server.csr").


[Bearbeiten] Key/Zertifikat des/der VPN-Clients

Nach den kryptographischen Grundregeln darf der Private-Key das Gerät, auf dem er erstellt wird, nicht verlassen. Der Private-Key müsste folglich auf dem Client selbst generiert werden. Zwecks einfacherer Darstellung wird im folgenden der Key auf dem VPN-Server generiert und über einen sicheren Kanal (scp...) auf den/die Clients übertragen.

Code: Client-Zertifikat und -Key generieren
./build-key client1 # Angaben analog zum Server-Zertifikat
rm /etc/openvpn/easy-rsa/keys/client1.csr # wird nicht benötigt, da Key/Zertifikat zugleich erstellt werden
ls /etc/openvpn/easy-rsa/keys/client1.* # client1.crt client1.key


[Bearbeiten] Diffie Hellman Parameter

Code: Diffie Hellman Parameter generieren
./build-dh # dauert ca. 5-10 min., je nach KEY_SIZE in "vars"
ls /etc/openvpn/easy-rsa/keys/dh* # dh2048.pem (bzw. dh1024.pem, je nach KEY_SIZE)


[Bearbeiten] statischer "preshared" Key

Zusätzliche Sicherheit wird durch einen statischen Key ("preshared secret") erreicht, der auf allen VPN-Systemen vorhanden sein muss.

Code: statischen Key generieren
openvpn --genkey --secret /etc/openvpn/easy-rsa/keys/ta.key
ls /etc/openvpn/easy-rsa/keys/ta.key # ta.key


[Bearbeiten] Verteilen der Dateien

Beim Kopieren von Private-Key und statischem Key auf den Client wird davon ausgegangen, dass ssh richtig konfiguriert ist und der scp-Befehl daher eine sichere Übertragung ermöglicht.

Code: Dateien ins openvpn-Verzeichnis und auf Client kopieren
cd /etc/openvpn/easy-rsa/keys
cp ca.crt ta.key dh2048.pem server.* /etc/openvpn/
scp ca.crt ta.key client1.* 88.88.88.1:/etc/openvpn/
# klappt nur, wenn auf NAT-Router1 Portforwarding von Port tcp/22 zum Client aktiviert ist


[Bearbeiten] Auslagern des CA-Keys

Wenn man keinen separaten Root-CA-Server verwenden möchte, sollte man zumindest den CA-Key auslagern.

Code: Auslagern des CA-Keys
mount /dev/sdb1 /mnt/usbstick
mount /dev/dvd  /mnt/dvdram
cp -a /etc/CertAuth/keys/ca.key /mnt/usbstick
cp -a /etc/CertAuth/keys/ca.key /mnt/dvdram
if [[ -e /mnt/usbstick/ca.key && -e /mnt/dvdram/ca.key ]] ; then rm /etc/CertAuth/keys/ca.key ; fi
umount /dev/sdb1 /dev/dvdram


Tipp: Sofern das Programm shred installiert ist, empfiehlt es sich, die Datei /etc/CertAuth/keys/ca.key vor dem Entfernen damit zu bearbeiten, um ein Wiederherstellen zu erschweren. (Anmerkung: Bei sogenannten Journaling-Dateisystemen ist dieses Vorgehen sinnlos, da shred hier nicht funktioniert) Dieser Tipp gilt natürlich für alle "wichtigen" Schlüssel, die man löschen möchte. Es ist noch zu beachten, dass shred die Datei nur unbrauchbar macht, also den Platz auf dem Datenträger überschreibt. Die Datei muss anschließend noch gelöscht werden. Leider bewirkt shred bei journaling filesystems (wie z.B. reiserfs) nicht, dass der Dateiinhalt tatsächlihch von der Festplatte gelöscht wird. Wenn man den ca.key jedoch mit einem starken Kennwort verschlüsselt, wie in diesem Artikel vorgeschlagen, ist er relativ gut geschützt, selbst wenn er auf der Festplatte bleibt. Wenn es sehr auf Sicherheit ankommt, sollte man ohnehin einen standalone Root-CA-Server verwenden.

[Bearbeiten] Konfiguration von openvpn

Code: Gruppe/User "openvpn" und chroot-Verzeichnis anlegen
groupadd openvpn
useradd -d /dev/null -g openvpn -s /bin/false openvpn
mkdir /etc/openvpn/chroot


Zur Erklärung der einzelnen Parameter verweise ich auf: http://openvpn.net/howto.html#examples Der Parameter "push..." bewirkt, dass der vpn-Dämon auf den Clients automatisch eine statische Route setzt, die ihnen ermöglicht, Server, die "hinter" dem VPN-Server liegen zu kontaktieren. Details siehe: http://openvpn.net/howto.html#scope

Datei: /etc/openvpn/openvpn.conf
proto udp
dev tun
local 192.168.2.10  # "bind-adresse": auf welchem Interface soll Port udp/1194 geöffnet werden?
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh2048.pem
tls-auth /etc/openvpn/ta.key 0  # "0" beim VPN-Server, "1" bei VPN-Clients
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/ipp.txt
keepalive 10 120
#cipher BF-CBC  (=Default; sehr schnell)
#cipher AES-128-CBC (sicherer)
#cipher AES-256-CBC (am sichersten)
comp-lzo      # Kompression
user openvpn
group openvpn
persist-key
persist-tun
resolv-retry infinite
status /etc/openvpn/openvpn-status.log
chroot /etc/openvpn/chroot
push "route 192.168.2.0 255.255.255.0"


Code: Init-Script
/etc/init.d/openvpn start
rc-update add openvpn default # zum Default Runlevel hinzufügen


[Bearbeiten] diverse Überprüfungen

Code: Überprüfungen
ps aux | grep openvpn # läuft der Prozess?
less /var/log/messages # Fehlermeldungen? chroot "succeeded"?
less /etc/openvpn/openvpn-status.log # interessant, wenn Client(s) verbunden sind
netstat -tulpen | grep openvpn # udp-port 1194 geöffnet?
lsmod | grep tun # Kernelmodul "tun" geladen?
ifconfig tun0    # Interface vorhanden und mit korrekter IP-Adresse?


[Bearbeiten] funktioniert die chroot?

Code: Prozesse laufen in chroot?!
OPENVPN_PIDS="$(pgrep openvpn)" # welches sind die Prozess-IDs?
for process in $OPENVPN_PIDS; do ls /proc/$process/root; done

Der letzte Befehl prüft, wie die "root" (also das, was man sieht, wenn man "ls /" eingibt) für die openvpn-Prozesse aussieht. Da das Verzeichnis /etc/openvpn/chroot leer ist, dürfte nichts angezeigt werden

[Bearbeiten] Konfiguration des tun-Interfaces

Zur Einrichtung des IP-forwarding zwischen tun0- und eth0-Interface (LAN-Interface des VPN-Servers) eignet sich hervorragend das einfach zu konfigurierende Iptables-Frontend "Firehol". Damit Firehol funktioniert, müssen im Kernel die Iptables-Module aktiviert sein (am besten als Module kompilieren). Firehol lädt die Module selbst, sie brauchen daher nicht in /etc/modules.autoload.d/kernel-2.6xxx eingetragen zu werden. Firehol läuft nicht mit der Bash-Version "bash-3.1_p16", daher sollte die neueste Version verwendet werden.

Code: Installation von Firehol
emerge -av --update bash  # installiert die neueste Version
emerge -av net-firewall/firehol
rc-update add firehol default  # firehol Init-Script ins Default Runlevel aufnehmen


Datei: /etc/firehol/firehol.conf
interface tun0 tun_if  
   policy reject
   server all accept # auf tun0 wird inbound alles erlaubt
   client all accept # auf tun0 wird outbound alles erlaubt
router tun0_to_eth0 inface tun0 outface eth0 # IP-forwarding zwischen tun0 und eth0
   route all accept  # alles wird geroutet, denn tun0 wird voll vertraut.


[Bearbeiten] Konfiguration mit net.tun0/net.tap0 [s. Diskussion!]

Bei einem emerge der aktuellen Version von OpenVPN kommt folgender Hinweistext:

* It is recommended that you create your tun/tap interfaces using
* the net.tun0/net.tap0 scripts provided by baselayout instead of
* using the 'server' directive in openvpn configuration files.
* This will insure that the interface really is up after openvpn
* starts.
* Note that you cannot use net.tun0/net.tap0 and the server option,
* otherwise openvpn will not start.

Es wird also empfohlen, das tun/tap-Device nicht per "server" in der Konfigurationsdatei zu erstellen, sondern mit den, von baselayout gestellten Skripten.

Hintergrund ist, dass OpenVPN beim Start direkt zurückkehrt, das Device aber erst etwas später erstellt wird. Daher kann es dazu kommen, dass Dienste, die versuchen auf dieses zuzugreifen, einen Fehler melden.

[Bearbeiten] Änderungen

Wie oben gesagt, muss "server" entfernt werden. In der man-page steht folgender Ersatz:

Datei: Pseudoersatz für "server" in /etc/openvpn/openvpn.conf
mode server
tls-server

if dev tun:
#  Diese Zeile muss entfernt werden!
#  ifconfig 10.8.0.1 10.8.0.2
   ifconfig-pool 10.8.0.4 10.8.0.251
   route 10.8.0.0 255.255.255.0
   if client-to-client:
      push "route 10.8.0.0 255.255.255.0"
   else
      push "route 10.8.0.1"

if dev tap:
#  Diese Zeile muss entfernt werden!
#  ifconfig 10.8.0.1 255.255.255.0
   ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0
   push "route-gateway 10.8.0.1"
Datei: Zusatz für tun/tap in /etc/conf.d/net
tuntap_vpn="" # <- hier "tun" oder "tap" eintragen!
config_vpn=( "10.8.0.1/24" )
Datei: Änderungen in /etc/openvpn/openvpn.conf
dev vpn
dev-type # hier tun oder tap eintragen


Nun muss nur der Link für net.vpn erstellt und dieser dann zum default-Runlevel hinzugefügt werden.

Code: link erstellen und zum default-runlevel hinzufügen
cd /etc/init.d
ln -s net.lo net.vpn
rc-update add net.vpn default


[Bearbeiten] Kompromitiertes Client-Zertifikat zurücknehmen

Sollte mal ein Client-Zertifikat in irgendeiner Weise kompromitiert werden (z.B. Diebstahl eines Laptops, Einbruch durch bösartige Software/Personen, ...) oder es soll aus einem anderen Grund kein Zugang mehr gewähren werden, muss man das Client-Zertifikat zurücknehmen.

Dieses gilt ausschließlich für die Clients! Sollte der OpenVPN-Server kompromitiert werden, müssen alle Schlüssel neu generiert und verteilt werden!

Code: Client-Zertifikat zurücknehmen
cd /usr/share/openvpn/easy-rsa/
source vars
./revoke-full client1 #hier muss der passender Client eingetragen werden (das Zertifikat muss vorhanden sein: client1.crt)
#Es muss dann zweimal das Passwort für die CA eingegeben werden
#Die letzte Zeile muss einen Fehler enthalten, da überprüft wird, ob das Zerifikat gültig ist.
#oä error 23 at 0 depth lookup:certificate revoked
cp /etc/CertAuth/keys/crl.pem /etc/openvpn/

Es gibt nun eine Datei crl.pem, die die "Ungültigkeitserklärungen" aller ungültigen Zertifikate enthält. Nun muss OpenVPN sie nurnoch benutzen, also noch die Konfiguration anpassen:

Datei: /etc/openvpn/openvpn.conf
crl-verify /etc/openvpn/crl.pem


Diese Datei wird bei jeder neuen Client-Verbindung oder jeder Neuaushandlung (Standard: alle 60 min.) ausgelesen.

[Bearbeiten] Client

[Bearbeiten] Konfiguration von openvpn

Code: Gruppe/User "openvpn" und chroot-Verzeichnis anlegen
groupadd openvpn
useradd -d /dev/null -g openvpn -s /bin/false openvpn
mkdir /etc/openvpn/chroot


Datei: /etc/openvpn/openvpn.conf
remote 99.99.99.1      # IP-Adresse des VPN-Servers bzw. des NAT-Routers
local 192.168.1.10  # "bind-adresse": auf welchem Interface soll Port udp/1194 geöffnet werden?
client              # Client-Modus
proto udp           # möglich wäre auch "tcp"
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client.crt
key /etc/openvpn/client.key
tls-auth /etc/openvpn/ta.key 1  # "0" beim VPN-Server, "1" bei VPN-Clients
keepalive 10 120
#cipher BF-CBC  (=Default; sehr schnell)
#cipher AES-128-CBC (sicherer)
#cipher AES-256-CBC (am sichersten)
comp-lzo
user openvpn
group openvpn
persist-key
persist-tun
resolv-retry infinite
status /etc/openvpn/openvpn-status.log
chroot /etc/openvpn/chroot
verb 3
ns-cert-type server    # nur ein Server-Zertifikat kann eine VPN-Verbindung zum Client aufbauen
tls-remote xyz-Server  # = Common Name des Servers bei der Server-Zertifikatsgenerierung.


Code: Init-Script
/etc/init.d/openvpn start
rc-update add openvpn default # zum Default Runlevel hinzufügen


[Bearbeiten] statische Route auf Servern "hinter" dem VPN-Gateway

Damit der Client auf einen Server hinter dem VPN-Gateway zugreifen kann (ping...), muss dort eine statische Route für den "Rückweg" der Pakete eingetragen werden. Zum Beispiel könnte man auf dem Webserver 192.168.2.11 (s. Skizze) folgende statische Route eintragen:

Datei: /etc/conf.d/local.start
route add -net 10.8.0.0 netmask 255.255.255.0 gw 192.168.2.10


[Bearbeiten] Überprüfungen

Zusätzlich zu den im Kapitel "Server" beschriebenen Überprüfungen, ist zu prüfen, ob die statischen Routen richtig gesetzt sind. Die folgende Route wird auf dem Client automatisch generiert aufgrund des Eintrags push "route 192.168.2.0 255.255.255.0" in der openvpn.conf auf dem VPN-Server.

Code: statische Route auf Client vorhanden?
ip route show # 192.168.2.0/24 via 10.8.0.5 dev tun0


Entsprechend ist zu prüfen, ob die "Rückroute" auf dem Zielserver gesetzt ist.

Code: statische Route auf HTTP-Server vorhanden?
ip route show # 10.8.0.0/24 via 192.168.2.10 dev eth0



SK, Ostfildern, den 7.7.2006

'Persönliche Werkzeuge