Openvpn
Aus Gentoo Linux Wiki
| Firewall • Dienste absichern • Verschlüsselung • alphabetischer Security Index |
[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
