=head1 Einfache VPN-Netzwerke =head1 Einführung =head2 Was ist ein "VPN-Netzwerk" VPN steht für Virtuelles Privates Netz und bezeichnet den Zusammenschluss mehrerer physikalischer Netze (oder Knoten) zu einem größeren. Die einzelnen Teile des Begriffes bedeuten: =over 4 =item Virtuell VPN-Netze sind keine physikalischen Netze, sondern existieren nur virtuell, indem sie sich bestehender Netze für den Transport bedienen. Sie vermitteln lediglich den Eindruck, in I abgeschlossenen Netz zu sein, daß wesentlich größer sein kann als ein echtes Netzwerk (z.B. können die Teilnehmer über den ganzen Erdball verstreut sein). =item Privat VPN-Netze sind abgeschlossen, d.h. sie lassen keine Kommunikation mit außerhalb des Netzes gelegenen Knoten zu. Dies schließt sowohl die Kommunikation von außen (Angreifer können keine Daten einschleusen), als auch die Kommunikation nach außen (Daten werden nicht nach außen gegeben bzw. können nicht "abgehört" werden) ein. Außerdem muss ein VPN-Netz gegen Veränderung von Daten resistent sein, d.h. es darf nicht möglich sein, Daten zu verfälschen. Dies schließt nicht notwendigerweise die Resistenz gegen Kommunikationsunterbrechung ein. Garantierte Kommunikation können natürlich auch VPN-Netzwerke nicht bieten. =item Netzwerk Unter einem Netzwerk verstehe zumindest ich einen Zusammenschluss mehrerer bis vieler Rechner. Am einfachsten kann man dies mit einem einfachen Tunnel erreichen, der zwei physikalische Netze miteinander verbindet und von einem Teilnetz in ein anderes vermittelt. (Außerdem ist der Begriff "VPN-Netzwerk" doppelt gemoppelt, aber das hat lange Tradition, siehe IFF-Format und Microsofts ungeschlagen aussagekräftige "Neue Technologie"-Technologie). =back =begin roff .bp =end =head1 VPN-Netzwerke, eine Klassifikation =head2 Tunnel vs. Netze Die einfachste Möglichkeit, ein VPN aufzubauen, ist es, einen Tunnel zwischen zwei physikalischen Netzen aufzubauen. Die beiden Teilnetze werden durch den Tunnel verbunden und bilden das VPN. Es gibt verschiedene gebräuchliche Tunnel-Typen, die man (unter anderem) durch die Protokollebene unterscheiden kann, die sie tunneln: =over 4 =item Applikationsebene, z.B. TCP Dieser Tunnel transportiert nur ein einziges Protokoll, z.B. telnet, pop3 oder X11. Dadurch werden häufig Optimierungen möglich, z.B. besonders gute Kompression oder die Weiterleitung von Authentifizierungsdaten (ssh). Außerdem sind sie meist sehr portabel und einfach zu konfigurieren. Ein Nachteil ist, das man nur ein einziges Protokoll zur Verfügung hat und für jedes weitere auch eine weitere Tunnel-Lösung benötigt. =item Protokollebene, z.B. IP Hierbei wird eine ganze Protokoll-Suite getunnelt, z.B. das Internet-Protokoll. Da die meisten Netzwerkapplikationen heute über IP miteinander kommunizieren können, deckt dies die meisten Anwendungen ab. Diese Art Tunnel benötigen etwas mehr Planung, da sich die Teilnetze nicht einfach überschneiden können und das Routing zwischen den Teilnetzen festgelegt werden muss. Grundlage für Tunnelsoftware ist das Vorhandensein eines so genannten C oder C-Netzwerkgerätes, über das sich Pakete abgreifen bzw. einspeisen lassen. =item Netzwerkebene, z.B. Ethernet Man kann noch eine Ebene tiefer ansetzen: Statt zwischen zwei physikalischen Teilnetzen lediglich zu vermitteln, kann man sie verbinden, so daß sie sich wie ein großes physikalisches Netz verhalten. Im Falle von Ethernet kann man einen Ethernet-Tunnel an beiden Endpunkten über Bridging an die physikalischen Teilnetze anschließen. Da sich das Gesamtnetzwerk fast wie ein physikalisches Netz verhält, kann man z.B. Rechner von einem Teilnetz in ein anderes verschieben ohne etwas umkonfigurieren zu müssen. Diese Tunnels sind am ineffizientesten, was den Overhead betrifft, da sie die Verwaltingsinformation mehrerer Protokollschichten übertragen müssen. Außerdem wird häufig mit I gearbeitet (z.B. um einen Rechner zu "finden"), die gerade bei größeren Netzen schnell die meist geringere Tunnelbandbreite auffressen können. =back =begin roff .bp =end =head1 TCP-Tunnel Dieser Abschnitt zeigt ein paar Beispiele für TCP-Tunnels. Sie verdienen es kaum, "VPN-Netzwerk" genannt zu werden, aber sie lösen jeweils ein Problem, und nur das zählt. =head1 SSH-Portforwarding Das SSH-Protokoll hat die r*-Protokolle und telnet im Internet fast vollständig abgelöst. Nicht nur ist es sicherer, es hat auch weitaus mehr Features als die Protokolle, die es ersetzt. Eines der Features ist Port-Forwarding, mit dem man einen bestimmten TCP-Port von lokalen Rechner zum entfernten weiterleiten kann, oder umgekehrt. =head2 Vorteile/Nachteile =over 4 =item + Fast überall installiert, I Standard schlechthin. =item + Sehr hohe Sicherheit =item + Einfache Installation und Benutzung =item - Nur TCP =back =head2 Beispiele (OpenSSH-Syntax) B<"Der POP3-Server steht in der Firma, ich will von außen Mail abholen."> Zugegebenermaßen kein Fall für ein VPN, aber mit SSH einfach zu lösen: ssh -L113:mailhost.internal:113 -N bastionhost.internet Dies erzeugt einen einfachen Tunnel vom lokalen Port 113 (pop3) zum Mailserver innerhalb des Firmennetzes. Da der Quellport (113) unter 1024 ist, kann nur Root dieses Kommando ausführen. Als User muss man einen Port über 1024 benutzen. Zur Benutzung muss man seinem Mailprogramm "lediglich" mitteilen, das der POP3-Server nun C heißt. B<"Meine neue Applikation ist fertig, jemand soll sie sich anschauen können, ohne das ich meinen Webserver ins Internet stellen muss."> Der folgende Aufruf erlaubt es einem Benutzer auf C auf meinen (hinter meinem Firewall befindlichen) Webserver zuzugreifen, indem er C auf seinem Rechner benutzt: ssh -R8000:localhost:80 -N andereruser.internet =begin roff .bp =end =head1 IP-Tunnel Ein IP-Tunnel bietet mehr Flexibilität als ein einfacher TCP-Tunnel. Und ist auch etwas komplexer beim Einrichten. Im folgenden gehe ich auf Tunnels mit SSH, ein Paket namens C und ein weiteres namens C ein, die alle einzelne Tunnels aufbauen können. =head1 PPP über SSH =head2 Vorteile/Nachteile =over 4 =item + Sehr einfach aufzusetzen =item + Die benötigten Komponenten sind einfach zu beschaffen Sowohl SSH als auch PPPD gehören zu jeder (allgemeinen) GNU/Linux-Distribution. =item + Ideal für Ad-Hoc-Tunnels z.B. für kurzzeitige Veranstaltungen, bei denen der Tunnel noch manuell überwacht werden kann. =item - Eigentlich ungeeignet für IP IP über TCP zu tunneln ist schlecht, da bei schlechter Verbindung sowohl das Tunnel-TCP als auch das getunnelte Protokoll retryen. Dadurch wird die Leitung schnell verstopft. Bei guter Verbindung gibt es aber außer einer gewissen Ineffizienz keine größeren Probleme. =item - Keine Stabilitätsrekorde Startet man C in C, per C? Was passiert bei Netzausfällen? Provider-Neueinwahl? Viele dieser Fragen lassen sich durch verbessertes Skripting (killen des C, starten per C etc.) lösen aber es wird schnell kompliziert. =item - Nur Punkt-zu-Punkt-Tunnels Bei mehr als zwei Teilnetzen braucht man schnell sehr viel Tunnels, die man nicht einfach manuell verwalten kann. =item - Total Unprofessionell "Ich habe 13 Filialen damit vernetzt" klingt nicht wirklich überzeugend... =back =head2 Beispiele Es kann so einfach sein: pppd pty 'ssh -tenone andererrechner.internet pppd nodetach noauth' \ nodetach noauth passive 10.8.0.1:10.9.0.1 Diese Zeile baut einen PPP-Tunnel mit C auf. Der lokale Rechner erhält die IP-Adresse C<10.8.0.1>, der entfernte C<10.9.0.1>. Der obige Tunnel funktioniert auf meinen Rechner wie angegeben, in der Praxis kommen manchmal noch Optionen wie C hinzu, oder der Pfad zum C muss angegeben werden. Mit ein paar weiteren Zeilen kann man zwei Teilnetze auf C verbinden: # lokal (ip kommt meistens aus dem iproute2-Paket) ip route add 10.9.0.0/16 via 10.9.0.1 ip addr add 10.9.0.1/16 dev eth0 # entfernt ip route add 10.8.0.0/16 via 10.8.0.1 ip addr add 10.8.0.1/16 dev eth0 Presto, ein VPN-Netzwerk! Nun kann man auf beiden Seiten Rechner innerhalb des C<10.8/9.x.x>-Netzes stellen (mit Default-Gateway C<10.8/9.0.1> oder statischer Route für das jeweilige andere Netz über C<10.8/9.0.1>, oder sogar I). # Proxy-Arp und IP-Forwarding einschalten, auf beiden Knoten echo 1 >/proc/sys/net/ipv4/ip_forward echo 1 >/proc/sys/net/ipv4/conf/eth0/proxy_arp =head1 VTund VTund ist eine der ältesten Lösungen und inspirierte (oder implementierte) Tunnel-Treiber für viele Betriebssysteme. =head2 Vorteile/Nachteile =over 4 =item + Vielfalt an Protokollen und Einsatzmöglichkeiten =item + Datenkompression =item - Nicht abhörsicher, nicht fälschungssicher, völlig unsicher. =item - Umständliche Konfiguration =item - Nur Punkt-zu-Punkt-Tunnels =back =head2 Beispiele dpkg -r vtund rpm -r vtund ... VTund ist ein Beispiel für Software, die man nicht benutzen sollte, da sie kryptographisch völlig unsicher ist. =head1 OpenVPN OpenVPN wäre für mich die Wahl ohne Qual, wenn es um einzelne Punkt-zu-Punkt-Tunnel geht. Es ist weit verbreitet, einfach einzurichten und solide ausgeführt. =head2 Vorteile/Nachteile =over 4 =item + Sehr hohe Sicherheit (TLS-Modus), hohe Sicherheit (shared secret) OpenVPN kann TLS (I Standard) für die Authentifizierung und die Schlüsselübergabe benutzen, d.h. Sicherheitsprüfungen und -fixes spiegeln sich automatisch bei OpenVPN wieder, während andere Software-Produkte eventuell erst getrennt gefixt werden müssen. Dadurch, daß man sehr einfach die Algorithmen wechseln kann, kann man bei neu entdeckten Schwächen bei einzelnen Algorithmen (z.B. MD5) schnell ausweichen. Das Label "hohe" Sicherheit für den shared-secret-Modus vergebe ich nur, weil die Implementation qualitativ hochwertig durchgeführt wurde. Security-Produkte, die ohne Key-Scheduling arbeiten (wie OpenVPN im shared-secret-Modus) haben fast immer auch andere Schwächen. Dies scheint bei OpenVPN nicht der Fall zu sein. =item + Hohe Portabilität OpenVPN besitzt Treiber für GNU/Linux, Solaris, OpenBSD, FreeBSD, NetBSD, Mac OS X, und Windows 2000/XP. =item + Sehr stabil OpenVPN hat mich trotz vieler widrigen Umstände (extremer Paket-Loss, häufige Wiedereinwahl, dynamische IP-Adressen, Software-Upgrades) niemals im Stich gelassen. =item + Unterstützt Bridging (Ethernet-Tunnels) =item + Einfache Konfiguration =item - Relativ hoher Paket-Overhead Durch die Verwendung von UDP (bzw. TCP, obwohl von TCP auch hier abzuraten ist) werden die Pakete relativ groß. =item - Nur Punkt-zu-Punkt-Tunnels =back =head2 Beispiele Wie man sieht, hat OpenVPN nicht sehr viele Nachteile. OpenVPN unterstützt im wesentlichen zwei Modi für die Verschlüsselung: I und I. Im ersten Modus erzeugt man einen gemeinsamem (shared) Schlüssel, den man sicher auf alle Rechner verteilen muss: openvpn --genkey --secret tunnel.key scp tunnel.key andererhost.internet: Dann muss openvpn auf beiden Seiten gestartet werden: # lokal openvpn --remote andererhost.internet --dev tun1 \ --ifconfig 10.8.0.1 10.9.0.1 --secret tunnel.key # andererhost openvpn --remote lokal.internet --dev tun1 \ --ifconfig 10.9.0.1 10.8.0.1 --secret tunnel.key Man kann, wie man sieht, also einen Tunnel aufbauen ohne ein einziges Konfigurationsfile zu schreiben. OpenVPN besitzt eine Unmenge an "fine-tuning"-Optionen, z.B. für dyndns (C<--resolv-retry>, C<--float>) und kann bei bestimmten Ereignissen auch Skripte ausführen. Der Nachteile des Shared-Secret-Modus ist, das der Schlüssel nicht gewechselt wird. Sollte der Schlüssel (das Keyfile) einmal in die Hände eines Angreifers fallen, ist sämtliche vergangene und zukünftige Kommunikation entschlüsselbar. Dieser Modus hat aber auch Vorteile: er benötigt keinerlei Handshaking, was nicht nur bedeutet, das der Tunnel sehr schnell aufgebaut werden kann, sondern auch, das man den Paketen dank fehlendem Kopf nicht ansehen kann, das es OpenVPN-Pakete sind. Für einen Mithörer sind es lediglich zufällig aussehende Daten. Sicherer wird es mit Zertifikaten: openvpn --ca ca.pem --cert cert1.pem --tls-server ... openvpn --ca ca.pem --cert cert2.pem --tls-client ... Das Erzeugen von TLS-Zertifikaten sprengt jedoch diese Präsentation. Der geneigte Leser dieses Dokumentes sei deshalb auf das OpenVPN beliegende "easy-rsa"-Paket verwiesen: C, bei Debian in C. =begin roff .bp =end =head1 Multipunkt-Netze =head1 tinc =head2 Vorteile/Nachteile =over 4 =item + Hohe Portabilität Tinc besitzt Treiber für GNU/Linux, Solaris, OpenBSD, FreeBSD, NetBSD, Mac OS X, und Windows 2000/XP. (Solaris, OpenBSD, NetBSD und Mac OS X nur IPv4). =item + Verschiedene Modi (Routing, Bridging) =item + LZO-Datenkompression =item + Hohe Sicherheit Tinc verwendet standardmäßig Public-Key-Kryptographie, vergleichbar mit OpenVPN im TLS-Modus. =item + Dynamisches Routing Tinc benötigt keinen Link von jedem Rechner zu jedem anderen, sondern kann um partielle Netzausfälle "herumrouten", indem es Pakete über andere Rechner im VPN versendet. Bei Broadcasts wird dadurch die Last auf einen einzelnen Rechner verringert. =item + Das Netzwerk kann im Betrieb vergrößert werden Ein nahezu einmaliges Feature :) =item - Relativ hoher Paket-Overhead Durch die Verwendung von UDP (bzw. TCP, obwohl von TCP auch hier abzuraten ist) werden die Pakete relativ groß. =item - Dynamisches Routing Für den Einen hilfreich, für den Anderen ein Bug: Tinc routet gerne mal Daten über den Rechner, für den volumenabhängig bezahlt werden muss. Die Stabilität des Netzes ist unter widrigen Umständen auch nicht die beste, da das Netz häufig umkonfiguriert wird und manchmal scheinbar ohne Grund die direkte (schnellste) Route vermieden wird. =item - Kritik an der Sicherheit In letzter Zeit wurde Kritik an einigen Implementationsdetails geübt, z.B. das Fehlen eines IVs. In der Praxis ist dies nicht wirklich relevant, dennoch ist die Sicherheit nicht so hoch wie OpenVPN im TLS-Modus. RFC3607 (Chinese Lottery Cryptanalysis) beschreibt jedoch die Möglichkeit, das einzelne Angreifer durchaus massiv-parallele Kryptoangriffe starten könnten, so daß man sich - echte Feinde vorausgesetzt - vorsehen sollte. Die nächste Version soll diesen Punkten Abhilfe schaffen. =item - (Relativ) umständliche Konfiguration Komplexität kommt auf den Betrachter an, da Tinc jedoch pro Rechner ein Konfigurationsfile + ein weiteres für jeden Knoten benötigt, die auch noch auf allen Rechnern leicht unterschiedlich sind. Außerdem gibt es eine gewisse Duplikation von Routing-Information. Verglichen mit vielen IPSEC-Implementation (FreeS/WAN z.B.) ist Tinc allerdings noch recht übersichtlich. Bei einfachen IP-Netzen hält sich die Konfiguration jedoch in Grenzen. =item - Benötigt TCP und UDP gleichzeitig TCP wird für die Authentifizierung und die Schlüsselübergabe benötigt, UDP für den Transport. Es gibt eine TCP-Only Option, aber die ist (da TCP) nicht zu empfehlen. In Hinsicht auf Firewall-Konfiguration kompliziert dies die Situation bisweilen. =item - Probleme in komplexen Routing-Situationen Da TCP und UDP-Sockets gleichzeitig verwendet aber nicht immer exakt synchronisiert sind (IP-Adressen beim versenden), kann es passieren, das eine Verbindung nicht zu Stande kommt. =back =head2 Beispiele B Für ein reines IP-Netzwerk benötigt man ein Hauptkonfigurationsfile (meistens C, wobei C für einen frei wählbaren Netznamen steht). Für dieses Beispiel reicht folgendes (leider eine Version für jeden Rechner): # auf rechner1 Name = rechner1 ConnectTo = rechner2 ConnectTo = rechner3 PrivateKeyFile = /etc/tinc/vpn/rsa_key.priv # auf rechner2 Name = rechner2 ConnectTo = rechner1 ConnectTo = rechner3 PrivateKeyFile = /etc/tinc/vpn/rsa_key.priv # auf rechner3 Name = rechner2 ConnectTo = rechner1 ConnectTo = rechner2 PrivateKeyFile = /etc/tinc/vpn/rsa_key.priv Um das Netzwerkinterface zu initialisieren benötigt man auf jedem Rechner noch ein C-Skript: # auf rechner1 ifconfig $INTERFACE 10.7.0.1 netmask 255.0.0.0 # Annahme: ifconfig eth0 10.7.0.1 netmask 255.255.0.0 # auf rechner2 ifconfig $INTERFACE 10.8.0.1 netmask 255.0.0.0 # Annahme: ifconfig eth0 10.8.0.1 netmask 255.255.0.0 # auf rechner3 ifconfig $INTERFACE 10.9.0.1 netmask 255.0.0.0 # Annahme: ifconfig eth0 10.9.0.1 netmask 255.255.0.0 Zusätzlich benötigt man für jeden teilnehmenden Rechner ein weiteres Konfigurationsfile namens C: # /etc/tinc/vpn/hosts/rechner1 Address = rechner1.internet Port = 2000 Subnet = 10.7.0.0/16 # /etc/tinc/vpn/hosts/rechner2 Address = rechner2.internet Port = 2000 Subnet = 10.8.0.0/16 # /etc/tinc/vpn/hosts/rechner3 Address = rechner3.internet Port = 2000 Subnet = 10.9.0.0/16 Nun muss man auf jedem Rechner das Schlüsselpaar erzeugen, in das rechnerspezifische Konfigurationsfile schreiben und auf die anderen Rechner kopieren: # auf rechner1, Vorgehensweise auf anderen Rechner ist ähnlich tincd -n vpn -K Dies erzeugt (interaktiv) die Datei C die den privaten Schlüsselteil enthält und schon an der richtigen Stelle steht. Der öffentliche Teil wird ebenfalls erzeugt und steht in C, was I die richtige Stelle ist :). Der öffentliche Schlüssel muß dann die rechnerspezifische Konfigurationsdatei angehängt werden und an die anderen Rechner verteilt werden: cat /etc/tinc/vpn/rsa_key.pub >>/etc/tinc/vpn/hosts/rechner1 scp /etc/tinc/vpn/hosts/rechner1 rechner2.internet:/etc/tinc/vpn/hosts/ scp /etc/tinc/vpn/hosts/rechner1 rechner3.internet:/etc/tinc/vpn/hosts/ # usw. für alle anderen Rechner Das ist, was ich unter "umständliche Konfiguration" verstehe. Nichtsdestotrotz ist die Konfiguration getan, man muss lediglich auf allen Rechnern C starten: tincd -n vpn Und kann sich am VPN erfreuen. Dieses VPN benutzt den C-Modus. Tinc unterstützt noch den C-Modus, bei dem kein IP-Netz sondern ein Ethernet emuliert wird. Dann kann man das Routing dem Kernel überlassen und muss die IP-(Sub-)Netze nicht in das Konfigurationsfile eintragen. =begin roff .bp =end =head1 Vpe =head2 Vorteile/Nachteile =over 4 =item + Hohe Portabilität Vpe besitzt Treiber für GNU/Linux, Solaris, OpenBSD, FreeBSD, NetBSD, Mac OS X, und Windows 2000/XP. (Solaris, OpenBSD, NetBSD und Mac OS X nur IPv4). =item + LZF-Datenkompression LZF (C) bietet ähnliche Kompressionsraten und -geschwindigkeiten wie LZO. =item + Sehr hohe Sicherheit Vpe verwendet standardmäßig Public-Key-Kryptographie. Ein besonderes Feature ist, das auch teilnehmende Rechner sich gegenseitig nicht abhören können oder (falsche) Daten einspeisen können (der Ursprung der Datenpakete kann mit Firewallregeln geprüft werden). =item + Große Auswahl an Transportprotokollen Neben dem Standardprotokoll UDP unterstützt Vpe auch einen RAWIP-Transport, ICMP-Tunneling, TCP und sogar HTTPS-Proxy-Tunnels. =item + Wählbarer Paket-Overhead Vpe-Pakete sind (bei entsprechender Konfiguration) 6 Byte kleiner als das entsprechende Ethernet-Paket. Beim RAWIP-Transport (und minimaler Länge der HMAC etc.) wird ein Tunnel-Paket gegenüber dem transportierten IP-Paket nur um 28 Byte größer. =item + Router/Routerloser Modus Designiert man einen (oder mehrere) Rechner als Router, so können diese als Protokollumsetzer dienen und zwischen anderen Knoten vermitteln. So können z.B. zwei Rechner hinter einem NAT eine UDP-Verbindung herstellen. =item + Einfache Konfiguration möglich. Komplexe ebenfalls. Es gibt nur ein Konfigurationsfile (und ein C-Skript zur Initialisierung des Interfaces), das auf allen Rechnern identisch sein kann, plus die Public-Key-Schlüssel der teilnehmenden Rechner. Wenn man ein komplexes Netz aufbaut (viele unterschiedliche Protokolle, Dynip-Rechner, "Einwahl" per HTTPS-Proxy), so wird die Konfiguration auch komplex - aber möglich. =item - Kein echtes Bridging Vpe emuliert zwar ein virtuelles Ethernet, die MAC-Adressen sind aber nicht frei wählbar. Das liegt daran, das Vpe anhand der MAC-Adressen routet. Das hat den Vorteil, das Routing-Information nur dem Kernel mitgeteilt werden muss (und beliebige Protokolle geroutet werden können). Aber auch den Nachteil, das keine Ethernet-Pakete direkt gebridged werden können. =item - Implementiert in C++ Nicht per se ein Nachteil, aber C++ ist weniger verbreitet als C. Zudem wurde Vpe bisher nur mit G++ 2.95 und 3.x getestet. =item - Interface-Konfiguration wird dem Benutzer überlassen Vpe emuliert lediglich ein Ethernet - die Konfiguration der Netzwerkinterfaces bleibt einem Skript überlassen. Dies schließt das (stark betriebssystemabhäbgige) Setzen der MAC-Adresse sowie eventuell notwendige ARP-Einträge mit ein. Dies erlaubt zwar volle Kontrolle über das Netz (ob man z.B. ARP benutzt oder nicht), kann aber bei komplexen Netzen auch umständlich sein. =item - Keine Verteilung von Broadcasts Durch die Abschottung der Rechner voneinander muss ein Knoten den Broadcast selbst an alle anderen Knoten verteilen. =item - Kein dynamisches Routing Eine Design-Entscheidung bei Vpe ist es, das alle Routing-Entscheidungen statisch getroffen werden, d.h. aus dem Konfigurationsfile (bzw. der Gesamtheit dieser) wird eine statische Entscheidung über Protokoll und Port getroffen. Ist dieser Weg nicht möglich, kommt keine Verbindung zustande. Dies verhindert zwar, das (wie bei Tinc) Routen zustande kommen, die man nicht vorhersehen kann, verringert aber die Ausfallsicherheit. =back =head2 Beispiele C Dazu benötigt man zwei Dateien, zuerst einmal die Konfigurationsdatei C: mtu = 1492 # Der dial-up-rechner benutzt tdsl mit MTU 1492 node = rechner1 address = rechner1.internet node = rechner2 node = rechner3 address = rechner3.internet C und C haben (hier) eine feste Adresse, C ist ein Dialup-Rechner. Die zweite Datei ist ein Skript (C), das die Netzwerkinterfaces einrichtet (es muss ausführbar sein!): #!/bin/sh ip link set $IFNAME address $MAC mtu $MTU up ifconfig $IFNAME 10.$NODEID.0.1/8 # Annahme: ifconfig eth0 10.$NODEID.0.1/16 Hier habe ich etwas getrickst: Vpe setzt eine Menge Environment-Variablen, eine davon, C<$NODEID>, ist eine numerische ID des aktuellen Rechners, die von der Reihenfolge im Konfigurationsfile bestimmt wird: C erhält die ID 1 und die IP# C<10.1.0.1>, C die ID 2 und die IP# <10.2.0.1> etc. Jetzt müssen die RSA-Schlüssel erzeugt werden: vpectrl -g Das erzeugt für jeden Knoten eine Datei C mit dem öffentlichen und eine Datei C. Nun können die beiden Konfigurationsdateien C und C, sowie die öffentlichen Schlüssel in C auf alle Knoten verteilt werden: scp -pr /etc/vpe/{vped.conf,if-up,pubkey} rechner2.internet:/etc/vpe/. scp -pr /etc/vpe/{vped.conf,if-up,pubkey} rechner3.internet:/etc/vpe/. Vpe erwartet (per Default) I (nicht I!) privaten Schlüssel in der Datei C. Der Grund ist, das die privaten Schlüssel den einzelnen Rechner abhörsicher machen. Ist das egal (wenn man allen beteiligten Rechnern vertraut), kann man das Verzeichnis auch direkt kopieren und im Konfigurationsfile C angeben. Wir wollen aber ein neurotisch-paranoides sicheres Netzwerk, und verteilen die Schlüssel einzeln von C auf die anderen: cd /etc/vpe cp hostkeys/rechner1 hostkey scp hostkeys/rechner2 rechner2.internet:/etc/vpe/hostkey scp hostkeys/rechner3 rechner3.internet:/etc/vpe/hostkey Nun ist es geschafft und man kann C starten: vped -l info rechner1 C benötigt den Knotennamen als einziges Argument um den aktuellen Rechner zu identifizieren. Das C<-l info> setzt den Logging-Level auf C, bei dem Vpe Verbindungsaufbauten mitprotokolliert. C geht in den Hintergrund und hält automatisch die Verbindungen aufrecht. Der Dial-Up-Rechner im Beispiel sollte bei IP-Adressänderungen ein C-Signal an den C schicken, sonst können andere Rechner ihn nicht erreichen. Eine andere Möglichkeit (die ich gerne praktiziere) um VPN (und andere) Dämonen automatisch zu starten ist, sie in die C einzutragen: t1:2345:respawn:/opt/vpe/sbin/vped -D -L mobil >/dev/null 2>&1 Der Schalter C<-D> sorgt dafür, das der C nicht in den Hintergrund geht. C selbst sorgt dafür, das C immer läuft, es sei denn, er startet zu schnell neu (bei Konfigurationsfehlern z.B.). Dann legt C ihn für eine Weile auf Eis. B Als zweites Beispiel möchte ich ein Subset meines Produktionsnetzwerkes vorstellen. Es enthält einige Router (stellvertretend benutze ich hier den Rechner C), einige Dial-Up-Rechner (C) und mein Notebook (C), mit dem ich auf Reisen bin. Außerdem wird der RAWIP-Transport benutzt (mit IPSEC-Protokollnummer, da dies häufig freigeschaltet ist): # vped.conf: mtu = 1492 # the mtu (minimum mtu of attached host) keepalive = 300 ifname = vpn0 # the tunnel interface name to use compress = yes connect = ondemand # connect to this host always/never or ondemand loglevel = notice udp-port = 407 tcp-port = 443 # https ip-proto = 50 # ipsec-esp enable-rawip = yes # RAWIP ist default für die Rechner node = router address = 130.4.88.20 router-priority = 10 enable-tcp = yes # also talks https node = dialup node = mobil Das C-Skript ist etwas komplexer (der Distribution liegt ein Beispiel-C-Skript bei, das ARP-loses IP-Routing implementiert und nebenher auch gleich C-Firewallregeln erzeugt): #!/bin/sh ip link set $IFNAME address $MAC mtu $MTU up [ $NODENAME = router ] && ip addr add 10.0.0.5 dev $IFNAME [ $NODENAME = dialup ] && ip addr add 10.9.0.31 dev $IFNAME [ $NODENAME = mobil ] && ip addr add 10.0.0.20 dev $IFNAME ip route add 10.0.0.0/8 dev $IFNAME # Festes verdrahten der Gateway-MAC-Adressen verhindert ARPs ip neighbour add 10.0.0.5 lladdr fe:fd:80:00:00:01 nud permanent dev $IFNAME ip neighbour add 10.9.0.20 lladdr fe:fd:80:00:00:02 nud permanent dev $IFNAME ip neighbour add 10.0.0.20 lladdr fe:fd:80:00:00:03 nud permanent dev $IFNAME # Routen eintragen [ $NODENAME != router ] && ip route add 10.0.0.0/28 via 10.0.0.5 dev $IFNAME [ $NODENAME != dialup ] && ip route add 10.9.0.0/16 via 10.9.0.31 dev $IFNAME Sieht kompliziert aus, verhindert aber ARP-Requests (Die gebroadcasted werden müssen und dabei Verbindungen zu allen anderen Rechner aufbauen müssen). C benutzt übrigens manchmal (Reisen! Veranstaltungen mit Netzzugang nur über Proxy etc!) leichte Veränderungen an der Konfigurationsdatei: node = mobil http-proxy-host = webproxy.domain http-proxy-port = 3128 # http-proxy-auth = user:password enable-tcp = yes enable-udp = no enable-rawip = no C benutzt dann TCP-über-HTTP-Proxy, was (fast) überall funktioniert. Wenn C den Rechner C erreichen will, fragt er bei C nach und bekommt mitgeteilt, das C kein gemeinsames Protokoll spricht. C versucht dann, über den C mit C zu kommunizieren (was auch klappt).