OpenVPN - mit sicheren Kommunikationswegen einen sicheren Zugang ins heimische Netzwerk herstellen
Datenschutz zum ersten (gegen Ausspähen), Schutz der eigenen Daten zum zweiten (gegen Manipulation), sichere Kommunikationswege zum dritten (gegen Abhören)... das ist hier in diesem Artikel mein Thema.
Inhaltsübersicht über die Kapitel dieses Artikels:
> Überblick - Was ist alles zur Einrichtung von OpenVPN notwendig ?
> Deb-Package für OpenVPN erstellen und installieren
> Ein paar Basics zu Protokollen, Verschlüsselung und Perfect Forward Secrecy
> Erstellen der Konfigurationsdateien, Keyfiles, Zertifikate und Service-Units
> Certificate Revocation List (CRL)
|
Kontinuierlich dem schon in meinen anderen Artikeln vorhandenen Security-Leitfaden folgend, befasst sich auch dieser Artikel wieder mit dem Thema Sicherheit, hier mit den beiden Aspekten Datenschutz und Schutz meiner Daten. Das sind tatsächlich zwei unterschiedliche Aspekte, der Datenschutz richtet sich gegen den unbemerkten, heimlichen und missbräuchlichen Zugriff durch Fremde, der Schutz meiner Daten richtet sich gegen unerlaubte Manipulation, Verlust oder Zerstörung. In diesem Artikel geht es um sichere Kommunikationswege. Im weiteren Sinne ist damit also ein Schutz gegen Zugriff auf meine Daten durch Fremde von außerhalb gemeint. Das betrifft sowohl meine Daten im heimischen LAN als auch die Daten meiner mobilen Aktivitäten, wenn ich auf Reisen Account- oder Zugangsdaten auf einer Web-Site eingeben soll/muss/will, um zum Beispiel unterwegs mal schnell einen Blick in mein Online-Postfach zu werfen. Speziell beim Letzteren geht es darum, das mögliche Belauschen der Verbindung und der Datenübertragungen durch Fremde vollständig zu unterbinden, wenn ich mich mit meinem Laptop an offenen WLAN-AccessPoints verbunden habe. Wir haben es hier also mit zwei unterschiedlichen Aspekten zu tun, die allerdings beide mit dem gleichen Werkzeug verfolgt und gelöst werden.... und zwar mit OpenVPN. In diesem Artikel befasse ich mich also mit OpenVPN und versuche Antworten auf die folgenden Fragen zu finden. Was ist OpenVPN? Was kann es für mich tun? Wann kann ich es nutzen? Wie richte ich es ein? Fangen wir mit der ersten Frage an.
Den Wortanteil "Open" im Namen des Paketes muss man wohl nicht erläutern... es ist halt ein Programm aus einer Open-Source-Community. Der Wort-Anteil "VPN" steht für "Virtual Private Network". OpenVPN ist also eine Netzwerk-Software, die zwischen zwei weit entfernt voneinander betriebenen Endgeräten (Computern) über das Internet eine Netzwerkverbindung als in sich geschlossene private End-to-End-Verbindung herstellen kann. Es handelt sich hierbei jedoch nicht um ein neues physikalisches Netzwerk, basierend auf Hardware und Kabeln, sondern um ein logisches, rein virtuelles Netzwerk. Allerdings bildet die vorhandene physische Infrastruktur wie z.B. PCs mit Netzwerk-Interface, Patchkabel und DSL-Router oder Mobilgeräte mit WLAN-Karten und natürlich auch das Internet die physische Grundlage, in der das virtuelle VPN eingebettet ist.
"In sich geschlossen" bedeutet, dass diese Datenverbindung aufgrund der in der Verbindung angewendeten Verschlüsselung von allem anderen im Internet vorhandenen Traffic unlesbar isoliert oder gekapselt ist. Umgangssprachlich wird hierbei von den Insidern oft von einem Tunnel gesprochen, mit dem i.ü.S. ein blickdichter Tunnel gemeint ist, der von dem einem Endgerät durchs gesamte weltweite Internet bis zum anderen Endgerät reicht. Blickdicht (ein vergleichender Begriff von mir) bedeutet, das alle Datenpakete, die durch diesen Tunnel transportiert werden, von niemand anderen abhörbar oder lesbar sind. Nach meiner Kenntnis sind entsprechend dem heutigen technischen Stand solcherart durch ein VPN geleitete Datenpakete nicht hackbar, die Verschlüsselung solcher auf dem Transportweg befindlicher Daten-Pakete ist auf absehbare Zeit nicht zu knacken. Das mag dann auch wohl der Grund dafür gewesen sein, dass Apple vom chinesischen Regime im Zeitraum Juli-August 2017 gezwungen wurde, weit über 600 VPN-Apps aus dem App-Store zu entfernen... ein tatsächlicher Sachverhalt, den man mit den entsprechenden Stichworten einfach im Web selber recherchieren und nachlesen kann. Dabei ist OpenVPN gar nichts subversives, es ist nichts aufrührerisches, nichts gefährliches.... es verhindert lediglich, dass meine Daten-Privatsphäre von mir fremden Menschen verletzt wird... es schützt meine digitale Privatsphäre, es schützt mein Recht auf die vollständige Verfügungshoheit meiner persönlichen Daten beim Transport durch das Internet.
Diese und die nächste Frage sind etwas komplizierter zu beantworten. Um die Sinnhaftigkeit und sogar Notwendigkeit von VPN-Software zu verstehen, muss man sich zuerst der real vorhandenen Gefahren bewusst sein, denen unsere privaten Daten permanent ausgesetzt sind. Und erst daraus resultiert die Erkenntnis, wie wertvoll OpenVPN für uns sein kann und bei welchen Gegebenheiten wir es verwenden sollten.
Um die Situation insgesamt etwas besser einschätzen zu können und um unsere Ausgangslage und die Rahmenbedingungen auch wirklich zu verstehen, schauen wir uns kurz das nebenstehende Bild an... ...und wir erkennen darin eine eigentlich völlig normale Situation... wir sitzen irgendwo auf der Welt in einem Café, in einer Strandbar, in einer Pension oder einem Hotel, oder sind irgendwo in einer City, oder in einem Park und freuen uns über das offene kostenlose WLAN. Unser Laptop ist also gerade mit irgendeinem 'freundlichen' AccessPoint via WLAN verbunden und wir können komfortabel unser Mailpostfach öffnen und auf neue Emails prüfen, oder unser Facebook-Konto auf neue Nachrichten prüfen, oder einfach nur frei Surfen im Web und vielleicht auch Postings in unseren abonnierten Online-Foren beantworten. |
Nun überlegen wir kurz, was uns zu solchen Situationen einfällt bzw. was wir dazu wissen ... und anschließend natürlich auch, was wir nicht wissen. Das, was wir wissen, ist einfach. Mir fallen dazu -wenn ich an mich und meinen Laptop denke- wirklich nur zwei Punkte ein:
Ich weiß, dass
1. mein Laptop 'sauber' ist und das ich keine bösen Absichten in diesem Gastnetz habe. Ich möchte das Gäste-WLAN einfach nur kurz für meine persönlichen Belange ins Internet nutzen.
2. mein Laptop nach der Anmeldung in ein fremdes Netzwerk integriert ist, was aus technischer Sicht faktisch gleich einzuschätzen ist, als wenn ich zuhause im LAN angeschlossen bin. Das ist insofern erwähnenswert, weil das Betriebssystem selber der Bewertung, ob das fremde Netzwerk ein freundliches Netz ist oder nicht, eher keine Bedeutung beimisst. Rein technisch betrachtet verbindet es sich mit einem "feindlich" gesinnten Netzwerk genauso schnell, wie zuhause im heimischen Netzwerk und es behandelt andere Clients in beiden Netzen gleich. Wenn mein Laptop zuhause einen SSH-Zugang oder einen Samba-Share anbietet, woher soll er wissen, dass er das in diesem fremden Netz nicht soll oder darf? Tja, er weiß es nicht.
Dem entgegen ist die Liste dessen, was ich nicht weiß, was aber trotzdem für mich von Bedeutung ist, etwas länger. Und wer jetzt denkt "was ich nicht weiß, macht mich nicht heiß" ... tja, der braucht hier auch nicht mehr weiterlesen.
Ich weiß nicht,
1. ob der Betreiber des Lokals (oder was auch immer diese Örtlichkeit darstellt) tatsächlich auch der Betreiber des WLAN-Access-Point ist
2. wer die Verantwortung für die Wartung und Pflege der WLAN- bzw. Netzwerk-Infrastruktur innehat
3. wer neben dem Betreiber außerdem auch (kontrolliert oder offen und unkontrolliert) Zugang zu dieser exponierten IT-Hardware hat
4. ob dieser AP von einem sachkundigen Administrator eingerichtet wurde oder ob der Koch nur einfach WLAN an seinem Router freigegeben hat
5. ob dieser AP resp. dessen Hardware durch fahrlässigen früheren Umgang nicht vielleicht schon kompromittiert ist
6. ob dieser AP über eine Firewall verfügt oder eingerichtet hat, die gegen das Internet wirkt
7. welche Absichten der Betreiber dieses AP überhaupt verfolgt, ob er integer sind oder eher als dubios einzuschätzen ist. Vielleicht geht's ihm ja auch nur darum, bei dem vielleicht hohen Durchsatz an Reisenden und Tourismus-Gästen gewisse Account-Daten abzugreifen um damit nebenher Geld zu verdienen
8. welchen lokalen staatlichen Bestimmungen ein WLAN-Betreiber vielleicht zwangsweise folgen muss, z.B. durch Anti-Terror-Gesetze, Gesetze zur Telekommunikationsüberwachung, etc.
9. welchen "Charakter" der AP überhaupt hat und ob er wirklich der ist, der er zu sein vorgibt (Stichwort Evil Twin)... ein Umstand, der für uns überhaupt nicht zu erkennen ist. Wenn ein Strandcafé beispielsweise das WLAN mit der SSID beach_cafe_mary anbietet, so ist es für uns unmöglich zu erkennen, dass die SSID beach_cafe_mary2 mit vielleicht besserer Leistung gar nicht zu diesem Café gehört, sondern ein Evil Twin ist. Dem Chef des Cafés wird das gar nicht auffallen, weil der bei der Bewirtung seiner Gäste wichtigeres zu tun hat, als ständig sein WLAN zu beobachten. Mit der SSID beach_cafe_mary2 melden wir uns aber in ein Netzwerk an, was uns gegenüber unzweifelhaft feindselig eingestellt ist ... eben weil es nicht von diesem Café betrieben wird und weil es keine andere Rechtfertigung dafür gibt, sich als jemand anderes auszugeben. Vielleicht hat das keine Konsequenzen für uns, aber dann nur deshalb nicht, weil wir als unbescholtene Urlauber einfach zu unwichtig sind. Aber vielleicht hat sich auch jetzt jemand Zugang zu unserem Laptop verschafft oder einfach nur unsere Anmeldedaten abgehört.
Es gibt also wirklich gute Gründe, sich vor der Anmeldung an fremden WLAN-Access-Points ein paar Gedanken über die Sicherheit seines Laptops zu machen. An dieser Stelle verweise ich deshalb natürlich auch noch mal auf meinen Artikel zu Sicherheit durch Firewall, in dem ich einen Paketfilter für solche Situationen beschrieben habe ... nun ja, das nur mal am Rande, denn hier soll es ja primär um OpenVPN gehen.
Die oben beschriebene Situation mit der WLAN-Verbindung an einem offenen/freien AccessPoint ist also offensichtlich etwas ganz normales, was völlig alltägliches ... nur leider eben durchaus auch mit ein paar Risiken behaftet. Das ganze erhält aber noch eine zusätzliche Dimension an Risiken, wenn ein Anwender darüber hinausgehend auch noch vorhat, sich von unterwegs mit seinem heimischen Netzwerk zu verbinden, um damit von jedem Ort auf der Welt einen Zugriff auf die Daten seines Servers zuhause zu bekommen. Das ist beispielsweise eine immer häufiger auftretende Frage in "meinen" Onlineforen, wenn Linux-Beginner nach Möglichkeiten fragen, um von außerhalb einen Zugriff auf die Hausautomatisierung zu bekommen, auf Überwachungskameras, auf die vom Server vorgehaltenen Daten.
Technisch ist das wirklich kein großes Problem. Das ist alles ganz fix gemacht. Wir öffnen einfach die benötigten Türen in der Firewall unseres DSL-Routers und schon steht uns von überall auf der Welt das ganze private Netzwerk zur Verfügung.
Ein SSH-Zugang mit leicht zu merkendem Password, ein Web-Server, der sich sofort mit "Hallo, hereinspaziert" meldet, ein lokaler Mailserver, mit dem man sich auf Reisen problemlos mit Thunderbird oder einem Smartphone-Client verbinden kann, die Home-Automatisierung, bei der man sich mit "1234" als Password authentifiziert ... alles kein Problem.... das geht alles ganz fix einzurichten. Man installiert die entsprechenden Dienste auf dem Server, passt die Einstellungen an, öffnet zudem die Ports im DSL-Router mit passender Weiterleitung und schon läuft alles wunderbar.
Wäre das nicht schön, wenn's dabei bleiben würde? Aber leider befindet sich genau hier das Problem... denn es bleibt nämlich nicht allein dabei. Die Wirklichkeit sieht leider ein wenig anders aus. |
Sobald wir einzelne Türen in unser Netzwerk herein öffnen, besteht ab diesem Moment ununterbrochen die äußerst signifikante Gefahr, dass sich durch diese Tür auch Fremde einschleichen wollen, und das heimlich einbrechend, unberechtigt, mit unbekannten Absichten. Und genau darin besteht meine größte Herausforderung: wie schaffe ich es, dass die von mir geöffneten Türen nicht unberechtigt auch von Fremden durchschritten werden? Wie verhinderte ich effektiv, dass Fremde sich illegalen Zugriff auf mein Heimnetzwerk verschaffen und mich belauschen, oder meine Daten stehlen, oder schlimmstenfalls sogar alle meine Daten zerstören? Tja... ich habe für unser Netzwerk meine Antwort auf diese Frage gefunden... die auch relativ einfach ist, aber auch radikal und endgültig. Ich vermeide heute einfach konsequent Türen zu öffnen, deren Sicherheit ich nicht selber absolut unzweifelhaft in der Hand habe. Und ich vermeide verschiedene Türen (also mehr als nur eine) für verschiedene Dienste öffnen zu müssen.
Genau für diese Zielsetzung eines wirklich kontrollierten Zugangs in mein Heimnetzwerk ist OpenVPN ein perfekte Lösung, weil ich für OpenVPN erfreulicherweise nur eine einzige Tür öffnen muss, die mir aber trotzdem den vollständigen Zugang auf alle Ressourcen ermöglicht und deren Passage nur mit Vorlage "meines Personalausweises" erlaubt ist ... man verzeihe mir den Vergleich mit dem Personalausweis, aber das ist eben für uns Laien die beste sinngemäße Übertragung für das Zertifikat zur Authentifizierung und dem Keyfile für die Ver-/Entschlüsselung ... mir fiel wirklich nichts besseres ein. Unbestritten ist, ohne diesen "Ausweis" (das Zertifikat) wird der Zugang ins Netzwerk verwehrt. Das bedeutet allerdings auch, dieses Zertifikat und das Keyfile sind als zwei äußerst sensible Dateien zu behandeln, die man wirklich zuverlässig geschützt vor unberechtigtem Zugriff aufbewahren muss. Die notwendige sichere Aufbewahrung habe ich auf meinen Laptop durch einem grundsätzlich unzugänglichen LUKS-Container realisiert, in dem die beiden Files gespeichert sind. Der Container wird on-the-fly erst dann geöffnet, wenn ich einen bestimmten USB-Stick ins Gerät einstecke. Sobald ich den Stick wieder abziehe, ist der Container wieder gesichert und kann nicht mehr eingesehen werden.
Die Vorgehensweise bis zur sicheren Verbindung ist also eigentlich ganz einfach:
1. Ein restriktiver Paketfilter ist aktiv
2. Netzwerk-Verbindung zum AccessPoint wird hergestellt
3. Bevor eine Anwendung gestartet wird, die das Netzwerk nutzt, wird der OpenVPN-Client gestartet
4. Nach erfolgreicher VPN-Verbindung starte ich auf dem Laptop die jetzt von mir gewünschten Programme oder Dienste
Mit OpenVPN habe ich also eine Möglichkeit gefunden, trotz aller vorhandenen Gefahren auf absolut sichere Weise sämtliche in meinem heimischen LAN verfügbaren Ressourcen auch von außerhalb erreichen und nutzen zu können, wie den Samba-Server, oder den Mailserver. Ich kann meine auf dem Server gespeicherten Kontakte mit dem Smartphone synchronisieren, meine Web-Cams öffnen und Haus und Hof kontrollieren, oder einfach auf abhörsichere Art und Weise über meinen Router zuhause im Internet surfen.... und das alles ganz (un)bequem auf dem oben gezeichneten Stuhl im Café sitzend, mit meinem Laptop auf dem Tisch, verbunden mit einem potentiell unsicheren fremden und unbekannten Netzwerk. OpenVPN kann damit vielleicht sogar die Installation eines eigenen Web-Servers und installierter Cloud-Software unnötig machen ... eine Idee, auf die man möglicherweise kommt, weil man drüber gelesen hat und weil man glaubt, nur damit können die Kontakte und Termine vom Handy mit dem Server synchronisiert werden. Dabei geht das auch wirklich prima ohne solch schweren Geschütze, deren Sicherheit ich aufgrund der wirklich hohen technischen Anforderungen als Laie vielleicht kaum gewährleisten kann. Dieses Problem löst radicale perfekt, welches genau für den Zweck der Synchronisation mehrerer Smartphones mit mehreren Adressbüchern und Kalendern ein tolles Werkzeug ist.
Der wirklich augenfällige Vorteil von OpenVPN ist, ich muss gar nicht eine für jeden Service meines LAN-Servers passende Tür öffnen, um über das Internet Zugang zu diesen Service zu bekommen, ich integriere mich mit OpenVPN einfach in das heimische Netzwerk und kann dann alle Dienste so nutzen, so als wäre ich mit meinem Laptop zuhause im Netz angemeldet. Schauen wir auf das nebenstehende Bild, um noch besser die Funktionsweise von OpenVPN zu verstehen. Ich melde meinen Laptop zunächst mal ganz normal bei diesem AccessPoint über einen Netzwerkmanager an. Bis zu diesem Moment sind noch keinerlei private Daten geflossen... es wird nur rein technisch eine Funkverbindung zwischen zwei Geräten hergestellt und ein Netzwerk etabliert. Das bedeutet, der Laptop bekommt eine IP-Adresse vom Router des APs aus dessen Netz zugewiesen. Ab diesem Moment ist mein Laptop aber auch in diesem Netzwerk resp. für den Admin dieses Netzes sichtbar, genau so wie ich meinen Laptop oder die anderen Geräte zuhause im Netz sehe, wenn ich das mit meinem PC kontrolliere oder überwache. Ich wiederhole das noch mal kurz... an diesem Punkt ist eine restriktiver Paketfilter eine wichtige Empfehlung.
|
Und nun starte ich auf dem Laptop den VPN-Client, der dann automatisch eine Verbindung zu meinem VPN-Server zuhause aufbaut und damit den schon erwähnten sicheren Tunnel zwischen diesen beiden Geräten etabliert. Nach erfolgreicher Verbindung bin ich ab jetzt nicht nur ein Mitglied meines Netzwerkes zuhause und alle dessen Ressourcen stehen mir zur Verfügung, es ist auch noch der direkte Zugang vom Laptop über den AccessPoint zum normalen Internet blockiert. Das bedeutet, wenn ich jetzt mit dem Browser im Internet surfe, geht der vollständige Traffic nicht mehr über den AccessPoint ins Internet, sondern erst durch den Tunnel in mein Netzwerk zuhause und dann über den heimischen Router wieder ins Internet. Keine einzige mit meinem Browser geöffnete Web-Seite ist vom AccessPoint sichtbar, es können keine Daten (Anmeldename, PWD) abgegriffen werden, die ich auf irgendeiner Web-Seite eingebe, der gesamte Datenverkehr findet hochsicher verschlüsselt durch den Tunnel über meinen Router zuhause statt. Ich kontrolliere das immer zuerst, in dem ich mir kurz auf einer Online-Website meine jetzt aktuellen öffentlichen IP-Adressen anzeigen lasse.... und mit erfolgreich gestarteten OpenVPN ist das nie die temporäre Adresse des AccessPoints, sondern immer die IP meines Routers zuhause oder eine IPv6-Adresse gebildet aus meinem heimischen ISP-Prefix.
Ist das VPN meiner FRITZ!Box nicht das gleiche, wie OpenVPN? Im DSL-Router ist VPN ja schon als Grundfunktion vorhanden und man kann es ohne viel Arbeitsaufwand nutzen. Ja, stimmt, vermutlich ist VPN über die Fritzbox um einiges leichter in Betrieb zu nehmen. Aber leider gibt es auch einige gravierende sicherheitsrelevante Unterschiede im Vergleich zu OpenVPN, wegen derer ich schließlich zu dem Fazit gekommen bin, das AVM-VPN nicht zu verwenden.
Ein OpenVPN-Tunnel ist immer eine end2end-Verbindung zwischen zwei vertrauenswürdigen Geräten, die von mir selber eindeutig als vertrauenswürdiger Erster und Letzter Punkt auf dieser Kommunikationsstrecke identifiziert sind. Alles was zwischen diesen beiden Endpunkten liegt, also auf dem ganzen Weg des Tunnels, kann man eigentlich durchweg als potentiell unsicher einstufen. Das betrifft natürlich zuallererst den offenen Start-AccessPoint mit dem wir verbunden sind, dann den Transport durchs Internet und letztlich auch die Fritzbox als End-AccessPoint. Der Vorteil des OpenVPN-Tunnels ist, dass die übertragenen Daten-Pakete diese "drei unvermeidbaren Teilnehmer" nicht entschlüsselbar und somit völlig unlesbar passieren, einschließlich der vielleicht auch übertragenen Passworte oder Zugangsdaten zu Geräten der Home-Automation.
Und warum ist das Fritzbox-eigene VPN als unsicher einzustufen? Zum einen, weil die Paketverschlüsselung an einem Punkt aufhört, der auf proprietärer Software basiert und zum anderen wegen der Tatsache, dass die Fritzbox bekanntermaßen eine Backdoor implementiert hat. Also braucht man eine Antwort auf die Frage, ob man einer fremden Hardware mit quasi unkontrollierbarer Software als Endpunkt einer Verschlüsselung wirklich vertrauliche Daten anvertrauen will? Wenn es dabei auch noch um Home-Automation und Zugangsdaten dazu geht, halte ich das für einigermaßen fahrlässig.
Was bedeutet Backdoor...?... das klingt ja irgendwie beunruhigend. Viele moderne DSL-Router -wie eben auch die FRITZ!Box von AVM- haben die TR-069-Schnittstelle implementiert. Über diese Schnittstelle werden primär Updates installiert, oder neue Programme, aber auch Sicherheitspatches. Und bei manchmal auftretenden heimischen Problemen, mit denen unkundige normale Home-User oft überfordert sind, können Support-Mitarbeiter des DSL-Anbieters über diese Schnittstelle auch Wartungsarbeiten am Router durchführen, bis hin sogar zu veränderten Einstellungen. Aber genau deswegen ist es funktional wie ein SSH-Zugang für Fremde in unser Netzwerk zu sehen, ohne faktisch selber ein SSH-Server zu sein. Also ist das alles nur scheinbar vorteilhaft für uns, es wird uns nämlich gar nicht offen mitgeteilt, welche Nachteile das zeitgleich für uns beinhaltet und wir werden nicht gefragt, ob wir dem überhaupt zustimmen. Denn wer diese Schnittstelle bedienen darf, kann alles installieren und im Router alles veranlassen. Ein Wikipedia-Artikel beschreibt die TR-069-Schnittstelle deshalb auch als Beschneidung der Privatsphäre und des Datenschutzes für den Endanwender. Dem DSL-Anbieter wird damit ermöglicht, Änderungen am DSL-Router durchzuführen, die der Benutzer weder kennt noch erlaubt hat. Über diese Schnittstelle sind sogar nicht nur Änderungen im Roll-Out-Mode für alle im Land betriebenen DSL-Router möglich, sondern auch explizit für einen einzeln Router, was insbesondere für uns eine große Bedeutung bei Online-Durchsuchungen, digitaler Schleierfahndung oder Abhörbefugnissen haben kann. TR-069 sieht sogar die Möglichkeit vor, Geräte hinter der Router-Firewall, also unsere Geräte im Netz zu sehen und ggf. dort Daten zu verändern. Damit stellt TR-069 durch sein Funktionsprinzip ohne jeden Zweifel eine Backdoor da. Einige DSL-Anbieter erlauben es, diese Schnittstelle im Router zu deaktivieren, einige DSL-Anbieter räumen einem dieses Recht nicht ein. In einem solchen Fall würde ich diese Fritzbox nicht verwenden bzw. eine eigene Router-Firewall zwischen DSL-Router und lokales Netzwerk positionieren.
Der Zusammenhang zum VPN ist also ganz einfach. TR-069 ist eine Schnittstelle, mit der natürlich folgerichtig auch direkt und unautorisiert auf die im DSL-Router hinterlegten Zertifikate und Kryptografie-Schlüssel zugegriffen werden könnte. Und wenn man die hat, braucht man die Schnittstelle gar nicht mehr, um Zugang zu Deinem Netzwerk zu bekommen, damit ist man einfach auf geraden Weg direkt drin. Wegen der Schnittstelle TR-069 hast Du tatsächlich also keine Kontrolle mehr darüber, wer vielleicht auf diese Daten zugreift und wie er das verwendet. Wie willst Du außerdem gewährleisten oder verhindern, dass bei einer Fritzbox nicht sogar beabsichtigt ist, die Keys auszulesen und anders als Du erlaubst zu verwenden? Wie willst Du gewährleisten, dass eine Behörde nicht so was wie einen 'Generalschlüssel' für diese Keyfiles hat oder von AVM oder dem DSL-Anbieter die Herausgabe als Polizeimaßnahme erzwingen kann?
Und genau hier besteht der wirklich beunruhigende Unterschied zu OpenVPN, denn wer Zertifikat und Kryptografie-Schlüssel aus der Fritzbox 'entwendet' hat, hat ungehinderten Zugang zu Deinem Netzwerk. Dabei ist es völlig egal, ob die Keys legal ausgelesen wurden, oder illegal, oder gehackt, oder über eine Sicherheitslücke. Deshalb machst Du die Sicherheit Deines privaten Netzwerkes auch von dem Zufall abhängig, wie "sorgfältig" und "gewissenhaft verschwiegen" irgendein beliebiger Support-Mitarbeiter Deines DSL-Anbieters mit den Zugangsdaten zu Deinem Router umgeht, ohne das Du selber den geringsten Einfluss darauf hast. Genauso wenig hast Du Einfluss darauf, wer beim DSL-Anbieter überhaupt wie autorisiert und wie kontrolliert und von welchen Compliance-Regeln geleitet Zugang zu deren Systemen hat, um darüber vielleicht die Zugangsdaten für Deinen Router auszulesen. Und vergiss nicht, dass im First-Level-Support manchmal auch nur 400€-Teilzeit-Kräfte für eine Erst-Hilfe sitzen, oder es handelt sich gar nur um ein mit dem Auftrag "Kunden-Erst-Kontakt" beauftragtes Call-Center.
Bei meiner FRITZ!Box konnte ich den Port jedenfalls nachweislich (mithilfe eines Port-Scanners) schließen. Wenn sich diese Situation jemals ändern sollte, schalte ich sofort eine eigene Router-Firewall zwischen LAN und DSL-Router. Und selbst wenn mein DSL-Router LAN-Intern unerlaubt lauschen und Passwörter (o.ä.) mitschreiben würde, so hat er dennoch keine Möglichkeit, auf Zertifikat und Keyfile lesend zuzugreifen und diese anders als von mir erlaubt zu verwenden. Insofern ist natürlich wegen fehlender Keyfiles auch kein unerlaubter Zugriff von außen möglich. Du solltest also akzeptieren, dass Du mit der Verwendung des AVM-VPNs die Kontrolle über Deine Hardware und Deines Netzwerkes zu einem beträchtlichen Teil aus der Hand gibst und somit möglicherweise in eine Situationen kommst, in der Du nicht mehr allein Entscheidungen für Deine Hardware triffst.
Meine Fritzbox hat definitiv keinen Zugang zu den Dateien, die die Kryptografie und ausschließlich den erlaubten Zugang in mein Netz sicherstellen. Insofern kann sie auch nichts übernehmen und ggf. unautorisiert weitergeben. Alles zusammengenommen sind das für mich wirklich gute Gründe, OpenVPN als Alternative zu verwenden.... auch wenn es -wie wir noch sehen werden- einigermaßen kompliziert einzurichten ist.
Bevor es nun endlich mit der Installation unseres VPN-Netzwerks losgeht, solltest Du Dir aber jetzt noch einmal bewusst machen, um was es hier überhaupt geht: Du öffnest ein Portal in Dein privates Heim-Netzwerk! Das bedeutet, wenn Du im Anschluss daran nicht zweifelsfrei eine auf Wissen beruhende Kontrolle über Deine Hardware hast, entscheidest Du auch nicht darüber, wer diese Hardware mit welchen Absichten verwendet. Punkt! Wie Deine Hardware verwendet wird, entscheiden dann vielleicht irgendwelche Dir völlig unbekannte Menschen. Akzeptiere das einfach. Allein zu denken und darauf zu vertrauen, Du hättest die Kontrolle und es passiert schon nix ... vergiss es! So funktioniert das nicht! Gerade bei den allzu oft vorgefundenen und fast normalen privaten Rahmenbedingungen ist das in Wirklichkeit nur ein Trugschluss. Auf einem potentiell unsicheren Betriebssystem kannst Du keine ausschließliche Kontrolle und somit keine vollständige Sicherheit erwarten, infolgedessen gibt es auch keine Garantie dafür, dass nur Du alleine Entscheidungen für Dein System triffst. | |
Ein potentiell unsicheres Betriebssystem ist es, wenn Du z.B. den Nutzungsbedingungen proprietärer Software ungelesen (oder unverstanden) zugestimmt hast, oder wenn Du Software aus dubiosen Fremd-Quellen (anonyme ppa's oder Quellen im Internet) verwendest, oder wenn Du in der Admin-Group eingetragen bist und als Du selber Programme starten kannst, die dann mit privilegierten Rechten ausgeführt werden. Unter solchen Bedingungen ist der Gedanke ganz allein die exklusive Kontrolle zu haben eine Illusion, ein reines Glücksspiel. Sei Dir deshalb immer zu jeder Zeit bewusst, dass Du im Fall der Fälle niemals nur Dir allein schadest, der Schaden trifft immer uns alle. Mach Dir bewusst, was es bedeutet, wenn Deine Hardware als Mitglied einer Bot-Net-Attacke z.B. einen Energieversorger angreift oder ein Krankenhaus oder eine Bank oder eine Versicherung. So etwas betrifft immer uns alle. Die Kontrolle darüber, wer Deine Hardware verwendet, kannst Du nur dadurch erhalten, wenn Du alles mit Sachverstand und der zweifelsfreien Feststellung "ich verstehe, was ich hier mache" tust. Und nicht vergessen, "Glauben" hat wirklich absolut gar nichts mit "Wissen" zu tun. |
Überblick - Was ist alles zur Einrichtung von OpenVPN notwendig ?
Die folgenden Liste verschafft uns einen kurzen Überblick über das, was uns ab jetzt erwartet.... mit folgender Zielsetzung:
- Ich möchte einen VPN-Zugang einrichten, um auf sichere Art und Weise von außerhalb über das Internet auf die Ressourcen meines Heimnetzwerks zugreifen zu können.
- Für ein Fallback-Szenario wird zusätzlich ein zweites VPN-Netz via TCP auf Port 443 vorgesehen.
- IPv6 soll via NAT geroutet werden. (Kann bei reinen IPv4-Netzen ignoriert werden!)
Dazu wird mit OpenVPN ein End-to-End-Tunnel über den Routing-Mode mit tun-Devices etabliert (alternativ: tap-Devices + Bridging). Als regelmäßig verwendetes Protokoll ist UDP vogesehen. Das Fallback-VPN ist in den Fällen eine mögliche Alternative, wenn ein Gastgeber-WLAN den Datenverkehr auf HTTP(S) beschränkt und sämtliche UDP-Ports über einen Paketfilter gesperrt hat. Bitte unbedingt dabei beachten, dass der Port 443 nicht durch einen anderen Service belegt sein darf, wie zum Beispiel durch einen Web-Server wie Apache oder Nginx. Wird der Port 443 bereits verwendet, steht diese Möglichkeit eines Fallback-VPNs nicht zur Verfügung. Es gibt zwar die Möglichkeit des Port-Sharings, OpenVPN unterstützt das, aber das kann nicht Thema dieses Artikels sein.
Die To-do-Liste:
Was? | Wo? | |
| Benötigte Ports öffnen und deren Weiterleitung einrichten | DSL-Router |
| Statische Routen für die VPN-Netze zum VPN-Gateway einrichten | DSL-Router |
| OpenVPN aus dem Source-Paket kompilieren und ein Deb-Package erstellen | Arbeitsplatz-PC |
| Keyfiles und Zertifikate für Server und alle betroffenen Clients-Geräte erstellen | Arbeitsplatz-PC |
| Config-Files für den Server erstellen | Arbeitsplatz-PC |
| Config-Files für Clients erstellen | Arbeitsplatz-PC |
| Systemd-Service-Units zum Starten der VPN-Daemons und nftables-Regeln erstellen | Arbeitsplatz-PC |
| Deb-Package für OpenVPN installieren | OpenVPN-Server |
| Kernelparameter für Forwarding setzen | OpenVPN-Server |
| Service-Units übertragen und aktivieren | OpenVPN-Server |
| Deb-Package für OpenVPN auf den Laptops installieren | mobile OpenVPN-Clients |
| Keyfiles und Zertifkate auf die betroffenen Laptops übertragen | mobile OpenVPN-Clients |
| On-The-Fly-Starter auf den betroffenen Laptops einrichten, um es nur bei Bedarf zu starten | mobile OpenVPN-Clients |
| OpenVPN-Client auf den betroffenen Smartphones installieren | Smartphone |
| Keyfiles und Zertifkate auf die Smartphones übertragen | Smartphone |
| OpenVPN-Client auf den Smartphones einrichten | Smartphone |
Mit einem Blick auf das nebenstehende Bild versuchen wir uns auch noch einmal kurz zu verinnerlichen, wohin die Reise überhaupt gehen soll, was unser Ziel ist, welche Komponenten wir mir welcher IP in Erinnerung behalten müssen ... und was ganz am Ende, wenn wir fertig sind, hinten rauskommen soll.
Wenn alles korrekt eingerichtet ist, haben wir 3 Netzwerke, 2 Gateways und 3 DHCP-Server in Betrieb genommen. Wir haben Clients, die sich mit allen 3 Netzen verbinden können, zuhause ins heimische LAN und unterwegs in eins der beiden VPN-Netze. Und sie erhalten je nach Netzwerk eine zum Netzwerk passende IP-Adresse für IPv4 und ggf. auch für IPv6. Wir haben dann | |
> das alte Heim-Netzwerk, IP-Range 10.0.1.0/24 und > ein neues VPN-Netzwerk (UDP), IP-Range 10.0.8.0/24 > ein neues VPN-Netzwerk (TCP), IP-Range 10.0.9.0/24 > das alte Gateway und DHCP-Server, IP 10.0.1.1 und > ein neues Gateway, IP 10.0.1.2 sowie > einen neuen VPN-DHCP-Server (UDP), IP 10.0.8.1 > einen neuen VPN-DHCP-Server (TCP), IP 10.0.9.1 |
Für die Vorbereitung der Installation auf Server und Clients verwende ich 2 Systeme, einmal meinen persönlichen PC, der hierfür als Entwickler-PC und als Key-Signing-Machine genutzt wird. Und einen RasPi zum Erstellen des OpenVPN-Binaries für die Arm-Architektur.
Weil mein als Server arbeitender Pi keine Entwicklungstools beinhaltet und ich diese dazu notwendigen Pakete nicht nur für diesen einen Ausnahmefall installieren will, erstelle ich das Paket auf einem Zweit-Pi mit einem eigenem Raspian-Lite. Falls kein zweiter PI zur Verfügung steht, empfehle ich im vorhandenen PI kurzerhand vorübergehend die Karte auszutauschen. Dazu einen shutdown durchführen, eben schnell eine Zweit-Karte mit einem abgespeckten Raspian-Lite rein, das Paket wie beschrieben erstellen, Karte raus, erste Karte wieder rein und den Pi für den Normalbetrieb durchstarten. Von der Zweitkarte übertrage ich dann das Paket zur Sicherung via Card-Reader und SSH auf meinen PC und führe später von dort die OpenVPN-Installation auf dem Server durch.
Für den späteren ersten Funktionstest einer Verbindung von außen über das Internet zum OpenVPN-Server verwende ich meinen Laptop und mein Galaxy-S8. Mit dem S8 kann ich über die Verwendung der Funktion "Mobile Daten" die aktive UMTS-Verbindung via Tethering "weitergeben". Der Laptop meldet sich dazu einfach am WLAN-Accesspoint des Handys an und hat damit über das Handy-Netz eine Internet-Verbindung.
|
Beginnen wir mir den notwendigen Einstellungen in unserem DSL-Router. Wie oben schon in den Bildern sichtbar und erklärt, ist es notwendig, eine spezielle Tür für die OpenVPN-Datenpakete ausdrücklich zu öffnen. Einige weitergehende und durchaus wichtige und mit diesem Artikel unbedingt im Zusammenhang stehenden Informationen zur rudimentären Firewall-Funktion des DSL-Routers habe ich in meinem Firewall -Artikel beschrieben, deswegen begnüge ich mich hier mit einem Verweis und spare mir damit lange Wiederholungen.
Ich empfehle als erstes den Dialog-Modus des Web-Inferfaces unseres DSL-Routers auf "erweitert" oder "Expert" einzustellen. Nur mit dieser Einstellung werden uns auch alle wichtigen Parameter angezeigt bzw. sind änderbar. Ich verwende hier Beispiele für die Fritzbox 7490, die aber im Großen und Ganzen auch passend für die FB 7270 sind. Für alle anderen Router muss man sich die äquivalenten Einstellungen im Menüsystem suchen. Über den Menüpunkt Freigaben werden die zu öffnenden Ports eingerichtet, über die später ein Zugang aus dem Internet heraus in unser lokales Netzwerk ermöglicht wird. Bitte die Schaltfläche Gerät für Freigaben hinzufügen auswählen. | |
Der erste Schritt ist es, den Zielhost für die von außen kommenden Datenpakete zu bestimmen. Erster Empfänger aller Pakete von außen ist immer unser DSL-Router, weil der als einziger eine Internet-taugliche IPv4 innehat. Die IPV4-Adressen aller anderen Clients sind nur lokal gültige Adressen, die nicht internettauglich sind. Auf diesem Bildschirm teilen wir dem DSL-Router mit, welcher PC im LAN als OpenVPN-Ziel-Host diese Pakete erhalten soll. Damit es hier zu keinen Missverständnissen führt, wähle ich immer den Zielhost ausdrücklich über seine in meinem Netz statische IP-Adresse aus. Das ist ein sehr wichtiger Umstand: Wir müssen sicherstellen, dass kein anderer PC diese IP-Adresse zugeteilt bekommt, diese IPv4 muss für den OpenVPN-Server reserviert bleiben. Bitte nach Eingabe des Zielhosts die Schaltfäche Neue Freigabe auswählen. | |
Mit diesen 2 Dialogen können für den zuvor festgelegten Ziel-Host die zu öffnenden Ports vorgegeben werden. Die Bezeichnung OpenVPN_UDP4 und OpenVPN_TCP4 sind von mir willkürlich festgelegt worden, ebenso ist die Wahl der Ports 443 und 55553 willkürlich. Den Port 443 habe ich als Fallback-Port freigegeben, der nur in Ausnahmesituationen verwendet wird, wenn durch den Admin eines für Gäste offenen AccessPoints das primär von mir genutzte UDP-Protokoll gesperrt ist – wovon möglicherweise unprivilegierte Ports oberhalb 1024 betroffen sein können. Der Port 55553 ersetzt den für OpenVPN regulär verwendeten Port 1194. Die Variante mit Port 443 ist eine besondere Spielerei, die bei einer Erst-Einrichtung eigentlich nicht zwingend notwendig ist. Für den Anfang reicht es aus, sich erst mal nur auf den UDP-Port zu konzentrieren und erst später, wenn das läuft, vielleicht über einen alternativen TCP-Port nachzudenken. Und es besteht hierbei noch eine wichtige Besonderheit, die uns durchaus bewusst sein muss. Eigentlich ist der Port 443 ja der für HTTPS-Traffic verwendete Port. Üblicherweise lauscht also ein Web-Server auf Verbindungsversuche, die von außerhalb über DSL-Router über diesen Port "reinkommen". Auf meinem OpenVPN-Server lauscht aber kein Web-Server auf Port 443, ich habe diesen Port im DSL-Router quasi zweckentfremdet. Bei mir lauscht auf dem Ziel-Host nur ein OpenVPN-Server auf den Ports 55553 (UDP) und 55554 (TCP). Man muss sich die Wege eines Daten-Paketes also wie folgt vorstellen: Internet-Anfrage: Annahme durch DSL-Router: Weitergeleitet an OpenVPN-Server: von Port 55553 auf Port 55553 auf Port 55553 von Port 443 auf Port 443 auf Port 55554 Wenn allerdings jetzt sofort beide Freigaben eingerichtet werden, empfehle ich, beide Freigaben einzeln einzurichten. Das heißt, nicht beide gleichzeitig, sondern die zweite erst dann, wenn die erste auf der Einstiegsseite als Aktiv markiert ist. Siehe ergänzend zu den Port-Nummern auch: < Firewall > | |
Die Übersichtsseite zeigt, dass die neuen Freigaben fehlerfrei eingerichtet sind. | |
Als nächstes sind im DSL-Router noch statische Routen zu setzen. Wir haben es ja hier faktisch mit 3 Netzen zu tun. Home-Network: 10.0.1.0/24 Gateway: DSL-Router = 10.0.1.1 OpenVPN-Netz via UPD: 10.0.8.0/24 Gateway: OpenVPN-Server = 10.0.1.2 OpenVPN-Netz via TCP: 10.0.9.0/24 Gateway: OpenVPN-Server = 10.0.1.2 Allein die Weiterleitung vom DSL-Router zum VPN-Server reicht nicht aus. Diese statischen Routen sorgen dafür, dass zwischen den 2 VPN-Netzwerken und dem Home-Netzwerk auch eine normale Kommunikation zwischen VPN-Clients und Home-Netzwerk-Clients möglich ist. Ohne Routen wären im Heimnetz die VPN-Clients unbekannte Ziele... das bedeutet, Pakete mit dem Ziel eines VPN-Clients (also unbekannt) würden die Standard-Route (DSK-Router) ins Internet nehmen und dort irgendwann verworfen werden, weil sie auch dort unbekannt sind. Durch diese neuen Routen wird definiert, dass für Pakete mit dem Ziel 10.0.8/24 und 10.0.9/24 unser OpenVPN-Server das Standard-Gateway ist und nicht der DSL-Router.... also kommen sie auch am Empfänger an. | |
Abschließend werfen wir noch einen Blick auf die Netzwerk-Einstellungen des DSL-Routers. Wir sehen hier die Adressen, die selbstverständlich die gleichen sind, die später bei den Konfigurationsdateien verwendet werden. Das ist sowieso einer der wichtigsten Grundsätze: Wenn wir solche Arbeiten tun oder vorhaben, also z.B. wie hier mehrere miteinander kommunizierende Netzwerke einrichten, so müssen wir uns zu jeder Zeit aller Faktoren bewusst sein. Dabei ist es auf jeden Fall hilfreich, wenn man zuvor ein Papier-Planungs-Netzwerk entwirft, auf dem alle Komponenten schon ihre zukünftigen Parameter erhalten und von dem man beim individuellen Einrichten die betroffenen Werte abliest oder einfach nur, um die eingerichteten Parameter am Ende noch mal mit der Planung zu vergleichen. Ein kleiner Fehler, und schon funktioniert's am Ende nicht... und dann beginnt das frustrierende Drama der Fehlersuche, weil man zunächst mal gar keine Ahnung hat, wo man überhaupt zu suchen anfangen soll. Also ganz wichtig, besser vorher genau planen und beim Einrichten immer äußerst konzentriert und gewissenhaft arbeiten. | |
Gerade im Hinblick auf die angemahnte Sorgfalt und Gewissenhaftigkeit und für das bessere Verständnis von Zusammenhängen (und ggf. auch meiner eigenen Rahmenbedingungen) möchte ich an dieser Stelle noch einen wirklich wichtigen Hinweis platzieren: Alle hier in diesem Beispiel verwendeten Adressen wurden willkürlich von mir festgelegt. Ich hatte hierbei wirklich nur ein einziges Interesse, und zwar einen von Anfang bis Ende nachvollziehbaren durchgängigen roten Faden zu haben. Und darüber hinaus muss dieser Artikel technisch passend und vollständig kompatibel zu meinen Artikel Sicherheit durch Firewall sein - denn das eine ohne das andere ist nur eine halbe Lösung. Die hier verwendeten IP-Adressen sind also keine Empfehlung, sie genau so zu übernehmen. Idealerweise baut man das oder die neue(n) VPN-Netz(e) in das bestehende Heim-Netzwerk ein, was zugegeben alles manchmal sehr kompliziert und umfangreich anmutet. Die stabilste Basis für einen erfolgreichen Abschluss eines solchen Projektes ist deswegen völlig unbestritten immer der Faktor "Verstehen". Ich zeige hier deshalb alles vollständig, damit man bei einer späteren Fehlersuche überhaupt eine Vorstellung über die Zusammenhänge hat, wo man überall nachsehen muss, oder ein grobe Richtung erkennt, in der man sich bei der Fehlersuche "bewegen" kann. | |
Und was mir als Hinweis noch wichtiger ist, das ist mein folgender Rat an alle jene, die glauben, man könne sich ohne Verständnis der Zusammenhänge von Netzwerk, VPN, Protokollen und Paketfilter alles Quick&Dirty auf die Rechner kopieren und einfach starten: Bitte lass es! Du schadest Dir viel mehr, als Du glaubst.... und der Nutzen ist im Vergleich zum Schaden viel geringer, als Du Dir vorstellen kannst. Fahrlässigkeit und Leichtsinnigkeit sind die schlechtesten Voraussetzungen für solcherart exponierten Netzwerks-Zugänge. |
|
Deb-Package für OpenVPN erstellen und installieren
An diesem Punkt verlasse ich jetzt eingetretene Wege und beschreite einen eigenen Weg. Der übliche Weg zur Installation eines OpenVPN-Server/-Client ist meiner Meinung nach, OpenVPN aus dem Distributions-Repository mit apt install zu installieren. Das übliche Ergebnis dabei ist, dass auch eine Script-Umgebung installiert wird, die sich u.a. mit dem Starten und Schließen des Services befasst. Bedauerlicherweise ist das bis zu diesem Zeitpunkt, an dem ich meinen Artikel schreibe, immer noch sysvinit-basierend. Und zum zweiten ist mir die im Repository vorhandene Version zumeist schlichtweg nicht aktuell genug. Außerdem habe ich sowieso einen etwas höheren Anspruch an Flexibilität und Variabilität. Wegen all dieser Gründe verwende ich nicht die Repo-Version, sondern das aktuelle OpenVPN direkt von der Project-Web-Seite.
Der erste Schritt ist, die zum Erstellen notwendige Programme zu prüfen und ggf. zu installieren. Soll das Paket in der normalen Laufzeit-Umgebung des PCs erstellt werden, empfehle ich, das System vorher auf einen aktuellen Stand zu bringen. Wenn das System aktuell ist und nichts aktualisiert wird, kann der Reboot übersprungen werden.
$ su -
# apt update
# apt full-upgrade
# dpkg -l wget
dpkg-query: Kein Paket gefunden, das auf wget passt
# apt install wget
# systemctl reboot
Wir laden nun das aktuelle OpenVPN-Paket herunter. Der Suchbegriff "openvpn.net download" im Browser und auf der Suchmaschine meiner Wahl bringt mir (in den meisten Fällen) gleich im ersten Ergebnis die Download-Seite des Projektes, auf der ich einen Hinweis auf die (am heutigen Tag) aktuelle Version und etwas weiter unten das Source-Code-Paket als Tar-File zum Downloaden finde. Bitte unbedingt darauf achten, den Download des Tar-Files nur von der Projekt-Seite und nicht von irgendeiner Dritt-Seite durchzuführen.
Source Tarball (gzip) openvpn-2.5.7.tar.gz
Das Tar-File lade ich mir einmalig runter und es wird mit dem Browser nach /tmp gespeichert, um es dann später (auf geeigneten Systemen (passende CPU-Architektur)) zu entpacken und dort zu kompilieren.
Das derzeit aktuelle und hier verwendete Paket kann auch direkt heruntergeladen werden. Aber bitte vorher auf der Web-Site überprüfen, ob es wirklich immer noch das aktuelle ist, wenn ja:
# cd /tmp
# wget -c https://swupdate.openvpn.org/community/releases/openvpn-2.5.7.tar.gz
Eine durch das ältere Buster-Release seinerzeit notwendig gewordene Änderung betrifft das Paket "checkinstall", welches vermutlich aufgrund von Fehlern zeitweise nur über die Backports installiert werden konnte. Checkinstall hatte ich bis dahin zum Bauen des Pakets verwendet. Die aktuellen Probleme des Programms, wegen derer es wahrscheinlich noch nicht im regulären Repo verfügbar ist, werden wahrscheinlich im Lauf der Zeit alle korrigiert, aber wenn es eine wirklich einfache Alternative für das gleiche Ergebnis mit sowieso im Betriebssystem vorhandenen Bordmitteln gibt, warum sollte ich da überhaupt ein weiteres Paket installieren? Wie wir sehen werden, ist das auch gar nicht notwendig. Aber speziell zu diesem Punkt möchte ich noch einen wichtigen Hinweis geben, der für beide Methoden gilt:
Das hier von uns selbst erzeugt Deb-Package ist nach seiner Fertigstellung ein statisches Paket, man könnte fast sagen "quick&dirty" erstellt, ohne Prüfsummen, es wird nicht automatisch upgedatet, erhält keine Security-Patches und erfüllt auch nicht die Dokumentationsanforderungen für Debian. Deshalb sind diese Pakete von "geringerer" Qualität als die durch einen Maintainer regulär erstellten Pakete. Das alles ist jedoch nichts wirklich Schlimmes, im Gegenteil, das erzeugte Paket ist technisch astrein und top-aktuell... aber wir sollten/dürfen es nicht verbreiten oder verteilen. Denn das wäre einfach nur unfair gegenüber dem anderen Nutzer, der mit Sicherheit bestimmte Erwartungen an seine Debian-Installation hat, Erwartungen die unser Deb-Package jedenfalls nicht erfüllen kann - selbst wenn es fehlerfrei funktioniert. Rein technisch betrachtet ist das Paket tatsächlich tadellos, aber das ist eben nicht alles, was man dabei berücksichtigen sollte.
Fangen wir an, die Erstellung unseres neuen Deb-Packages vorzubereiten. Weil für die Installation und Inbetriebnahme weitere Werkzeuge notwendig sind, tue ich hier alles von vornherein als "root". Man kann das auch alles umständlich mit sudo-Statements erledigen, aber da ich "sudo" sowieso für völlig überflüssig und geradezu als gefährliches Sicherheitsleck erachte, verschwende ich hier ganz bestimmt keinen Gedanken daran. Ich empfehle aber, meiner Vorgehensweise in \tmp unverändert zu folgen, weil das keine Nachteile beinhaltet und im Ablauf getestet ist.
Weitere und noch zusätzlich notwendige Pakete werden zuerst überprüft. Überprüfen bedeutet nachzusehen, ob die entsprechenden Pakete nicht schon auf dem Rechner installiert sind, um dann nur die noch fehlenden zu installieren. Bitte also nicht einfach blind die Befehlszeilen kopieren und übernehmen und ausführen... es ist jedes mal sicherzustellen, dass nur die jetzt noch fehlenden Pakete installiert werden.... alles andere lassen wir unberührt! | |
# dpkg -l build-essential autoconf automake autotools-dev intltool dpkg-query: Kein Paket gefunden, das auf build-essential passt dpkg-query: Kein Paket gefunden, das auf autoconf passt dpkg-query: Kein Paket gefunden, das auf automake passt dpkg-query: Kein Paket gefunden, das auf autotools-dev passt dpkg-query: Kein Paket gefunden, das auf intltool passt # apt install build-essential autoconf automake autotools-dev intltool # dpkg -l liblzo2-2 libssl-dev liblzo2-dev liblz4-dev libpam0g-dev net-tools iproute2 openssl dpkg-query: Kein Paket gefunden, das auf openssl passt dpkg-query: Kein Paket gefunden, das auf liblzo2-2 passt dpkg-query: Kein Paket gefunden, das auf libssl-dev passt usw... NUR fehlende Pakete installieren! # apt install liblzo2-2 libssl-dev liblzo2-dev liblz4-dev libpam0g-dev net-tools openssl iproute2 | |
# mkdir -p /tmp/openvpn/root/opt/openvpn/plugins # mkdir -p /tmp/openvpn/root/DEBIAN # mkdir -p /tmp/openvpn/root/usr/local/share/man/man8 # mkdir -p /tmp/openvpn/root/usr/sbin | Ich verwende als Zielverzeichnis zum Entpacken und für die Erstellung des Pakets auf allen Systemen einfach /tmp, denn, wenn alles fertig ist, brauch ich den ganzen Kram nicht mehr und lass es mit dem Runterfahren meines Rechner einfach verschwinden. Selbst wenn ich es erneut brauchen würde, habe ich es in wenigen Sekunden neu erstellt, warum soll ich mich also dafür mit Aufwand zum Aufbewahren belasten? Also, weg mit dem unnötigen Kram am Ende. |
# ne /tmp/openvpn/root/DEBIAN/control Package: openvpn Version: 100.2.5.7 Section: misc Priority: extra Architecture: amd64 Depends: liblzo2-2, libpam0g Installed-Size: 8 Maintainer: toml <toml@thlu.de> Homepage: www.thlu.de Description: Openvpn-2.5.7
| Die 100 als Prefix zur Version des Pakets stellt sicher, dass OpenVPN nicht im Zuge der regulären System-Upgrades verändert wird. Die Version 100 ist eine deutlich höhere Version, als es die derzeit aktuelle 2 ist.
Die markierten Werte sind auf eigene Parameter anzupassen
Achtung: Unterhalb des Feldes „Description“ muss als letzte Zeile eine Leerzeile angefügt werden. |
# cd /tmp/openvpn # tar -xf /tmp/openvpn-2.5.7.tar.gz | Das OpenVPN-Tar-Archiv wird in den neu erstellten Zielordner entpackt. |
# cd /tmp/openvpn/openvpn-2.5.7 # ./configure # make | Kompilieren der Sourcen. Bitte jeweils auf Fehlermeldungen achten. Wenn Fehler berichtet werden, dann nicht weitermachen, die Fehler müssen zuerst behoben werden. "Warnings" können allerdings zunächst ignoriert werden. ...und kopieren der benötigten Dateien in unser temporäres build-deb-Verzeichnis: |
# cp /tmp/openvpn/openvpn-2.5.7/src/openvpn/openvpn /tmp/openvpn/root/opt/openvpn # cp /tmp/openvpn/openvpn-2.5.7/src/plugins/down-root/.libs/openvpn-plugin-down-root.so /tmp/openvpn/root/opt/openvpn/plugins # cp /tmp/openvpn/openvpn-2.5.7/src/plugins/auth-pam/.libs/openvpn-plugin-auth-pam.so /tmp/openvpn/root/opt/openvpn/plugins # cp /tmp/openvpn/openvpn-2.5.7/src/plugins/down-root/openvpn-plugin-down-root.la /tmp/openvpn/root/opt/openvpn # cp /tmp/openvpn/openvpn-2.5.7/src/plugins/auth-pam/openvpn-plugin-auth-pam.la /tmp/openvpn/root/opt/openvpn # cp /tmp/openvpn/openvpn-2.5.7/doc/openvpn.8 /tmp/openvpn/root/usr/local/share/man/man8 | |
# cd /tmp/openvpn/root/opt/openvpn/plugins # ln -s ../openvpn-plugin-down-root.la openvpn-plugin-down-root.la # ln -s ../openvpn-plugin-auth-pam.la openvpn-plugin-auth-pam.la # cd /tmp/openvpn/root/usr/sbin # ln -s ../../opt/openvpn/openvpn openvpn | Drei Symlinks zur Vervollständigung erstellen |
# cd /tmp/openvpn # dpkg -b /tmp/openvpn/root openvpn-2.5.7_bullseye_amd64.deb | Nun wird das deb-Package erzeugt |
# cp /tmp/openvpn/openvpn-2.5.7_bullseye_amd64.deb /home | Das neue Deb-Package wird zur späteren Verwendung aus dem /tmp-Dir auf einen nichtflüchtigen Speicher gesichert. |
Achtung: Bitte auf keinen Fall vergessen, dass jedes erstellte Deb-Package ausdrücklich für eine bestimmte Prozessor-Architektur erstellt wurde. Ein amd64.deb ist nicht auf einer 32-Bit-Architektur und auch nicht auf einem Raspberry Pi installierbar. Haben wir noch einen 32-Bit-Rechner, so muss für diese Maschine ein passendes 32-Bit-Deb erstellt werden, was man problemlos mit exakt gleichen Schritten entweder auf der 32-Bit-Maschine oder in einer 32Bit-VM unseres Entwickler-PCs erledigen kann. Und wiederum mit exakt den gleichen Schritten muss das Paket auch auf einem Raspberry Pi für armhf erzeugt werden. Für alle Systeme gilt gleichermaßen, wenn das Deb-Package im Verzeichnis /tmp erzeugt wurde, muss das erstellte Paket sofort gesichert werden, damit es nicht nach einem Shutdown verloren ist. Entweder durch direktes kopieren oder bei einer bestehenden Netzverbindung auch einfach via SSH auf ein nichtflüchtiges Verzeichnis eines anderen Rechners im LAN kopieren. | |
.../openvpn-2.5.7_bullseye_amd64.deb .../openvpn-2.5.7_bullseye_armhf.deb .../openvpn-2.5.7_bullseye_x86.deb | Sofern OpenVPN auf unterschiedlichen Architekturen installiert werden soll, sollten wir am Ende unserer Arbeit für jede Rechner-Architektur ein eigenes deb-Package vorliegen haben, was jeweils auf einem zum Zielsystem passenden System erstellt wurde. |
Auf unserem "Entwickler-PC" müssen wir OpenVPN nun installieren, auch wenn wir es später auf dieser Maschine nicht nutzen. Aber es wird im Laufe der weiteren Arbeiten zum Generieren der notwendigen Keyfiles benötigt.
# dpkg -i /tmp/openvpn/openvpn-2.5.7_bullseye_amd64.deb
Vormals nicht ausgewähltes Paket openvpn wird gewählt.
(Lese Datenbank ... 24744 Dateien und Verzeichnisse sind derzeit installiert.)
Vorbereitung zum Entpacken von .../deb/openvpn_...
Entpacken von openvpn ...
# dpkg -l openvpn
||/ Name Version Architektur Beschreibung
+++-==============-============-============-=========================
ii openvpn 100.2.5.7 amd64 Openvpn-2.5.7
Wir können es später, wenn alle Arbeiten erledigt sind, natürlich auch wieder löschen. Aber genauso gut kann man's auch einfach bestehen lassen. Im Unterschied zu der aus dem Repository installierten Version wird hier nicht der Start des VPN-Daemons beim Systemstart durchgeführt. Weil wir das Paket auf dem Entwickler-PC vermutlich sowieso nicht nutzen, sind es also einfach nur ein paar Dateien in einer Menge von vielleicht 100.000 oder 200.000 weiteren Dateien - mit anderen Worten, nichts worüber man großartig nachdenken muss. Aber wer will, kann es später mit apt purge openvpn auch wieder entfernen.
Einige der hier in dieser Beschreibung angelegten bzw. anzulegenden Dateien können mit dem dieser Beschreibung entsprechenden Inhalt unter der folgenden Adresse runter geladen werden. http://www.thlu.de/Public/openvpn.tar Wenn die im Tar-File enthaltenen Dateien in die späteren Original-Verzeichnisse kopiert werden, um sie dort manuell anzupassen, müssen unbedingt die Rechte-Einstellungen gemäß dieser Anleitung nachbearbeitet werden! Im Übrigen ist es möglich, dass die Beispiele hier in der Anleitung weniger aktuell sind, als die im Tar-File enthaltenen Dateien. Deswegen empfehle ich unbedingt, nur die Beispieldateien aus dem Tar-File zu verwenden und nach /tmp zu entpacken. Bei mir ist das dann der Ordner /tmp/OpenVPN, auf den ich im weiteren Verlauf des Artikels mehrfach Bezug nehme. |
|
Ein paar Basics zu Protokollen, Verschlüsselung und Perfect Forward Secrecy
Trotz ziemlich mühsamen und tagelangen Recherchen im WWW zur Beantwortung der Frage, wie viele Bits braucht's denn nun für eine sichere Verschlüsselung, musste ich irgendwann zweifelsfrei feststellen, dass es ab einem gewissen Level wirklich schwierig wird, verständliche und belastbare Antworten allein durch Suchen zu finden. Aber letztlich muss auch bei solchen Schwierigkeiten trotzdem immer das bereits in der Kapitelüberschrift erwähnte "Perfect Forward Secrecy" (PFS) das angestrebte Ziel sein. Die Probleme dabei sind sehr anspruchsvoll, die im Web gefundenen Lösungen bleiben hinsichtlich der Erklärungen meistens ein wenig vage, bis hin zu völlig fehlenden Erklärungen. Und manchmal erkennt man, dass eine Lösung auch nur woanders abgeschrieben wurde... bis hin zum auch gefundenen und geradezu fatalistischen Fazit, dass es vermutlich wirklich keine ultimative Sicherheit für lange Zeiträume geben wird. PFS beinhaltet jedenfalls nach derzeitigem Wissensstand die maximale Sicherheit dafür, dass heutige OpenVPN-Verbindungen (Mehrzahl!), die jetzt durch irgendeine Instanz unerlaubt mitgeschnitten und gespeichert wurden, auch in der Zukunft nicht rückwirkend mal eben auf die Schnelle entschlüsselt werden können. Es bedeutet, dass, wenn im schlimmsten Fall eine einzelne Sitzung erfolgreich gehackt wurde, dennoch alle anderen früheren und künftigen Sitzungen nicht gleichzeitig ebenfalls gehackt worden sind oder gehackt werden können.
Vor einer technisch gut begründeten Entscheidung über die Art und Weise der Verschlüsselung für den Schutz privater Daten vor unerlaubtem Ausspähen fehlt zunächst eine Antwort auf die wichtigste Frage: Bis wie weit in die Zukunft sollen die von mir verschlüsselten Daten überhaupt sicher sein?
Im Regelfall sollte man dabei an die langfristige Speicherung von Dateien auf einem Speichermedium denken, wenn man für den Lagerort des Mediums nicht garantieren kann, dass sich keine unberechtigten Personen Einsicht oder Zugriff verschaffen können. Deshalb sollen die Dateien ja schließlich verschlüsselt werden. Weil man allerdings davon ausgehen kann, das RSA-2048 in naher Zukunft gebrochen wird oder werden kann, ist das für langfristig zu speichernde Daten vermutlich keine gute Wahl. Allerdings sollte man an diesem Punkt auch mal kurz darüber nachdenken, wer solchen Schutz überhaupt brechen kann, welche Hardware er dazu benötigt und ob das wirklich sogar on-the-fly auch mit unseren Low-Level-Consumer-Geräten möglich ist. Bei diesem Aspekt vermute ich, dass es da schon größeres und deutlich leistungsfähigeres Werkzeug bedarf. Und außerdem korreliert der Aufwand zum Entschlüsseln unserer privaten Daten auch immer mit der Bedeutsamkeit dieser Daten... der Aufwand muss sich schlichtweg lohnen, für belanglosen Kram ist das einfach zu teuer und zu aufwendig. Aber unberücksichtigt davon, besser wäre es dafür auf jeden Fall bereits heute schon RSA-3072 oder sogar RSA-4096 zu verwenden. Vielleicht darf es sogar noch ein bisschen mehr sein... so nach dem Motto "viel hilft viel", vielleicht 8192 oder sogar 16384 Bit? Denn wer kann schon heute beantworten, wie lange solcherart Verschlüsselung überhaupt noch sicher ist. Allerdings löst das sofort auch weitere Fragen aus, z.B. ob die Ver- und Entschlüsselung in sehr hoher Qualität und mit einer echten Langzeit-Perspektive im eigenen täglichen Gebrauch überhaupt praktikabel ist, oder ob das Arbeiten dann möglicherweise unzumutbar länger dauert? Ist das noch erträglich oder sitzt man ständig wartend vor dem Bildschirm? Was ist überhaupt ein gesundes Verhältnis von Performance und Sicherheit und eigenen Anforderungen/Bedürfnissen?
Und als nächstes muss die ebenso wichtige Frage beantwortet werden, mit der uns eine Unterscheidung abverlangt wird: Will ich selber tatsächlich langfristig schutzwürdige Daten verschlüsselt speichern oder erzeuge ich mit OpenVPN-Verbindungen nur dialogartige Kommunikationsdaten mit einer für mich nur kurzlebigen Bedeutung, wobei ich aber verhindern will, dass jemand diese verschlüsselte Kommunikation unerlaubt speichert und sie möglicherweise irgendwann in der Zukunft unautorisiert entschlüsselt?
Bei dieser zweiten Frage geht es um typische kurzlebige Ad-Hoc-Datenverbindungen, die man zwischen zwei vertrauenswürdigen (aber an entfernt voneinander liegenden Standorten befindlichen) Geräten über eine nicht-vertrauenswürdige Datenleitung (das Internet) hergestellt hat. Dabei greift man zum Beispiel von unterwegs mithilfe eines OpenVPN-Tunnels auf sein NAS im heimischen Netzwerk zu, oder auf den Kalender-/Kontakte-Sync des Homeservers, oder auf den heimischen Mailserver oder die Cloud, oder man will einfach nur über seinen eigenen DSL-Router einen sicheren Zugang ins Internet herstellen... was auch immer... also eben genau das, worum es hier in dieser Setup-Dokumentation geht. Hierbei werden nicht explizit Dateien verschlüsselt, sondern lediglich kurzzeitig auftretende Kommunikationsdaten.... und selbst wenn dabei tatsächlich Dateien übertragen werden, auf dem Transportweg sind das letztlich dennoch nur Dialog- oder Kommunikationsdaten, weil sie rechts und links außerhalb des Tunnels wieder ganz normale unverschlüsselte Dateien sind. Der charakteristische Unterschied ist, bei der ersten Frage geht es um den Zugriffsschutz bei der Langzeit-Speicherung von Dateien, bei der zweiten Frage geht es um die Abhörsicherheit eines kurzzeitigen 'Gesprächs' zwischen zwei vertrauenswürdigen Computern über die unsichere Wegstrecke 'Internet'.
Weil die Langzeitspeicherung von Dateien jedoch nicht das Thema dieses Artikels ist, gehe ich auch nur in aller Kürze darauf ein. Aber es ist wichtig, das nicht vollkommen außer acht zu lassen, weil es dabei hilft, die unterschiedlichen (!) Auswirkungen zu verstehen und was es für unsere heutigen OpenVPN-Verbindungen bedeutet, wenn gesagt wird, RSA2048 ist langfristig unsicher. Ganz allgemein wird heute aber auch festgestellt, dass die Verschlüsselung mit RSA-2048 derzeit im Jahr 2019 eben noch nicht gebrochen werden kann. Es wird jedoch empfohlen, schon heute für Langzeitarchive eine über das Jahr 2030 hinausreichende Verschlüsselung z.B. mit RSA-3072 oder RSA-4096 zu wählen. Solange es nicht auf einmal zu einem massiven Forschungs-Durchbruch in mathematischen Erkenntnissen oder zu enormer Leistungsfähigkeit von neuen Computern kommt, ist eine solche Verschlüsselung sicher. Allerdings kann man sich auch die Frage stellen, wenn es irgendwann in der Zukunft Risiken gibt, warum sollte ich dann heute überhaupt noch RSA für diesen Zweck nehmen? Warum sollte ich mir über all das Gedanken machen, wenn ich ein Longterm-Storage doch gleich mit AES256 ohne diese Risiken des möglichen Brechens schützen kann? Genau aus diesem Grund speichere ich solche Daten-Archive bereits heute mit GPG und AES256 verschlüsselt. Dabei unterliegt es dann kompromisslos meiner Verantwortung dafür zu sorgen, dass der Kryptografie-Schlüssel konsequent vor Fremdzugriff geschützt ist. Gelingt das, sind die Daten sicher ... verschlampe ich allerdings die sichere Aufbewahrung des Schlüssels, sind die Dateien möglicherweise auch nicht mehr sicher. Aber hier gilt ergänzend, der verschlampte Schlüssel bedarf mindestens einer Person, die diesem Schlüssel unberechtigt verwendet.
Völlig anders sieht es aber m.M.n. bei Ad-Hoc-Verbindungen mit OpenVPN aus, weil bei dieser temporären Datenverbindung kein gewollter Longterm-Storage beabsichtigt ist, das sind immer alles sehr kurzlebige Daten aus einer Quasi-Dialog-Kommunikation zwischen zwei Geräten. Hier kann es schlimmstenfalls passieren, dass irgendeine fremde Instanz diesen verschlüsselten Datenverkehr unerlaubt mitschneidet und auf einen Zeitpunkt in der Zukunft wartet, um diesen (für mich dann belanglosen) Traffic aus einem weit zurückliegendem Jahr rückwirkend entschlüsseln zu können. Wie zuvor ist also auch für solcherart verschlüsselter Kommunikation selbstverständlich ein Kryptografie-Schlüssel notwendig, hierbei zum fast zeitgleichen verschlüsseln und unmittelbarem entschlüsseln auf der anderen Seite. Und weil es sich hier um zwei im Dialog mit einander 'sprechende' Geräte handelt, muss natürlich beiden Geräten jetzt und in diesem Moment der gleiche Schlüssel bekannt sein, denn wenn beide nicht das 'gleiche' sprechen, gibt's auch keine Kommunikation. Das tatsächlich größte Problem bei solchen Moment-Verbindungen ist also, beide Geräten direkt am Anfang auf den gleichen Schlüssel einzustellen. Keinesfalls kann z.B. der Server bestimmen "das Password lautet heute novembergeheimsache" und überträgt dieses Password dann einfach über das Internet zum anderen Peer, z.B. via Email, oder Whatsapp, oder eine Cloud-Platform von Google oder Microsoft oder ähnlich. Als Ergebnis einer solchen Aktion kann man dann feststellen, dass die Verschlüsselung für diese Sitzung damit gerade eben aufgehoben wurde. Und natürlich kann man einen solchen Schlüssel auch nicht per Briefpost versenden oder persönlich übergeben, weil dann dieser Schlüssel einerseits zu einem statischen Kryptografie-Schlüssel werden würde, der immer wieder erneut benutzt werden würde, und andererseits weil man diese Schlüsselvereinbarung auf ggf. große Entfernung ja schließlich jetzt sofort benötigt. Der statische Schlüssel hätte zudem mit PFS natürlich überhaupt nichts mehr zu tun... wurde eine Sitzung geknackt, sind alle anderen Sitzungen auch geknackt. Das tatsächlich zu lösende Problem bei Beginn einer VPN-Sitzung ist also der geheime Schlüsselaustausch, der unbedingt jedes Mal erneut geschehen muss, bei jedem Mal mit einem neuen Schlüssel als Ergebnis, wodurch schließlich zweifelsfrei verhindert wird, dass ein bereits verwendeter Kryptografie-Schlüssel ein zweites Mal verwendet wird.
Weil man zur Lösung des Problems beim Schlüsselaustausch also keinen symmetrischen Schlüssel verwenden kann (also auf beiden Seiten des Tunnels zeitgleich und sofort verwendbar den gleichen Schlüssel), eben weil dieser nicht sicher transportiert werden kann, besteht die Lösung schon seit langer Zeit darin, zunächst einen asymmetrische Schlüssel verwendenden Algorithmus zu nutzen, wie eben RSA. An diesem Punkt angekommen ist es jetzt notwendig, zunächst einmal sowohl Bedeutung und Unterschied von asymmetrischer und symmetrischer Verschlüsselung zu verstehen. Ein Hauptunterschied von asymmetrischer (RSA/ECC) und symmetrischer Verschlüsselung (AES) besteht darin, dass es beim asymmetrischen Verfahren immer zwei Schlüssel gibt, einen öffentlichen und einen geheimen. Mit dem öffentlichen Schlüssel kann verschlüsselt werden, nur mit dem geheimen kann entschlüsselt werden. Das bedeutet, beide Peers müssen bei Beginn der Sitzung zunächst mal ihren öffentlichen Schlüssel dem Partner senden, was beim öffentlichen Schlüssel durchaus auch über einen unsicheren Weg geschehen kann, denn verschlüsselte Daten können damit eben nicht entschlüsselt werden. Zur Entschlüsselung der empfangenen Daten, die vom Partner mit dem eigenen (zuvor übertragenen) öffentlichen Schlüssel verschlüsselt wurden, verwendet der Empfänger dann seinen geheimen Schlüssel, wodurch sich der Kreis wieder schließt. Ein symmetrischer Schlüssel wird hingegen für beide Schritte verwendet, sowohl zur Verschlüsselung als auch zur Entschlüsselung... was wiederum die Konsequenz beinhaltet, dass man einen symmetrischen Schlüssel keinesfalls über einen unsicheren Weg versenden oder abgeben darf. Denn jeder, der über diesen Schlüssel verfügt, kann unsere Daten damit unerlaubt sowohl entschlüsseln als auch wieder verschlüsseln.
Und trotz der Feststellung, dass RSA-1024 und kleiner anscheinend gebrochen ist und RSA-2048 voraussichtlich in den nächsten Jahren gebrochen werden kann, ist hier und jetzt aber dennoch festzustellen, der Teil der OpenVPN-Kommunikation, der heute mit RSA2048 verschlüsselt wird, kann jetzt im Jahr 2019 noch nicht gebrochen werden. Und die Formulierung „Teil der Kommunikation“ führt uns zu der Folge-Frage „Gibt es noch einen anderen Teil?“. Ja, den gibt es, und das ist der wirklich spannende Unterschied zum o.g. Longterm-Storage. Bei OpenVPN sind die eigentlich wichtigen privaten Daten bereits heute schon nicht mehr mit RSA, sondern mit AES verschlüsselt ... und damit sind sie jetzt schon genau so sicher, wie beim oben erwähnten Procedere mit GNUPG plus AES256. Also gibt es bei OpenVPN zwei Verschlüsselungen, gleichzeitig RSA und AES, gleichzeitig asymmetrisch und symmetrisch ausgehandelt? Ja, genau so ist es. Das bedeutet, es finden tatsächlich zwei voneinander getrennte Verschlüsselungen statt.
Um das zu verstehen, muss man sich kurz mit der Funktionsweise des OpenVPN-Protokolls auseinandersetzen. Üblicherweise verwendet OpenVPN aus Performance-Gründen nicht TCP/IP, sondern UDP/IP. Beide Protokolle arbeiten jedoch auf der gleichen Ebene der Netzwerkschichten. Der Unterschied zwischen beiden ist, dass UPD keine Zuverlässigkeit beinhaltet, keine Fehlerprüfung, keine Bestätigung über Reihenfolge, Empfang oder Fehler oder Neuanforderung eines Datenpaketes... UDP ist schlichtweg stateless. UDP-Pakete werden zwar auf gleicher Ebene wie TCP-Pakete übertragen, aber eben ohne Kontroll-Mechanismen. Das macht es schneller, aber dafür mit geringerer Fehlertoleranz. |
Die eigentlichen OpenVPN-Datenpakete werden wiederum mit einer eigenen Header-Struktur in den UDP-Paketen gekapselt. Um die hierbei bestehenden Mängel (durch die fehlenden Kontroll-Funktionen sowie des bei UDP ebenfalls fehlenden Security-Layers TLS) in einem bidirektionalen Dialog mit dem Anspruch auf Zuverlässigkeit zu beheben, verwendet OpenVPN eine Technik analog DTLS. Bei OpenVPN ist diese Technik allerdings um einige Jahre älter, sie basiert auf dem Multiplexing zweier Kanäle auf einem Port (z.B. 1194). Der Control-Channel emuliert dabei das, wofür TLS bei TCP/IP zuständig ist, also Authentifizierung der Peers, Verschlüsselung, Paket-Integrität, Fehlerbehandlung, auf dem weiterhin z.B. Server-Options 'gepusht' werden können und worüber Peer-Infos ausgetauscht werden. Der Daten-Channel transportiert letztlich separat verschlüsselt unsere schützenswerte persönliche Daten-Nutzlast. Die beiden folgenden Grafiken versuchen das zu veranschaulichen:
Die wichtigen Aufgaben des Control-Channels sind also, Authentifizierung der Peers, Zuverlässigkeit und Sicherheit der Kommunikation zu gewährleisten, sowie die Integrität der durchs Internet übertragenen Pakete sicherzustellen, also bis hin zur Überwachung darauf, dass die ankommenden Pakete auf dem Transportweg nicht manipuliert oder verändert wurden. Der Control-Channel wird zum Schutz der Kommunikation mit einem asymmetrischen Schlüssel verschlüsselt. Die tatsächlich schützenswerten persönlichen Daten werden auf einem eigenen Kanal transportiert, und zwar dem Daten-Channel, wo sie mit AES und einem symmetrischen Schlüssel verschlüsselt werden.
Wie in der folgenden Grafik ersichtlich ist, existiert neben RSA alternativ auch noch ECC, was für Elliptic Curve Cryptography steht. Beiden ist gemein, dass sie eine Grundlage der asymmetrischen Verschlüsselung sind. Beide Algorithmen dienen als Basis für das Diffie-Hellman Protokoll, über das schließlich der eigentliche einmalig geltende symmetrische Sitzungsschlüssel verhandelt wird. Ich habe mich in meinem Setup anstatt für RSA für die Verwendung von ECC entschieden.
Das gibt uns also jetzt einen deutlichen Hinweis darauf, wie man die Sinnhaftigkeit der Überlegung zum angeblich besseren Schutz unserer privaten Daten durch einen Wechsel von RSA-2048 auf hohe RSA-8192 auf dem Control-Channel einschätzen kann. Beides kann jetzt nämlich nicht gebrochen werden, und selbst wenn RSA-2048 im Jahr 2030 gebrochen sein sollte, ist das dennoch irrelevant, weil der Sitzungsschlüssel auf dem Daten-Chanel nicht rückwirkend rekonstruiert werden kann. Mit anderen Worten: eine solch enorme Steigerung bringt im Moment gar nichts, kostet aber, wodurch die Nachteile überwiegen. Das bedeutet aber nicht, dass man die Frage jetzt gedankenlos nach hinten schieben kann, nein, wir müssen uns trotzdem unbedingt auch Gedanken über eine sichere Verschlüsselung des Control-Channels machen, aber doch ein wenig losgelöst von den Lebenszeit-Garantien eines asymmetrischen Schlüssels. Wir brauchen mit Blick auf die Zukunft natürlich auch für den Control-Channel eine starke Verschlüsselung, einfach deshalb, damit uns die Zukunft nicht unbemerkt überholt. Dazu ein kleiner Vergleich, wie asymmetrische Verschlüsselung derzeit im Verhältnis zur symmetrischen Verschlüsselung einzuschätzen ist:
RSA | <= | AES | => | ECC |
| |||
1024 Bit 2048 Bit 3072 Bit 15360 Bit |
| 80 Bit 112 Bit 128 Bit 256 Bit |
| 160-223 Bits 224-255 Bits 256-383 Bits 512+ Bits | = Unsicher = Voraussichtlich sicher bis ~ 2030 (Prognose basierend auf heutigem Wissensstand!) = Sicher über 2030 hinaus (dto.) = dto. |
| ||
Die Steigerung von 2048 auf 3072 Bit ist bei RSA jedoch keine einfache Steigerung um 50% der Sicherheit, auf 4096 ist auch keine Steigerung um 100%, die Steigerung ist immer exponentiell. Die Steigerung von 112 auf 128 Bit und dann auf 256 Bit verändert die tatsächliche Tiefe auf AES bezogen wie folgt: | ||||||||
2^112 = | ~5,19229685853483 x 1033 | echo "2^112" | bc = 5192296858534827628530496329220096 | ||||||
2^128 = | ~3,40282366920938 x 1038 | echo "2^128" | bc = 340282366920938463463374607431768211456 | ||||||
2^256 = | ~1,15792089237316 x 1077 | echo "2^256" | bc = 115792089237316195423570985008687907853269984665640564039457584007913129639936 |
Anmerkung: Es geht hier nicht um mathematische Korrektheit bis auf die letzte Stelle. Für einen rein optischen Eindruck, um welche Größen es hierbei überhaupt geht, ist das aber völlig ausreichend. Es soll lediglich deutlich werden, dass mit einer einfachen Verdopplung tatsächlich eine exponentielle Steigerung verbunden ist. |
Obwohl wir nun wissen, dass es nicht die Aufgabe der Verschlüsselung auf dem Control-Channel ist, unsere persönlichen Daten vor unberechtigtem Zugriff zu schützen, so ist es dennoch wichtig, sich auch mit dem Schutz eben dieses Control-Channels zu befassen.
Daraus resultieren jetzt einige Probleme und die entsprechenden Fragen: 1. Wie transportiere ich einen symmetrischen Schlüssel sicher von meinem Gerät durch das unsichere Internet zum anderen Gerät? 2. Wie verhindere ich, dass (sogar) rückwirkend alle meine Daten gehackt werden können, wenn jemand diesen Schlüssel abgreift/ermittelt/hackt/etc.? Zu 1 kann man sagen: sicher? ist nicht möglich!.... und zu 2 kann man feststellen: verhindern? ist auch nicht möglich! Die Lösung für dieses Problem muss also anders aussehen. Zu 1 lautet sie: Wir übertragen niemals einen symmetrischen Schlüssel über unsichere Wege. Zu 2 lautet sie: Wir verwenden jeden Schlüssel nur ein einziges mal, so das ein bestimmter Schlüssel nur für eine einzige Verbindung gilt. |
Wenn also ein symmetrischer Schlüssel zur Verschlüsselung unserer privaten VPN-Verbindung vor Beginn einer Sitzung nicht auf unsicheren Wegen übertragen werden darf und weil deshalb die beiden Peers bei Beginn der Verbindung noch gar keine Kenntnis über einen gemeinsam und temporär verwendbaren Sitzungsschlüssel haben können, müssen sie sich irgendwie ad hoc auf einen solchen Schlüssel einigen. Dieses Problem wird auf dem Control-Channel unter dem Schutz der asymmetrischen Verschlüsselung gelöst. Auf diesem Kanal können sich die beiden Peers über den Algorithmus des Diffie-Hellman-Protokolls in einer Schlüsselverhandlung auf einen neuen geheimen symmetrischen Einmal-Schlüssel einigen. Die Besonderheit dieses DH-Protokolls ist, dass der gefundene neue symmetrische Schlüssel selbst niemals übertragen wird, sondern das ihn beide Parteien jeder für sich selber errechnen. Dazu wird wie zuvor wieder von beiden Seiten jeweils ein öffentlicher Schlüssel-Anteil ausgetauscht und beide Peers errechnen in Kombination mit dem jeweils eigenen geheimen Teil einen beiden Seiten bekannten symmetrischen Schlüssel.
Hierbei ist lediglich vorher die Entscheidung zu treffen, welcher Algorithmus bei der Schlüsselverhandlung durch DH verwendet werden soll, also entweder RSA oder ECC. Die Wahl der entsprechenden Cipher-Suite erfolgt dann beim Erzeugen der Zertifikate. Bei beiden ist es aber klar, dass das als Publickey/Privatekey-Kombination nicht vollständig geheim ist, sondern das das i.ü.S. nur große Primzahlen sind, wo der Publickey als öffentlicher Schlüssel auch im unsicheren Internet übertragen werden kann. Das ist auch erst mal unkritisch, denn diese Schlüsselverhandlung für den Daten-Channel findet ja auf dem bereits verschlüsselten Control-Channel statt, und der jeweils geheime Schlüsselanteil verbleibt sowieso lokal auf dem Gerät. Die Sicherheit basiert hierbei auf der Überlegung, dass der öffentlich übertragene Schlüssel ohne weitere Bestandteile zu kennen nicht mehr zurück in seine ursprünglichen Bestandteile zerlegt werden kann. Ein weitaus wichtigerer Aspekt bei der Schlüsselverhandlung ist jedoch der Anspruch, unbedingt eine ephemeral Cipher-Suite zu verwenden, die zweifelsfrei einen kurzlebigen Kryptografie-Schlüssel für eine einmalige Verwendung verhandelt, was derzeit durch das aktuelle TLS 1.3 sichergestellt ist. Ob jetzt als verwendeter Algorithmus nun RSA oder ECC besser ist oder schlechter ...?... die Frage muss sich jeder selber im Internet beantworten. | Die Funktionsweise des DH-Algorithmus vereinfacht dargestellt: |
Für uns ist hierbei nur die Erkenntnis wichtig, ein so verhandelter Schlüssel hat wirklich nur für die aktuelle VPN-Sitzung Gültigkeit und kann selbst bei Vorliegen allen vergangenen Datenmaterials vermutlich nicht rekonstruiert werden... ganz egal und völlig unberücksichtigt davon, ob zuvor RSA-2048 oder RSA-8192 oder ECC den Control-Channel verschlüsselt hat. Und wenn man aus dem vielleicht vorliegenden Datenmaterial eines Mitschnitts ephemere Schlüssel nicht rekonstruieren kann, können auch die damit und mit AES256 verschlüsselten privaten Daten auf dem Daten-Channel nicht rückwirkend entschlüsselt werden.
Diese Schlüsselverhandlung bei Beginn einer OpenVPN-Verbindung zum Schutz des Daten-Channels findet also auf dem bereits verschlüsselten Control-Channel statt, wobei das Diffie-Hellman-Proktoll selber zur Schlüsselverhandlung nicht extra verschlüsselt ist. Und genau damit haben wir jetzt noch einmal deutlich die Bedeutung der asymmetrischen Verschlüsselung auf dem Control-Channel festgestellt... und zwar die Kommunikation an sich zu schützen, damit am Ende die vom Control-Channel unabhängige AES-Verschlüsselung auf dem Daten-Channel auf zweifelsfrei sichere Weise erfolgen kann. RSA/ECC schützt die Kommunikation auf dem Control-Channel und dort insbesondere auch die Schlüsselverhandlung zur Findung des symmetrischen Schlüssels, AES schützt dann mit diesem Schlüssel unsere auf dem Daten-Channel übertragenen Daten.
Vor dem Hintergrund der Prognose einer anscheinend begrenzten 'Haltbarkeit' einer RSA-2048-Verschlüsselung befassen wir uns nun kurz mit den vorhandenen Risiken. Fakt ist, eine schwache RSA-Verschlüsselung macht die Kommunikation auf dem Control-Channel angreifbar, wenn auch nicht heute direkt, sondern eher in der Zukunft rückwirkend. Theoretisch ist es also denkbar, wenn die Verschlüsselung erst einmal gebrochen ist, dass eine aufgezeichnete komplette Kommunikation auf dem Control-Channel rückwirkend lesbar ist. Das beinhaltet dann ggf. den Umstand, dass auch die in der Schlüsselverhandlung ausgetauschten öffentlichen Parameter möglicherweise unautorisierten Personen bekannt sind. Allerdings kann damit immer noch nicht sofort auch der Daten-Kanal entschlüsselt werden, es fehlt ja noch von beiden Seiten der geheime Teil aus der Schlüsselverhandlung, der nicht übertragen wurde. Möglicherweise ist es irgendwann in der Zukunft sogar möglich, aus einer mitgeschnittenen OpenVPN-Sitzung nicht nur den Control-Channel zu hacken, sondern auch den geheimen Schlüssel des Daten-Channels zu rekonstruieren. Das könnte möglicherweise dadurch begünstigt sein, wenn die beiden Peers in der Schlüsselverhandlung quasi wiederholt den gleichen Key quasi als Static-Session-Key verwenden würden. Aus mehreren mitgeschnittenen Sitzungen im Rahmen einer quasi fortlaufenden Überwachung wären dann wegen des größeren Daten-Material-Umfangs evtl. bessere Möglichkeiten für mathematische Rückschlüsse gegeben. Aber das führt uns dann zwangsläufig zu der Erkenntnis, dass man Wiederholungen des zuletzt verwendeten symmetrischen Schlüssels auf dem Daten-Channel besser kategorisch ausschließt, was durch TLS 1.3 sichergestellt sein sollte.
Also, nicht die sinnlos übertriebene Steigerung der RSA-Tiefe auf dem Control-Channel ist die Lösung, denn da ist der Wechsel von 'Schlecht' auf 'Optimal' auf 'Überoptimal und wieder Schlecht' schnell geschehen. Die optimale Lösung liegt bei der Wahl der richtigen Cipher-Suite, die dafür sorgt, dass ein einmalig generierter symmetrischer Schlüssel keinesfalls wiederholt wird oder wiederholbar ist und auch nicht aus dem vorliegenden Datenmaterial rekonstruiert werden kann. Wenn also tatsächlich die Verschlüsselung des Control-Channels irgendwann gebrochen wäre, bedeutet das jedenfalls noch lange nicht, dass auch wirklich unsere Daten auf dem Daten-Channel gehackt worden sind. Und wenn wir für diesen Kanal einen ephemeren Schlüssel verwenden, bedeutet das auf jeden Fall, dass mit einem einzelnen gehackten symmetrischen Schlüssel keinesfalls frühere Sitzungen entschlüsselt werden können. Es reicht also überhaupt nicht aus, nur die Verschlüsselung des Control-Channels zu brechen, um sofort Zugang zu unseren vertraulichen Verbindungsdaten zu haben. Wer also wirklich besorgt ist, sollte sich zwischen ECC und RSA-4096 entscheiden... beides ist nach heutigem technischen Wissen noch lange sicher.
Außerdem vertrete ich an der Stelle unverändert den Standpunkt, das ist doch alles vor dem Hintergrund der eher geringen Bedeutung meiner privaten Daten sowieso viel zu aufwendig. Darüber hinaus ist doch auch viel einfacher an relevante Daten heranzukommen, wenn es gelingt die Daten-Quelle selber zu kompromittieren... z.B. durch Trojaner resp. den Staatstrojaner direkt auf der Festplatte des PCs, über vielleicht subversive Software aus fremden Quellen (ppa's), durch proprietäre unkontrollierbare Software, durch subversive AddOns, Plugins, Apps, durch Ausnutzung bzw. Missbrauch von administrativen Rechten (sudo) leichtsinniger oder fahrlässiger User. Dabei findet das Ausspähen der Daten direkt an der Quelle statt, bevor überhaupt eine Verschlüsselung Schutz bieten kann. Allein auf OpenVPN zu vertrauen und gleichzeitig die Integrität des eigenen Netzwerks durch leichtsinnig installierte Fremd-Software fahrlässig zu behandeln ist sicher keine gute Lösung.
Als weiteres wirklich relevantes Problem erachte ich zudem die Frage, was sich bei allen Betrachtungen auch klar herausgestellt hat, wie kann ich sicherstellen, dass der Host auf der anderen Seite wirklich der ist, der er zu sein vorgibt? Ich muss mir für den Erfolg all meiner Schutzmaßnahmen sicher sein, dass bei der Schlüsselverhandlung auf dem Control-Channel auch wirklich meine zwei vertrauenswürdigen Geräte sicher verschlüsselt verbunden sind. Kommuniziere ich nämlich unbemerkt mit einem MITM oder einer Middlebox, ist es faktisch völlig egal, ob ich mit dem oder dem Mann im Mond über RSA-1024 oder RSA-15360 kommuniziere.... dann verhandele ich nämlich mit einem unautorisierten Dritten über den symmetrischen Schlüssel und nicht mit dem gewollten Partner. Dann spielt es keine Rolle, mit welcher Logik oder Schlüsseltiefe verschlüsselt wird, die 'Leitung' ist gehackt. Andersrum ist es heute noch ebenfalls egal, wenn die Integrität beider Peers und der Verbindung unzweifelhaft ist, ob ich RSA2048 oder größer verwende... in dem Fall ist RSA2048 heute genauso sicher, wie ein höherer Wert, weil darüber auf zweifelsfrei sichere Weise ein nur einmalig gültiger symmetrischer Schlüssel für den Daten-Channel verhandelt wurde.
Das primäre Ziel muss deswegen immer sein sicherzustellen, dass der andere Peer auch wirklich der ist, der er vorgibt zu sein... und deshalb muss ich meine Zertifikate durchaus vor unberechtigtem Zugriff geschützt sicher aufbewahren, eben damit nicht jemand Fremdes mit der Verwendung eines gestohlenen Zertifikats vorgeben kann, jemand zu sein, der er gar nicht ist.
Ums nun zum Ende zu bringen ... bei all den vielen vorhandenen Faktoren, die man beachten muss und die es einem selber wirklich sehr schwer machen, für die Lösung der eigenen Ansprüche überhaupt einen Überblick zu behalten und belastbare Entscheidungen treffen zu können, lautet mein Fazit für dauerhaft sichere OpenVPN-Verbindungen:
|
Erstellen der Konfigurationsdateien, Keyfiles, Zertifikate und Service-Units
Weil auch dieses Thema wieder eine kleine Herausforderung darstellt, erfolgt als erstes ein Überblick darüber, was alles notwendig ist und was dafür zu tun ist. Es sind die Konfigurationsdateien für Server und Client-Systeme notwendig, sowie Service-Units, die den OpenVPN-Server in den Systemstart einreihen. Jeder Aufbau einer VPN-Verbindung fängt mit einer Authentifizierung an. Beide Teilnehmer müssen sich unzweifelhaft zu erkennen geben und müssen nachweisen, dass sie auch wirklich der sind, der sie zu sein vorgeben. Diese eindeutige Authentifizierung findet über ein für das Client-Gerät "personifiziertes" Zertifikat und Keyfile statt.
Um die folgenden Dateien müssen wir uns nun kümmern bzw. diese erstellen:
Datei | Benötigt durch | Zweck: | Geheimhaltung: |
server_udp.conf | server | OpenVPN-Konfiguration | nein |
server_tcp.conf | server | dto. (von Port 443) | nein |
|
|
|
|
client_udp.conf | alle clients | dto. | nein |
client_tcp.conf | alle clients | dto. (für Port 443) | nein |
|
|
|
|
Datei | Benötigt durch | Zweck: | Geheimhaltung: |
ca.key | key signing machine | Root CA Key (wird zur Erstellung aller Client-Certs benötigt, unbedingt unzugänglich aufbewahren) | JA! |
ca.crt | server + alle clients | Root CA Certificate | nein |
ta.key | " | Encrypt + HMAC | ja |
server.crt + server.key | server | Zertifikat + Key für Authentifizierung und Encrypt | Cert=nein, Key=ja |
dh4096.pem | server | Diffie Hellman Parameters | nein |
client1.crt + client1.key | client1 | Zertifikate + Keys für Peer-Authentifizierung und Encrypt | Cert=nein, Key=ja |
client2.crt + client2.key | client2 | ||
client3.crt + client3.key | client3 | ||
|
|
|
|
Datei | Benötigt durch | Zweck: | Geheimhaltung: |
openvpn.service | server | Service-Unit für Systemstart | nein |
openvpn@.service | server | dto. | nein |
set-nftables-vpn.service | server | dto. | nein |
Geheimhaltung ist hier immer aus der Perspektive der CA-Signing-Machine (hier ist das mein Entwicklungsrechner) zu sehen. Von diesem Rechner werden an den Server und den Client-Systemen sowohl ein Zertifikat als auch ein Keyfile herausgegeben, denn beides wird bei der späteren Verbindungsaufnahme benötigt. Ab dem Moment der Herausgabe sind diese Dateien aber nicht mehr wirklich geheim, sie sind ja herausgegeben und ab jetzt hat nicht mehr die Key-Signing-Machine die absolute Kontrolle darüber, was mit diesen Dateien passiert. Es liegt jetzt in der Sorgfalt und der Hand dessen, der das jeweilige Client-Gerät bedient. Und auf dem Server liegt es in der Hand des Admins, der den Server wirksam gegen Zugriff von außen geschützt hat. Die auf den Client-Systemen vorhandenen Certs und Keys sind aber immer noch und ohne jeden Zweifel als äußerst "brisant" einzuschätzen, und natürlich müssen wir diese Dateien vor unberechtigtem Zugriff und vor der Öffentlichkeit als Top Secret schützen. Jeder Angreifer, der sich dieser Dateien bemächtigt, könnte sich damit als jemand ausgeben, der er gar nicht ist und sich dadurch einen vollständigen Zugriff auf unser Netzwerk verschaffen.... und wir würden das vielleicht noch nicht mal bemerken. Auf einem unbeaufsichtigten Laptop oder auf einem leicht zugänglichen Smartphone ohne Einschalt- oder Aktivierungsschutz würde ich diese Dateien jedenfalls nicht unverschlüsselt aufbewahren.
Als nächstes sind jetzt 4 Konfigurations-Files zu erstellen oder - was der bessere Weg ist - wir verwenden die Dateien aus dem zum Artikel gehörenden Tar-Archiv. Zwei sind für den Server vorgesehen, die anderen 2 werden auf allen infrage kommenden Client-Systemen installiert. Wir werden zwar alle Dateien verwenden bzw. installieren, beginnen aber bei der Inbetriebnahme zunächst nur mit der UDP-Konfiguration - so ist das auch weiter unten in der systemd-Service-Unit vorgesehen. Die TCP-Variante via Port 443 ist für mich nur eine Fallback-Installation. Im Regelfall funktioniert das UDP-Protokoll bestens.... zumal es auch den Vorteil hat, dass es performanter ist. Aber ich zeige dennoch beide Fälle, einfach auch aus dem Grund, damit die Geringfügigkeit der Anpassungen erkennbar sind. Wenn das UPD-basierte Protokoll läuft, ist es tatsächlich ein einfaches, zu einem späteren Zeitpunkt auf gleichem Weg wie zuvor auch den Daemon für das TCP-Protokoll in Betrieb zu nehmen und die Freigaben im Router einzurichten. Und wer sowieso nur vorhat, sich überwiegend hier innerhalb DE von unterwegs via UMTS mit seinem Heim-Netzwerk zu verbinden, wird die TCP-Variante eigentlich gar nicht verwenden, denn UDP läuft hierbei wirklich bestens.
TCP ist immer nur dann eine Fallback-Alternative, wenn ein übereifriger Admin sein öffentlich zur Verfügung gestelltes WLAN absichtlich oder dilettantisch kastriert hat. Das ist mir zwar nur selten passiert, aber ab und zu ist es so. Und in solchen Fällen ist es praktisch, eine Alternative zu haben... eben als Fallback via TCP Port 443.
Wenn das Tar-Archiv openvpn.tar nach /tmp entpackt ist, finden wir die folgenden neuen Verzeichnisse vor, in denen die benötigten Dateien teilweise schon enthalten sind. Im weiteren Ablauf werden wir noch Keyfiles und Zertifikate dort hineinkopieren und ganz am Ende daraus ein Setup-Paket erstellen, welches uns dann bei den einzelnen Installationen auf Server- und Client-PCs unterstützen soll.
# cd /tmp
# wget -c http://www.thlu.de/Public/openvpn.tar
# tar -xf /tmp/openvpn.tar
# ls /tmp/OpenVPN
drwxr-x--- 2 thomas thomas 60 2018-10-14 15:53 ca_client
drwxr-x--- 2 thomas thomas 60 2018-10-14 15:53 ca_server
drwxr-x--- 2 thomas thomas 120 2018-09-11 21:11 easy-rsa
drwxr-x--- 3 thomas thomas 140 2019-08-20 15:59 /etc/openvpn
drwxr-x--- 2 thomas thomas 100 2019-08-20 15:45 /etc/systemd/systemd
drwxr-x--- 2 thomas thomas 80 2018-10-14 11:51 /usr/local/bin
Die OpenVPN-Konfigurations-Dateien: jetzt hier in /tmp/OpenVPN/root/etc/openvpn, später auf den Systemen installiert in /etc/openvpn |
Client-Konfiguration für Transport-Protokoll UDP
client_udp.conf | Client-Konfiguration für Transport-Protokoll TCP
client_tcp.conf | ||
tls-client remote myprivateddnslink.net
proto udp dev tun0 port 55553
remote-cert-tls server pull ping 60
cipher AES-256-GCM auth SHA256 auth-nocache
ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/client.crt key /etc/openvpn/keys/client.key tls-crypt /etc/openvpn/keys/ta.key
mute 10 verb 3 explicit-exit-notify log-append /var/run/openvpn/client.log | tls-client remote myprivateddnslink.net
proto tcp-client dev tun0 port 443
remote-cert-tls server pull ping 60
cipher AES-256-GCM auth SHA256 auth-nocache
ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/client.crt key /etc/openvpn/keys/client.key tls-crypt /etc/openvpn/keys/ta.key
mute 10 verb 3
log-append /var/run/openvpn/client.log | ||
Client verbindet sich als Roadwarrior mit dem OpenVPN-Daemon des Servers via UDP auf Port 55553 | Client verbindet sich als Roadwarrior mit dem OpenVPN-Daemon des Servers via TCP über Extern-Port 443 auf Port 55554 | ||
Server-Konfiguration für Transport-Protokoll UDP
server_udp.conf | Server-Konfiguration für Transport-Protokoll TCP
server_tcp.conf | ||
server 10.0.8.0 255.255.255.0 server-ipv6 fd00:10:0:8::/64
proto udp dev tun0 port 55553 topology "subnet"
push "topology subnet" push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 10.0.1.1" push "dhcp-option DNS fd00:10:0:1:228d:ff77:fe11:2892" push "route 10.0.1.0 255.255.255.0" push "route-ipv6 fd00:10:0:1::/64"
ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/server.crt key /etc/openvpn/keys/server.key
cipher AES-256-GCM auth SHA256 auth-nocache
dh /etc/openvpn/keys/dh4096.pem ecdh-curve secp384r1 tls-version-min 1.3 tls-crypt /etc/openvpn/keys/ta.key
ping-timer-rem keepalive 10 60 persist-key persist-tun group vpnuser user vpnuser
verb 3 mute 10 log-append /var/log/openvpn/openvpn_udp.log | server 10.0.9.0 255.255.255.0 server-ipv6 fd00:10:0:9::/64
proto tcp-server dev tun1 port 55554 topology "subnet"
push "topology subnet" push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 10.0.1.1" push "dhcp-option DNS fd00:10:0:1:228d:ff77:fe11:2892" push "route 10.0.1.0 255.255.255.0" push "route-ipv6 fd00:10:0:1::/64"
ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/server.crt key /etc/openvpn/keys/server.key
cipher AES-256-GCM auth SHA256 auth-nocache
dh /etc/openvpn/keys/dh4096.pem ecdh-curve secp384r1 tls-version-min 1.3 tls-crypt /etc/openvpn/keys/ta.key
ping-timer-rem keepalive 10 60 persist-key persist-tun group vpnuser user vpnuser
verb 3 mute 10 log-append /var/log/openvpn/openvpn_tcp.log |
Schauen wir uns noch kurz ein paar der wichtigen Parameter und deren Bedeutung an:
remote myprivateddnslink.net | my private ddns link.net ist ein immer gleichbleibende symbolischer Name für die öffentliche IP-Adresse unseres DSL-Routers, mit dem wir über das Internet unser Netzwerk zuhause erreichen können. Üblicherweise richtet man sich dafür einen dyndns-Account bei einem entsprechenden Dienstleister ein, um dann bei Verwendung dieses Namens an die Internet-taugliche WAN-IP-Adresse seines heimischen DSL-Routers weitergeleitet zu werden. Wer über eine Fritzbox verfügt hat es einfach, MyFritz bietet einen solchen Dienst kostenlos an. Warum das notwendig ist, ist einfach zu verstehen, wenn man sich das einmal so vorstellt, als hätte man kein feste heimische Telefonnummer, sondern eine täglich wechselnde, veranlasst durch den Telefon-Anbieter. Dann versuch mal zuhause anzurufen, wenn Du unterwegs bist und Dir die neue Nr. unbekannt ist. Dieses Problem löst der symbolischer Name, beim Netzwerk ist es der DynDNS-Account. Es gibt zwar Tricks und Mittel und Wege, z.B., wenn man einen eigenen Web-Space hat... aber das ist Aufwand und erfordert hohe Sachkenntnis. |
remote-cert-tls server | Es ist völlig normal, mehr als 1 Client-CA herauszugeben, deshalb, weil man auch mehrere verschiedene Mobil-Geräte verwendet. Aber es wird eigentlich nie mehr als eine einzige Server-CA installiert. Und weil es sich bei den VPN-Clients meist um mobile Geräte handelt, die oft an unsicheren Standorten betrieben werden und die z.T. auch unsichere Software verwenden, werden natürlich zwangsläufig auch mehr Clients gehackt, als fest-installierte Server, die sich zudem auch noch hinter dem eigenen meist sicheren DSL-Router befinden. Mit diesem Parameter wird versucht zu verhindern, dass ein sich unrechtmäßig angeeignetes Client-Zertifikat von einem Angreifer dazu genutzt wird, sich einem anderen Client gegenüber als Server auszugeben. Ein richtiges Server-Zertifikat enthält ein Flag, welches es als Server-Cert identifiziert, was mit dieser Anweisung vom Client überprüft werden kann. Es handelt sich somit um eine zusätzliche Sicherheitsprüfung. Eine umgekehrte Prüfung, das also der Server prüft, ob es ein echtes Client-Zertifikat ist, kann man machen, hat aber rein logisch betrachtet wenig Sinn, weil ein Server-Cert nicht so einfach entwendet werden kann. Und wenn das wirklich passiert wäre, dann hat man ein echtes und größeres Problem, weil dann nämlich der Server als solcher kompromittiert ist. |
port 55553 port 55554 | Muss natürlich angepasst werden, wenn eigene Ports vorgesehen sind. Für UDP ist Port 1194 der Default-Port, den man auch problemlos verwenden kann. Vielleicht ist hier der Hinweis interessant, dass auf dem UDP-Port überhaupt keine Verbindungs-Fehlversuche durch Fremde im Protokoll nachgewiesen oder festgestellt sind. Fehlversuche auf dem Fallback-Port 443 gibts allerdings täglich. |
tls-crypt /etc/openvpn/keys/ta.key | Im Vergleich zu tls-auth leistet tls-crypt grundsätzlich das gleiche, verschlüsselt aber zusätzlich noch den gesamten Traffic auf dem Control-Chanel mit einem symmetrischen Schlüssel. Die Richtungsangabe ist hierbei nicht mehr notwendig. |
dh /etc/openvpn/keys/dh4096.pem ecdh-curve secp384r1
| Die Wahl, ob für die asymmetrische Verschlüsselung RSA oder ECC zugrunde gelegt wird, erfolgt beim Erstellen der Zertifikate, siehe vars weiter unterhalb.
Das Aushandeln eines symmetrischen Schlüssels erfolgte mithilfe des Diffie-Hellman-Algorithmus. --dh ist ein Parameter auf der Server-Seite zur Verwendung beim RSA-Algorithmus. Dieses Tutorial verwendet jedoch ECC. Aber unberücksichtigt davon, ob zuvor ECC oder RSA gewählt wird, sollte auf jeden Fall trotzdem ein dh4096.pem-File generiert und in die Conf eingetragen werden. Der Hintergrund ist, dass ansonsten bei fehlendem Pem-File die im Programm vorhandenen 'hard-coded parameter' verwendet werden, wodurch die Sicherheit wieder herabgesetzt wird und was möglicherweise eine 'Logjam Attack' begünstigt.
Kontroll-Befehle im Terminal, um zu prüfen für welchen Algorithmus die Zertifikate erstellt wurden:
openssl ec -noout -text -in /etc/openvpn/keys/server.key openssl rsa -noout -text -in /etc/openvpn/keys/server.key |
tls-version-min 1.3 | Die für die Sicherheit wichtigste Einstellung. Damit wird beschränkt, wie weit die Sicherheit reduziert werden darf oder soll, damit sich ggf. auch ältere Geräte verbinden können. TLS 1.3 bietet derzeit die best-mögliche Sicherheit. Mit meiner Hardware gab es bei dieser Einstellung keine Probleme, alle Systeme unterstützten das. Falls auch Geräte verwendetet werden sollen, die nur den älteren Standard verwenden können, musst hier auf 1.2 oder ggf. noch weiter zurück geändert werden.
An dieser Stelle noch mal der Hinweis auf den Parameter --tls-cipher. Das ist ein Ergänzungsparameter, der die Sicherheit nicht verbessert, sondern immer nur einschränkt. Die konstante Vorgabe einer Cipher hat den Nachteil, dass sie auch dann beibehalten wird, wenn ein System eigentlich eine Cipher-Suite mit höherer Security verwenden würde und könnte. Siehe dazu die 'preferred list', in der immer die höchstwertige geeignete Cipher verwendet wird. Geeignet bedeutet, dass beide Peers die gewählte Cipher-Suite unterstützen. Wenn ein einzelnes Gerät eine hohe Sicherheit nicht unterstützt, ist es eine wirklich schlechte Entscheidung, deshalb mit ---tls-cipher die Gesamtsicherheit für alle Geräte zu reduzieren.
Kontroll-Befehle im Terminal: openvpn --show-tls openvpn --show-ciphers | less openvpn --show-curves | less |
auth SHA256 auth-nocache | Mit SHA256 erfolgt die Authentifizierung der Paketintegrität (HMAC) auf der Protokoll-Ebene. 'No Cache' verhindert, dass zur Authentifizierung eingegebene Passwörter im Speicher verbleiben und somit u.U. ausgelesen werden könnten. |
server-ipv6 fd00:10:0:8::/64 push "dhcp-option DNS fd00:10:0:1:228d:ff77:fe11:2892" push "route fd00:10:0:1::/64" | Diese Einträge sorgen dafür, dass bei meinem Dual-Stack-Account der IPv6-Stack komplett durch den VPN-Tunnel geroutet wird. Das bedeutet, sogar wenn ich mit meinem S8 via UMTS (= IPv4-Netz) Tethering erlaube, so hat mein Laptop als WLAN-Client des S8 trotzdem einen vollständigen IPv6-Stack verfügbar, mit der IPv6 (GUA) des OpenVPN-Servers als Gateway.
Beinhaltet der heimische DSL-Account ein reines IPv4-Netz, so müssen diese Zeilen mit dem Comment-Tag '#' deaktiviert werden. |
push "dhcp-option DNS 10.0.1.1" push "route 10.0.1.0 255.255.255.0" | Hier ist natürlich die IP-Adresse des heimischen DSL-Routers und das von ihm repräsentierte Netzwerk einzutragen, siehe: |
group vpnuser user vpnuser | Die Festlegung, unter welcher UID und GID die VPN-Prozesse im System laufen. Muss man nicht, kann man aber machen und verbessert die Sicherheit, weil der User vpnuser keine privilegierten Rechte im System besitzt. |
log-append /var/run/openvpn/client.log | Auf dem Client besteht immer nur eine einzige aktive Verbindung zu einer Zeit. Also kann auch immer gleichbleibend dasselbe Log verwendet werden. Ich speichere es unter tmpfs, weil ich es nur zum reinschauen brauche, wenn es Probleme gibt. War eine Verbindung erfolgreich, ist es Datenmüll, der beim nächsten Poweroff des Rechners vergessen wird. |
log-append /var/log/openvpn/openvpn_udp.log log-append /var/log/openvpn/openvpn_tcp.log | Auf dem Server sind die Grundlagen anders, weil wegen 2 möglicher Protokolltypen auch 2 Daemons gleichzeitig laufen, die jeder für sich eigene Log-Daten erzeugen. Darüber hinaus werte ich nachträglich über Port 443 kommende Verbindungen aus und übertrage wiederholt vorkommende Hacking-IPs in meine Paketfilter-IP-Blacklist. Mir ist aufgefallen, dass es eine nur Handvoll gleicher IPs sind, die ununterbrochen eine Kontaktaufnahme versuchen. Alle anderen täglich ankommenden Einzel-Versuche sind möglicherweise nur Irrläufer, die ich ignoriere. |
Alle weiteren Parameter können einfach auf der Projektseite von OpenVPN nachgesehen werden, oder noch einfacher via
# man openvpn | less
auf einem System, auf dem OpenVPN installiert ist. Sucht man einen bestimmten Parameter, wie z.B. persist-key, tippt man shift-7 (das Zeichen /) auf der Tastatur und gibt unten auf der Eingabe-Zeile den Suchbegriff --persist-key (mit führenden --) ein. Nach Drücken der Entertaste springt less zum ersten Vorkommen, mit Taste "n" springt es zum nächsten. Taste "q" beendet less.
Wie wir in der Tabelle der "benötigten Dateien" oberhalb schon gesehen haben, müssen sowohl für den Server als auch für jeden Client unterschiedliche und jeweils individuelle Keyfiles und Zertifikate erstellt werden. Alle benötigten Files werden im Zusammenwirken mit dem neu installierten OpenVPN, OpenSSL und der Script-Sammlung aus dem Paket Easy-RSA erstellt. Und selbstverständlich werden im Anschluss die Keyfiles so gehandhabt, dass keines der Systeme die Keyfiles eines anderen System sehen oder lesen oder verwenden kann. Das bedeutet, wir kopieren auf jeden Rechner nur genau die für diesen Rechner bestimmten Dateien.
Damit uns das aber hinterher in der Handhabung während der Installation nicht unnötig schwer gemacht wird, packen wir einfach für alle Systeme die benötigten Dateien in ein Archiv, aus dem wir dann nach Bedarf für jedes System genau die Dateien herauskopieren, die dort explizit benötigt werden. Eine Besonderheit ist das zweite Archiv, welches die PKI-Struktur enthält. | ||
Jeder, der über diese Verzeichnisstruktur verfügt, kann damit neue Schlüssel erzeugen und diese für einen Zugang in unser Netzwerk verwenden, auch außerhalb unserer Kenntnisnahme. Deswegen muss dieses PKI-Archiv absolut sicher und vor Zugriff geschützt aufbewahrt werden, also idealerweise nicht auf dem PC, an dem man selber oder andere Personen täglich arbeiten. Das Setup-Paket für die Clients darf natürlich ebenfalls auch nicht einfach so an die Anwender der Clients verteilt werden, weil eben im Paket Keyfiles für verschiedene Systeme enthalten sind. |
Dieses Paket so zu verwenden ist nur dann ein gangbarer Weg, wenn ausschließlich eine einzelne Person (der Admin) dieses Paket zur Installation auf allen Geräten verwendet, z.B. von einem USB-Stick. Muss das Paket auf ein Gerät kopiert werden, so muss es nach Ende der Arbeiten natürlich auch wieder gelöscht werden… und folgerichtig natürlich auch aus dem Papierkorb, um jeglichen Missbrauch zu verhindern.
Wie zuvor bei OpenVPN beschreite ich auch für die Erstellung der Zertifikate und Keyfiles einen eigenen Weg. Üblicherweise werden diese Dateien mit dem Paket easy-rsa erstellt, was mir aber -wie schon bei OpenVPN- im Debian-Repository nicht aktuell genug ist. Aus diesem Grund lade ich die aktuelle Version direkt von der Projektseite herunter. Der Suchbegriff "download easy-rsa" in der Suchmaschine meines Browsers führt mich sofort im ersten Ergebnis auf die passende Seite "Releases" bei GitHub, wo ich problemlos das jetzt aktuelle Release EasyRSA-*.tgz finde. Das ist die Version, welche ich auch hier in diesem Artikel verwende. Auch diesen Download muss man nicht aufbewahren, man kann ihn jederzeit aktuell neu laden, ich speichere die Datei also einfach über den Browser ebenfalls in /tmp. Alternativ kann die Datei auch direkt im Zielverzeichnis heruntergeladen werden. Das Paket easy-rsa ist selber eigentlich kein Programm im üblichen Sinne, sondern eher eine Sammlung von Script-Befehlen.
# cd /tmp
# wget -c https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.0/EasyRSA-3.1.0.tgz
# tar -xf /tmp/EasyRSA-3.1.0.tgz
Da es sich hier um die Herstellung einer Certificate Authority handelt, die auf einer vertrauenswürdigen Key-Signing-Machine eingerichtet bzw. vorbereitet wird, halte ich es für angemessen, wenn diese Aktivitäten außerhalb dessen stattfindet, worauf anschließend mit normalen User-Berechtigungen zugegriffen werden kann. Die Einrichtung in tmpfs-->/tmp sorgt dafür, dass nach dem Ausschalten des Rechners nichts mehr davon vorhanden ist.
Nun sind noch einige kleinere Vorbereitungen zum Erstellen unserer eigenen Certificate Authority vornzunehmen:
# cd /tmp/EasyRSA-3.1.0
# mv /tmp/OpenVPN/easy-rsa/create-ca3 create-ca3
# mv /tmp/OpenVPN/easy-rsa/vars vars
# mv vars.example vars.example.sik
# chown -R root:root /tmp/EasyRSA-3.1.0
# chmod 755 /tmp/EasyRSA-3.1.0/create-ca3
Wenn alles richtig gemacht wurde, enthält das Verzeichnis nun u.a. die folgenden Dateien und 1 Verzeichnis:
# ls -lah /tmp/EasyRSA-3.1.0
drwxrwxr-x 2 root root 140 2018-01-21 16:37 x509-types
-rwxr-xr-x 1 root root 6,4K 2018-09-11 19:26 create-ca3
-rwxrwxr-x 1 root root 36K 2018-01-21 16:37 easyrsa
-rw-rw-r-- 1 root root 4,5K 2018-01-21 16:37 openssl-easyrsa.cnf
-rw-rw-r-- 1 root root 789 2018-09-11 17:32 vars.example.sik
-rw-rw-r-- 1 root root 727 2022-08-25 15:32 vars
Der vermutlich übliche Weg mit EasyRSA zur Erstellung von Keys und Certs ist es, zuerst ein paar Befehle einzeln zu starten und dabei jedes mal die im Dialog gestellten Fragen zu beantworten. Ein paar dieser Befehle dienen der einmaligen grundsätzlichen Vorbereitung, andere Befehle müssen danach dann wiederholt für jedes VPN-System erneut aufgerufen werden. Ich beschreibe das hier nur in aller Kürze, weil mir das eigentlich zu kompliziert ist und weil ich das beim jährlichen Wechsel meiner CA-Files immer nur 'mit wieder erneuten Einlesen in meine How-To-Dokumentation' hinkriegen würde. Mein Script erspart mir diese Arbeit. Das hier wären die notwendigen Befehle, wenn man es Schritt für Schritt durchführt:
./easyrsa init-pki | Sollte durchgeführt werden, wenn ein komplett neuer Satz von Certs und Keys erzeugt werden soll. Der Befehl erzeugt eine neue und leere pki-Verzeichnisstruktur. Bei Wiederaufnahme eines bestehenden Verzeichnisses (z.B. Ergänzungen) muss der Punkt mit Skip übersprungen werden. |
./easyrsa build-ca nopass | Key-Signing-Zertifikat und -Key ... die Grundlage aller Client-Zertifikate und Keys. Mit anderen Worten, ca.key ist die wichtigste Datei überhaupt, die unbedingt geheim zu halten ist und am besten separat aufbewahrt wird. |
./easyrsa gen-req $host nopass ./easyrsa sign-req server $host | Erstellt Zertifikat und Keyfile für den Server, hier natürlich ohne Password. Mit Password wäre einigermaßen ungeschickt,weil dann in der Bootphase ein Password abgefragt wird... nur leider sieht man die Abfrage nicht, weil Systemd alle Ausgaben "einsammelt". |
./easyrsa gen-req $host ./easyrsa gen-req $host [nopass] ./easyrsa sign-req client $host | Wird für jeden Client separat durchgeführt und erstellt individuelle CA-Files, meine Androids mit Password, die Debian-Clients ohne. |
./easyrsa gen-crl | Eine am Anfang leere Revoke-Liste, um herausgegebene Client-Keys nachträglich zu sperren, z.B. bei Diebstahl eines Gerätes. |
openssl dhparam -out dh4096.pem 4096 | Diffie-Hellman-Parameters. Die Datei dient dazu, einen kryptografischen Schlüssel über potentiell unsichere Kanäle auszuhandeln. DH ist im Betrieb sicher langsamer als RSA2048, aber eben auch deutlich performanter beim Aushandeln periodischer Schlüssel. Und letztlich dient es hier nur dazu, eine sichere Authentifizierung zu gewährleisten und nicht dazu, den Normalbetrieb zu verschlüsseln. Das Pem-File sollte unbedingt erstellt werden, weil ansonsten die im Programm vorhandenen 'hard-coded parameter' verwendet werden, was möglicherweise eine 'Logjam Attack' begünstigt. |
openvpn --genkey --secret ta.key | Die HMAC-Firewall, weitere Erläuterungen siehe weiter unterhalb. |
Man kann das also durchaus auch auf diesem manuellen Step-by-Step-Weg machen, nur ist mir das echt zu kompliziert und einfach zu aufwendig. Ich verwende dafür ein Helper-Script und vordefinierte Parameter, die statt der Defaults exportiert werden. Somit kann ich mich mit der Enter-Taste einfach geradlinig durch die Erstellung durchbewegen, was mich dann im Nebeneffekt auch noch erfolgreich vor Tippfehlern und meinen Leichtsinns- oder Unaufmerksamkeitsfehlern bewahrt.
Das Paket EasyRSA enthält seit jeher eine interessante Besonderheit, und zwar können wir individuellen Einfluss auf die neue Certificate Authority durch von uns vordefinierte Parameter nehmen. In gewisser Weise könnte man das auch mit einer Programm-Conf mit fest eingestellten Werten vergleichen - die Vorgehensweise ist zwar etwas anders, aber der Effekt ist für uns der gleiche. Wenn man nicht nur ein einziges mal eine CA erzeugt, sondern vielleicht regelmäßig (ich tu's jährlich), bekommt man damit bei den Wiederholungen die Garantie, dass gewisse Grundparameter immer gleich bleiben. Diese Möglichkeit ist mit der im easy-rsa-tgz-Archiv vorhandenen Datei 'vars.example' für uns als Beispiel abgebildet. Mit einer eigenen Datei 'vars' können wir nun eigene Vorgabewerte setzen. Das Script und meine geänderte vars sind selbstverständlich im Tarfile-Archiv enthalten.
Ich unterscheide in meiner vars zwei Sektionen. Der obere Teil enthält Parameter für die Kryptografie und die Gültigkeitsdauer meiner Zertifikate. Im Original ist die Gültigkeit mit 3650 Tagen auf 10 Jahre festgelegt, ich stelle es bei mir auf 365 Tage = 1 Jahr ein. Die hier vorgegebene Key-Size 4096 bietet derzeit eine hohe Sicherheit, aber man kann das natürlich ändern. Und wenn jemand denkt, SHA256 ist nicht ausreichend, kann er das auch ändern, wobei ich jedoch von einer Änderung abrate ... siehe Hinweise. Das alles muss aber jeder für sich selber entscheiden. Für meine Anforderungen sind die unten eingesetzten Parameter passend.
In der zweiten Sektion können dem Zertifikat Herausgeber-Informationen mitgegeben werden. In der früheren easy-rsa-Version hatte ich das immer noch gemacht, jetzt in der aktuellen nicht mehr. Der Aufwand beim Erstellen ist im Vergleich zu ohne um einiges höher, weil diese Parameter jedes mal einzeln bestätigt werden müssen. Es handelt sich aber doch nur um allein von uns selbst verwendete Zertifikate, da sind keine fremden Anwender, die das auch nutzen können sollen. Welchen Mehrwert hat es also, wenn Name, EMail, Wohnort, usw. im Zertifikat stehen, wenn das sowieso niemand liest. Ich habe mich deshalb für den einfachen Weg entschieden und mit der Einstellung set_var EASYRSA_DN "cn_only" nur den Common-Name zu verwenden, der einmalig abgefragt wird. Dafür wird im Dialog bei der entsprechenden Frage einmalig der Herausgeber eingetragen und fertig ist's damit:
Common Name (eg: your user, host, or server name) [Easy-RSA CA]: TomL
Meine "vars" nutzt also nur einen Teil der folgenden für mich/uns möglichen individualisierten Parameter, die während der Erstellung der Files exportiert werden, um damit die Defaults zu ersetzen. Als erstes wird bestimmt, dass auf dem Control-Channel Elliptic Curve Cryptography als Algorithmus für den asymmetrischen Schlüssel verwendet werden soll, worüber dann eine entsprechende best-möglich geeignete Cipher-Suite maschinell ausgewählt wird. Soll das Zertifikat über die notwendigen Paramenter auch die umfassenderen Herausgeber-Infos enthalten, muss EASYRSA_DN "org" gesetzt sein. Weiterhin müssen die rot markierten Werte entsprechend den eigenen Gegebenheiten angepasst werden. Und schließlich sind natürlich bei den betroffenen Zeilen auch noch die Comment-Tags '#' zu entfernen. damit diese Zeilen überhaupt beachtet werden.
/tmp/EasyRSA-3.1.0/vars
# Algorithmus? "ec" or "rsa"
set_var EASYRSA_ALGO ec
set_var EASYRSA_KEY_SIZE 4096
set_var EASYRSA_CRL_DAYS 365
set_var EASYRSA_CA_EXPIRE 365
set_var EASYRSA_CERT_EXPIRE 365
set_var EASYRSA_DIGEST sha256
# Certificate-Properties:
# Use a Common-Name-Value requested in dialog? "cn_only"
# Use the "traditional" Country/Province/City/Org/OU/email/CN format? "org"
set_var EASYRSA_DN "cn_only"
set_var EASYRSA_REQ_CN ""
set_var EASYRSA_REQ_COUNTRY ""
set_var EASYRSA_REQ_PROVINCE ""
set_var EASYRSA_REQ_CITY ""
set_var EASYRSA_REQ_ORG ""
set_var EASYRSA_REQ_OU ""
set_var EASYRSA_REQ_EMAIL ""
Mit der Vorgabe "org" könnten die Werte wie folgt gesetzt werden, um traditionelle Parameter-Werte einzufügen:
set_var EASYRSA_DN "org"
set_var EASYRSA_REQ_CN "toml.de"
set_var EASYRSA_REQ_COUNTRY "DE"
set_var EASYRSA_REQ_PROVINCE "NRW"
set_var EASYRSA_REQ_CITY "Zuhause"
set_var EASYRSA_REQ_ORG "toml"
set_var EASYRSA_REQ_EMAIL "thomas@toml.de"
set_var EASYRSA_REQ_OU "private"
Und auch im Script sind einige Parameter unbedingt an die eigenen Gegebenheiten anzupassen. Wegen des Zugangs zu unserer Card/Cal-Dav-Synchronisation mit den Android-Geräten und auch zum Mailserver erzeuge ich immer für mehrere VPN-Clients Zertifikate. Die Bezeichnungen dieser Clients habe ich hier willkürlich vorgenommen. Wichtig ist für mich nur, dass die tatsächlichen Namen beim jährlichen Wechsel von Cert + Key unverändert bleiben, weil eben genau darauf durch die Conf-Files Bezug genommen wird. Auf unseren Debian-Systemen sind die jeweiligen namentlich benannten Files schließlich via SymLink mit der OpenVPN.conf 'verbunden'. Das macht den Austausch dann ganz einfach.... alte Cert+Key mit neuen überschreiben und fertig. Für die Androids ist das irrelevant, da sie dort sowieso einzeln importiert werden müssen.
Eine weitere Besonderheit sind die drei Ergänzungen: {srv}, {pwd} und {p12}. In der Liste der verwendeten Hosts muss natürlich der Server von den Clients unterschieden werden, dazu dient der Eintrag {srv}. Weil ich insbesondere Android-Geräte beim Zugang ins Internet grundsätzlich für 'exponiert' erachte und deren Sicherheit systemimmanent als kritisch einzuschätzen ist, verlange ich für diese Geräte vor der Verbindung nach Hause ein Password für das Zertifikat. Wer das Password nicht kennt, kann sich nicht verbinden. Bei den Linux-Clients verzichte ich darauf, weil Debian eben nicht Android ist. Ums kurz zu sagen, die beiden Einschübe {srv} und {pwd} steuern die Erstellung der Zertfikate oder nehmen Einfluss darauf. Mit dem Eintrag {p12} wird ein Paket-Archiv mit Cert, Key und root-Cert erzeugt, welches alternativ zum einzelnen Import der Dateien als Paket in die Keychain eines Android-Smartphones übernommen werden kann.
Zur Erinnerung: alle notwendigen Dateien können mit diesem Archiv herunter geladen werden (was ich anstatt der Verwendung der Texte von der Web-Seite auch unbedingt empfehle): http://www.thlu.de/Public/openvpn.tar
/tmp/EasyRSA-3.1.0/create-ca3
#! /bin/bash #=================================================================================================== # Description : Create Certificate Authority ((CA) Certs & Keyfiles) for OpenVPN) # # Script-Name : create-ca3 # Date : 24.08.2022 # Version : 4.3 # Licence : GNU General Public License 3 # # create-ca is written and tested for Debian (... and with easy-rsa) #===================================================================================================
PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
# VPN-Hosts: fname[ 0]="{srv} server“ fname[ 1]="{pwd} S5" fname[ 2]="{pwd} S8" fname[ 3]="{pwd}{p12} Tab" fname[ 4]="D630"
BOLD="\033[1m" RED="\033[31m" GREEN="\033[32m" YELLOW="\033[33m" LIGHTBLUE="\033[36m" COLRES="\033[0m" INVERSE="\033[7m"
jobs=() keysize=2048
#---------------------------------------------------------------------------------------------------
DoPrepareJobs() { clear for i in "${jobs[@]}"; do echo -e "\n${GREEN}${BOLD}Want to start $i?${COLRES}\n" read -p "Continue? Yes,Skip,Quit? (y/s/q): " CONFIRM
case $CONFIRM in q) echo "Stopped!" exit 1 ;; s) echo $i "skipped!" ;; *) $i echo -e "\n $i ${GREEN}done!${COLRES}\n\n" ;; esac done
return } #===================================================================================================
BuildFilesPerHost() { Hint 3
KeyCN_bak=$KEY_CN clear
for host in "${fname[@]}"; do withpwd=false server=false p12=false
if [[ "$host" =~ "{pwd}" ]]; then host="${host//'{pwd}'/''}" withpwd=true fi if [[ "$host" =~ "{srv}" ]]; then host="${host//'{srv}'/''}" server=true fi if [[ "$host" =~ "{p12}" ]]; then host="${host//'{p12}'/''}" p12=true fi
host="${host#"${host%%[![:space:]]*}"}" host="${host%"${host##*[![:space:]]}"}" export KEY_CN="${KeyCN_bak}_${host}"
clear echo -e "\n\n${GREEN}${BOLD}Want to start build-key for Host '$host' (pwd=$withpwd) (pkcs12=$p12)?\n${COLRES}\n" read -p "Continue? Yes,Skip,Quit? (y/s/q): " CONFIRM
case $CONFIRM in q) echo "Stopped!" exit 1 ;; s) echo "Skipped!" ;; *) if [ $server == true ]; then ./easyrsa gen-req $host nopass ./easyrsa sign-req server $host else if [ $withpwd == true ]; then Hint 2 clear ./easyrsa gen-req $host else ./easyrsa gen-req $host nopass fi ./easyrsa sign-req client $host if [ $p12 == true ]; then Hint 4 openssl pkcs12 -export -in ./pki/issued/$host.crt -inkey ./pki/private/$host.key -certfile ./pki/ca.crt -name $host -out ./pki/private/$host.p12 fi fi
if [ -s "./pki/private/$host.key" ] && [ -s "./pki/issued/$host.crt" ]; then echo -e "\n\nbuild key for Host $host ${GREEN}done!${COLRES}\n" else echo -e "\n\nbuild key for Host $host ${RED}failed!${COLRES}\n" fi
read -p "Press Enter to Continue: " CONFIRM [ "$CONFIRM" = "q" ] && exit 1 ;; esac done } #===================================================================================================
Hint() { local ahelp=()
clear if [ $1 -eq 1 ]; then ahelp=( "${INVERSE} Hinweis! ${COLRES}" " " "Die folgende sich mehrfach wiederholende Abrage mit der Eingabeaufforderung:" " ${LIGHTBLUE}Continue? Yes,Skip,Quit? (y/s/q):${COLRES}" "kann jeweils einfach mit der Enter-Taste zur Fortführung beantwortet werden." " " "Taste 'q' und Enter beendet das Programm" "Taste 's' und Enter überspringt den betreffenden Programmpunkt!" " " "Die meisten weiteren Abfragen können ebenfalls jeweils mit der Enter-Taste" "bestätigt werden. Sofern eine Eingabe ausdrücklich notwendig ist, erfolgt" "vorher ein Hinweis." )
elif [ $1 -eq 2 ]; then ahelp=( "${INVERSE} Hinweis! ${COLRES}" " " "Die Angabe {pwd} im Client-Array verlangt später beim" "Herstellen einer Verbindung durch diesen Client ein Password" "zur Authorisierung der Verwendung des Zertifikats. Bitte jetzt" "bei der Eingabeaufforderung auf dem nächsten Bildschirm:" " " " ${LIGHTBLUE}Enter PEM pass phrase:${COLRES}" " " "das gewünschte Password eingeben! Achtung: Es müssen mindestens" "4 Zeichen eingegeben werden!" )
elif [ $1 -eq 3 ]; then ahelp=( "${INVERSE} Hinweis! ${COLRES}" " " "Die folgende Abfrage für 'Sign' und 'Commit' als Abschlussfrage bei der" "Erstellung der Zertifikate muss bei jedem einzelnen Host explizit mit ${GREEN}${BOLD}'yes'${COLRES} " "als Eingabe beantwortet werden, da sonst kein Zertifikat erstellt wird:" "${LIGHTBLUE}Type the word 'yes' to continue, or any other input to abort.${COLRES}" "${LIGHTBLUE}Confirm request details:"${COLRES} )
elif [ $1 -eq 4 ]; then ahelp=( "${INVERSE} Hinweis! ${COLRES}" " " "Für die Zertifikat-Erstellung wurde der Parameter ${GREEN}${BOLD}{p12}${COLRES} eingetragen, deshalb wird für eine " "Verwendung mit besserer Sicherheit (z.B. auf Android-Geräten) eine zusätzliche pkcs12-Datei als" "Paket-Archiv erzeugt, die anstelle von clt.key, clt.crt und ca.crt in die Benutzer-Zertifikat-DB" "des Android-Geräts übernommen werden kann." " " "Bitte auf die beiden unterhalb folgenden Abfragen zuerst das vergebene Zertifikat-Password" "eingeben, wodurch die Verwendung des Zertifikats für den nächsten Schritt erlaubt wird. Und" "bei der nächsten Abfrage bitte ein weiteres neues Password eigeben, mit dem das Zertifikat" "später aus der pkcs12-Datei in die Keychain des Android-Gerätes exportiert werden darf, um" "sie dann von dort in das OpenVPN-Profil zu importieren." "Wenn man das unbedingt möchte, kann man das gleiche Password sowohl für das Zertfikat als" "auch für den Export in die Keychain verwenden." " " ) fi
echo -e "\n" for i in "${ahelp[@]}"; do echo -e "$i"; done echo -e "\n"
[ $1 -eq 4 ] && return read -p "Press Enter to Continue! " CONFIRM echo -e "\n\n"
[ "$CONFIRM" = "q" ] && exit 1
return } #=================================================================================================== # Main
[ -z "$(which openssl)" ] && echo "Fehler: Kein openssl gefunden!" && exit 1 [ -z "$(which openvpn)" ] && echo "Fehler: Kein openvpn gefunden!" && exit 1 [ -f "vars.example" ] && mv vars.example vars.example.sik
while read line; do [ -n "$line" ] && line=${line%#*} if [ -n "$line" ];then name=$(awk -F ' ' '{ print $2 }' <<< $line) parm=$(awk -F ' ' '{ print $3 }' <<< $line)
case $name in EASYRSA_KEY_SIZE) [ -n "$parm" ] && keysize=$parm;; esac fi done < <(cat "$(dirname $0)/vars"; echo "")
Hint 1
# Pre-Jobs jobs=() jobs[0]="./easyrsa init-pki" jobs[1]="./easyrsa build-ca nopass" DoPrepareJobs
BuildFilesPerHost
# Post-Jobs jobs=() jobs[0]="./easyrsa gen-crl" jobs[1]="openssl dhparam -out dh$keysize.pem $keysize" jobs[2]="openvpn --genkey secret ta.key" DoPrepareJobs
[ -s ./pki/ca.crt ] && mv ./pki/ca.crt ./pki/issued [ -s ta.key ] && mv ta.key ./pki/private [ -s dh${keysize}.pem ] && mv dh${keysize}.pem ./pki/private
#=================================================================================================== #EOF |
Nachdem nun alle benötigten Dateien kopiert sind, wird das Script gestartet:
# cd /tmp/EasyRSA-3.1.0
# ./create-ca3
Die erste Abfrage ist ziemlich wichtig. Die Antwort entscheidet nämlich darüber, ob eine neue pki-Verzeichnisstruktur erstellt oder eine bestehende genutzt wird. Wenn die Antwort mit Enter als "Yes" gegeben wird, wird bei einer Erstinstallation eine neue pki-Struktur angelegt, eine bestehende Struktur würde aber gelöscht werden und mit der neuen leeren überschrieben. Damit können dann für die alte CA keine neuen Clients mehr angelegt werden und auch keine Sperrung für aktive Clients eingerichtet werden. An dieser Stelle muss man also aufpassen. Wenn es sich um eine Erst-Einrichtung handelt, gibt es das pki-Verzeichnis noch nicht, also kann man auch nichts versehentlich falsch machen.
Want to start ./easyrsa init-pki?
Continue? Yes,No,Skip? (y/n/s):
Hier ist es noch interessant zu wissen, dass easy-rsa eigentlich auf jedem PC-System und auf jedem Betriebssystem funktioniert, egal ob das nun Debian (oder eines der Derivate) ist, oder Raspian, oder Windows. Auf Windows-PCs funktioniert natürlich nicht mein Bash-Script, dafür hatte ich früher und vor etlichen Jahren ein ähnliches Batch-File für den gleichen Zweck, aber Windows interessiert mich heute nicht mehr.
Sofern man sich nach dem Start einmal im Script "verhampelt" hat oder ein Fehler ist bei einem bestimmten Client durch Unachtsamkeit passiert ... kein Problem.... einfach ignorieren und weitermachen, als wäre nichts passiert. Es ist kein Problem, das Script ein zweites Mal zu starten und fehlerhafte Clients erneut zu generieren. Das Script wird dazu einfach noch mal gestartet und alle Abfragen, die sich nicht auf den neuen Client beziehen, werden mit Taste "s" (für skip) und Enter übersprungen. Auf gleiche Weise werden auch neue Clients hinzugefügt. Einfach an das Array anhängen und das Script starten, dann durchskippen bis zum neuen Client und fertig, die neu hinzugekommenen Files sind generiert.
Certificate Revocation List (CRL)
Eine Zertifikatsperrliste ist eine Liste, mit der die Ungültigkeit von Zertifikaten festgelegt werden kann, oder anderes ausgedrückt, mit der die Gültigkeit eines Zertifikats widerrufen werden kann. Es ist durchaus möglich, dass wir zu einem späteren Zeitpunkt für ein bestimmtes Client-Gerät den VPN-Zugang sperren möchte (zum Beispiel weil das Gerät gestohlen wurde). Das erfolgt über einen Widerruf der Certificate Authority mithilfe der Revoke-Liste. Das betroffene Client-Gerät, hier im Beispiel mein "GalaxyS3", wird dazu in die Revoke-Liste eingetragen. Danach muss die geänderte Liste auf den OpenVPN-Server übertragen und aktiviert werden. Die folgenden Befehle sind dazu auf der Key-Signing-Machine (mein "Entwickler-PC") mit Verwendung der o.g. PKI-Struktur durchführen.
Vor der Änderung:
# cd /tmp/EasyRSA-3.1.0
# openssl crl -inform PEM -text -in pki/crl.pem
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha512WithRSAEncryption
Issuer: /CN=Easy-RSA CA
Last Update: Sep 17 13:05:33 2018 GMT
Next Update: Dec 16 13:05:33 2018 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:0B:GG:6C:77:34:66:KK::NN:6C:34:43:12:21:89:98:76:67:B5:AB
DirName:/CN=Easy-RSA CA
serial:23:GG:PP:ZZ:32:VV:45:54
No Revoked Certificates.
Zertifikat widerrufen und CRL neu generieren:
# ./easyrsa revoke S3
# ./easyrsa gen-crl
Nach der Änderung:
# openssl crl -inform PEM -text -in pki/crl.pem
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha512WithRSAEncryption
Issuer: /CN=Easy-RSA CA
Last Update: Sep 17 13:11:42 2018 GMT
Next Update: Dec 16 13:11:42 2018 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:0B:GG:6C:77:34:66:KK::NN:6C:34:43:12:21:89:98:76:67:B5:AB
DirName:/CN=Easy-RSA CA
serial:23:GG:PP:ZZ:32:VV:45:54
Revoked Certificates:
Serial Number: DA694678569SDGFHDKGHKGHKK523D8FE
Revocation Date: Sep 17 13:10:49 2018 GMT
Die Befehle:
openssl crl -inform PEM -text -in pki/crl.pem | Zeigt den aktuellen Inhalt der CRL |
./easyrsa revoke S3 | übernimmt das S3 in die Zertifikat-Speerliste |
./easyrsa gen-crl | generiert eine aktulle Sperrliste mit dem Gültigkeitszeitraum in EASYRSA_CRL_DAYS |
Anschließend ist die neue Datei crl.pem natürlich auf den OpenVPN-Server zu transportieren und dort zu aktivieren.
# cp $(speicherort)/crl.pem /etc/openvpn/ssl/
In der server_udp.conf ist die folgende neue Zeile einzutragen, um den OpenVPN-Server darüber zu informieren, dass es eine Revoke-Liste gibt und das er die beachten soll. Wird auch der TCP-Daemon genutzt, muss die gleiche Änderung natürlich auch in dessen TCP-Conf durchgeführt werden. Danach muss der OpenVPN-Daemon neu gestartet werden.
crl-verify /etc/openvpn/ssl/crl.pem
Im oberhalb stehenden Listing habe ich zusätzlich die beiden Datumsfelder markiert, aus denen der Gültigkeitszeitraum dieser CRL abgelesen werden kann. Diese recht kurze 3-monatige Laufzeit ist entstanden, weil ich zuvor in der vars (s.o.) den Ablaufzeitraum der CRL mit EASYRSA_CRL_DAYS 90 auf eben nur diese 90 Tage gesetzt habe. Dabei muss man nun daran denken, dass nach Ablauf der 90 Tage Verbindungsversuche möglicherweise mit dem Fehler "VERIFY ERROR, CRL has expired" abgewiesen werden, selbst wenn der Client ein im Moment noch gültiges Zertifikat verwendet. Denn es könnte ja sein, dass in einer aktuellen CRL genau dieser Client jetzt gesperrt ist. In dem Fall muss die CRL also mit aktueller Gültigkeit neu generiert werden. 'Best Practice' ist es meiner Meinung nach, die CRL solange nicht in der aktuellen Laufzeit-Version zu verwenden, wie man keine Zertifikate widerrufen muss. Und wenn ich einen komplett neuen Satz von Certs und Keys erzeuge, was bei mir einmal jährlich passiert, würde ich den vielleicht vorhandenen älteren Eintrag zunächst auch wieder deaktivieren.
Nachdem nun das Ziel Certificate Authority über die von uns erstellten Zertifikate und Key-Files erreicht ist, fehlt uns an dieser Stelle nur noch ein etwas besseres Verständnis für die HMAC-Firewall. Was ist das denn schon wieder? Ums vorweg zu nehmen, das ist was ziemlich wichtiges. HMAC steht für "Hash Message Authentication Code" und findet bei der Verschlüsselung und Authentifizierung über den TLS-Control-Chanel einer Verbindung seine Anwendung. Die HMAC-Firewall verschlüsselt und signiert die auf dem TLS-Control-Chanel übertragenen Pakete, alle Pakete mit fehlender oder falscher Signatur werden verworfen. Der Hintergrund für die Wichtigkeit dieser Firewall ist einfach erklärt:
Eine Verschlüsselung (also das was OpenVPN tut) bedeutet, die Daten beim Transport vor Ausspähen zu schützen. Das beinhaltet aber nicht, dass damit eine gezielte Manipulation dieser Daten ausgeschlossen ist, also das jemand die Daten auf der Transportstrecke verändert. Mit einer Traffic-Analyse und bei Beachtung von Größe und Timing von Daten-Paketen bestehen für einen Angreifer durchaus gute Chancen, bestimmte Pakete gezielt zu manipulieren, um darüber eine über diesen Link laufende korruptionsgefährdete Anwendung gezielt zu attackieren. Vielleicht weiß der Angreifer nicht einmal, was er verändert hat, aber wir können es jedenfalls nicht feststellten, denn Kryptografie beinhaltet für uns keine Möglichkeit zu erkennen, dass unsere verschlüsselte Daten unerlaubt verändert wurden. Und genau das verhindert die HMAC-Firewall. Sie erlaubt es OpenVPN zu erkennen, dass ein Paket manipuliert wurde, um es dann verwerfen zu können... was ein erneutes Senden des fallengelassenen Paketes nach sich zieht - in der Hoffnung, dass es nun ein intaktes Paket ist. Die HMAC-Firewall ist nach meinem Verständnis eine zusätzliche Schicht über dem bekannten TLS (Transport Layer Security) und garantiert, dass man auf der anderen Seite der Leitung auch wirklich mit dem spricht, von dem man glaubt, dass er das ist. Ums kurz und mal ganz lapidar auszudrücken: Das Teil ist wichtig! :-)
Ich gehe jetzt davon aus, dass auf dem System, auf dem wir bis jetzt alle Vorarbeiten erledigt haben und gerade die Zertifikate mit easy-rsa erzeugt haben, natürlich auch OpenVPN installiert ist und das das folgende Keyfile ta.key bereits erfolgreich erzeugt wurde. Wenn das nicht der Fall ist, weil OpenVPN fehlte, so kann die Datei auch nachträglich manuell erzeugt werden. Dazu müssen aber jetzt OpenVPN und die liblzo2-2 installiert sein. Der folgende Befehl erstellt dann manuell durchgeführt das Keyfile für die HMAC-FW. Aber wie gesagt, wenn das Script fehlerfrei durchgelaufen ist, sollte das Key-File bereits erstellt sein.
# cd /tmp/EasyRSA-3.1.0/pki/ssl
# ls -lah # Achtung: Erstellen abbrechen, wenn die Datei schon enthalten ist
# openvpn --genkey --secret ta.key
Der Hintergrund, warum ich alle Arbeiten in /tmp erledige ist relativ einfach erklärt... ich verlasse mich darauf, dass alle in /tmp vorhandenen Dateien nach dem Ausschalten meines PCs auch wieder unwiederbringlich beseitigt sind. /tmp ist bei mir kein Festplattenspeicher, sondern durch tmpfs quasi als RAM-Disk zu sehen. Das bedeutet, ich muss vor dem Ausschalten des Rechners nur daran denken, nachdem alle Zertifikate und Keys erzeugt sind, unbedingt das Verzeichnis /tmp/easy-rsa/pki zu sichern. Das erledige ich mit der Übernahme der Dateien in ein eigenes Tar-Archiv:
# cd /tmp/EasyRSA-3.1.0
# tar -cvf openvpn-ca-pki.tar pki/
# mv openvpn-ca-pki.tar /home
Das neu erzeugte Tar-Archiv enthält nun alle erstellten Schlüssel für Server und Clients, aber mit der ca.key auch die grundsätzliche Autorisierung, neue Schlüssel für vielleicht neu hinzugekommene Clients zu generieren. Darüber hinaus ist die leere Revoke-Datei enthalten und die dafür notwendige Grundlage, um bei Bedarf zu sperrende Clients in eine neue Revoke-Liste zu übernehmen. Dieses Tar-Archiv sollte keinesfalls auf die Rechner verteilt werden, sondern wirklich sicher vor missbräuchlichem Zugriff aufbewahrt werden. Man kann sie einfach auf eine SD-Card speichern und wegschließen oder mit einem Kryptografie-Tool verschlüsselt auf einem Rechner speichern. Für die zweite Variante muss man natürlich gewährleisten, dass man sich auch noch nach 1 Jahr an das Password erinnert. Man kann sie aber auch einfach sofort unwiederbringlich löschen. Wichtig ist nur eines, Missbrauch zu verhindern. Wenn sie gelöscht ist, ist das im Fall der Fälle auch kein wirkliches Drama, dann muss man eben einmal für alle Systeme neue Keyfiles generieren und die neuen gegen die alten austauschen. Damit sind die alten wertlos und können nicht mehr verwendet werden.
Zwei für den Systemstart des OpenVPN-Servers notwendige Dateien. Die Service-Units sorgen im späteren Normalbetrieb des Servers dafür, dass der oder die OpenVPN-Daemons direkt beim Systemstart auch gestartet werden. Die drei hier verwendeten Service-Units sind bereits im Ordner
# ls /tmp/OpenVPN/etc/systemd/system
insgesamt 12K
-rw-r--r-- 1 thomas thomas 391 2018-10-14 11:20 openvpn.service
-rw-r--r-- 1 thomas thomas 535 2019-08-05 12:11 openvpn@.service
-rw-r--r-- 1 thomas thomas 496 2019-08-20 15:45 set-nftables-vpn.service
enthalten. Bitte beachten, dass der TCP-Daemon zunächst mit einem Comment-Tag # deaktiviert ist. Es ist besser, sich erst mal nur mit dem UDP-Protokoll zu befassen und erst dann, wenn es fehlerfrei läuft, nimmt man auf gleiche Art und Weise wie zuvor den TCP-Daemon in Betrieb. Mit großer Wahrscheinlichkeit reicht es dann aus, einfach die Comment-Tags zu entfernen, die Service-Unit 'openvpn.service' einmal zu stoppen und erneut zu starten. In den Log-Files kann dann nachgesehen werden, ob der Start ohne Fehler durchgelaufen ist.
openvpn.service
[Unit]
Description=thlu:openvpn.service Start OpenVPN-Daemons for TCP and UDP
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/systemctl start openvpn@server_udp.service
#ExecStart=/bin/systemctl start openvpn@server_tcp.service
ExecStop=/bin/systemctl stop openvpn@server_udp.service
#ExecStop=/bin/systemctl stop openvpn@server_tcp.service
[Install]
WantedBy=basic.target
openvpn@.service
[Unit]
Description=thlu:openvpn@%I.service Start OpenVPN-Daemon
[Service]
Type=forking
PIDFile=/var/run/openvpn/%I.pid
ExecStartPre=/bin/mkdir -p /var/run/openvpn
ExecStartPre=/bin/mkdir -p /var/log/openvpn
ExecStartPre=/bin/chmod 770 /var/log/openvpn
ExecStartPre=/bin/chown root:vpnuser /var/log/openvpn
ExecStartPre=/bin/sleep 2
ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%I.pid --status /var/run/openvpn/%I.status 60 --config /etc/openvpn/%I.conf
KillMode=process
[Install]
WantedBy=multi-user.target
Eine Service-Unit mit Paketfilter-Regeln. Ohne diese Regeln könnte zwar ein Tunnel zwischen Client und Server erfolgreich aufgebaut werden, aber das war's dann auch schon. Sicheres Surfen im Internet über den heimischen Router sowie der Zugriff auf Ressourcen des Heimnetzwerks wäre allein mit dem Tunnel nicht möglich. Dafür werden zusätzlich diese Regeln benötigt.
Hinweise:
1. Wenn das Interface gemäß der mit systemd eingeführten 'Predictable Network Interface Names' einen anderen Namen hat, muss eth0 natürlich durch den richtigen Interface-Namen ersetzt werden.
2. In einem reinen IPv4-Netzwerk müssen die 3 IPv6-Einträge in der folgenden Service-Unit mit # einkommentiert werden.
3. Bei einer bereits installierten Desktop-Firewall darf diese Unit zur Vermeidung von Konflikten nicht gestartet werden. Der richtige Weg ist dann, die notwendigen Regeln in der Firewall zu setzen und auf die Unit zu verzichten. Mit den folgenden 3 Befehlen kann kontrolliert werden, ob eine vorhandene Firewall schon Paketfilter-Regeln gesetzt hat:
4. Achtung: Die unterhalb in der Service-Unit stehenden Regeln ermöglichen auf dem Server ausschließlich den Paket-Transport aus dem VPN-Netz in das LAN bzw. zum Standard-Gateway und haben keinerlei schützende oder überwachende Funktionen.... ergänzende Informationen für notwendige Sicherheitseinstellungen von Client und Server mithilfe des Paketfilters siehe Artikel security und Kapitel Netfilter OpenVPN/Mobil-Geräte
# nft list ruleset
# iptables -L -nv
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# ip6tables -L -nv
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Hier in diesem Beispiel oberhalb ist keine Desktop-Firewall installiert, also kann die folgende Unit auch problemlos -ohne Konflikte auslösen zu können- verwendet werden. Die inet-family zur vereinfachten Dual-Stack-Administration für IPv4/IPv6 wird für stateful NAT erst ab Kernel 5.2 unterstützt.
set-nftables-vpn.service
[Unit]
Description=thlu:set-nftables-vpn.service: Setting some netfilter-rules for openvpn-server
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/sbin/nft flush ruleset
ExecStart=/usr/sbin/nft add table ip filter
ExecStart=/usr/sbin/nft add chain ip filter postrouting "{ type nat hook postrouting priority 100; policy accept; counter;}"
ExecStart=/usr/sbin/nft add rule ip filter postrouting oifname eth0 ip saddr 10.0.8.0/23 masquerade
ExecStart=/usr/sbin/nft add table ip6 filter
ExecStart=/usr/sbin/nft add chain ip6 filter postrouting "{ type nat hook postrouting priority 100; policy accept; counter;}"
ExecStart=/usr/sbin/nft add rule ip6 filter postrouting oifname eth0 ip6 saddr fd00:10:0:8::/63 masquerade
[Install]
WantedBy=multi-user.target
ipv4_vpn="10.0.8.0/23" ipv6_vpn="fd00:10:0:8::/63" | Deklaration der durch OpenVPN verwendeten Subnetze |
|
10.0.1.0/24 | 10. 0. 1. 0. 00001010 00000000 00000001 00000000 | Lokales Netzwerk |
10.0.8.0/24 10.0.9.0/24 | 00001010 00000000 00001000 00000000 00001010 00000000 00001001 00000000 | VPN UDP VPN TCP |
10.0.8.0/23 | ^^^^^^^^ ^^^^^^^^ ^^^^^^^ | Deckt beide VPN-Netze ab. |
Nachdem nun alle Zertifikate und Key-Files sowie die zusätzlich benötigten Daten erfolgreich erzeugt wurden, müsse nur noch die Dateien aus den Easy-RSA-Verzeichnissen in die schon bestehende Verzeichnis-Struktur nach /tmp/OpenVPN kopiert werden, um daraus dann unser "Transport- und Setup-Archiv" zu erstellen. Dazu verwende ich natürlich wieder den auch in den anderen Artikeln schon erwähnten Midnight-Commander. Mit dem Midnight Commander wird in der einen Hälfte das Verzeichnis /tmp/EasyRSA-3.1.0/pki geöffnet und in der Hälfte gegenüber das Verzeichnis /tmp/OpenVPN. Dann werden alle Dateien passend zur folgenden Tabelle kopiert.
Nicht vergessen: Die beiden Verzeichnisse (also weder /tmp*/pki noch /tmp/OpenVPN) mit den darin enthaltenen CA-Dateien für Server und mehrere Clients sind überhaupt nicht geeignet, um sie an andere Personen weiterzugeben, damit die selber Ihren Client-PC einrichten. Ich gehe davon aus, dass der CA-Ersteller (hier bin ich das) diese Dateien niemals komplett aus der Hand gibt, sondern selber die heimischen Clients einrichtet und hinterher alle Spuren beseitigt.
Verzeichnis: | bereits enthaltene / zu kopierende Dateien: | |||
/tmp/OpenVPN/etc/openvpn | client_tcp.conf client_udp.conf server_tcp.conf server_udp.conf |
| ||
Server-Setup: /tmp/OpenVPN/etc/systemd/systemd | openvpn.service openvpn@.service set-nftables-vpn.service | |||
Client-Setup: /tmp/OpenVPN/usr/local/bin | vpn.1 vpn.2 | |||
/tmp/OpenVPN/ca_server | server.crt crl.pem dh4096.pem ca.crt ta.key | server.key | - | |
/tmp/OpenVPN/ca_client | S5.crt S8.crt Tab.crt d630.crt ca.crt ta.key | S5.key S8.key Tab.key d630.key |
Tab.p12
|
Alle anderen in der pki-Struktur verbliebenen Dateien, wie *.pem, *.csr, index* und serial* sind für den Betrieb des OpenVPN-Netzwerks nicht notwendig. Man kann sie aufbewahren oder auch einfach löschen... die Entscheidung muss man für sich selber treffen. Es gibt wirklich nur einen einzigen Grund, warum man später noch einmal darauf zugreifen können wollte. Und zwar braucht man das, wenn man einen neuen VPN-Client dem VPN-Netz zufügen will, also wenn nachträglich noch mal ein individuelles neues Zertifikat und ein Schlüssel erzeugt werden sollen. Dann muss aus dem Archiv die alte pki-Struktur zurückkopiert werden. Man trägt den neuen Client ins Script ein, skip't sich durch und verwendet anschließend Cert und Key wie gehabt. Na ja... ich habe das noch nie gebraucht, ich lösche eigentlich immer alles sofort, was nicht direkt verwendet ober benötigt wird. Und ganz nebenbei bemerkt schätze ich es auch als Sicherheits-Feature ein, wenn die Gültigkeit solcher Dateien sowieso nicht diese 10 Jahre besteht, wie aktuell in der vars eingetragen ist. Meine Dateien haben immer nur 1 Jahr Gültigkeit, danach wird sowieso alles neu erstellt.
Abschließend packen wir alle im nun vorsortierten Sammel-Verzeichnis vorhandenen Dateien in ein Tar-File, welches wir dann später irgendwo an vor Fremdzugriff sicherer Stelle aufbewahren sollten. Aber zunächst mal brauchen wir das natürlich noch bei der Installation auf unseren Geräten.
# cd /tmp
# tar -cvf openvpn-setup.tar OpenVPN/
# mv openvpn-setup.tar /home
# ls /home
insgesamt 132K
-rw-r--r-- 1 root root 80K 2019-09-04 16:06 openvpn-ca-pki.tar
-rw-r--r-- 1 root root 50K 2019-09-04 16:31 openvpn-setup.tar
-rw-r--r-- 1 root root 1,3M 2019-09-04 16:34 openvpn-2.5.7_bullseye_amd64.deb
Wenn alles richtig gemacht wurde, finden wir jetzt im Verzeichnis /home diese Einträge:
openvpn-ca-pki.tar | Das Tar-Archiv der originalen Certificate Authority. Dieses Archiv sollte unzugänglich und vor unberechtigtem Zugriff gesichert aufbewahrt werden. |
openvpn-setup.tar | Das Tar-Archiv .... enthält für alle Systeme immer alles, was notwendig ist... wir können beim Setup der einzelnen Systeme nichts vergessen. |
openvpn-2.5.7_bullseye_amd64.deb | Das in Debian installierbare OpenVPN-Deb-Package für 64-Bit-Systeme (... oder auch mehrere, wenn weitere Packages für andere Rechnerarchitekturen erstellt wurden). |
Nach der erfolgreichen Erstellung von allen benötigten Zertifikaten, Schlüsseln und Zertifikatsunterzeichnungsanforderungen müssen wir unbedingt verstehen, dass nur .key-Dateien als wirklich vertrauenswürdig behandelt werden können. Die noch zusätzlich im Verzeichnis bestehenden .csr-Dateien könnten auch über potentiell unsichere Kommunikationswege gesendet werden, wie z.B. Klartext-Emails. Aber das ist nicht unser Problem, wir brauchen das nicht, wir müssen überhaupt keine Dateien versenden, wir installieren einfach die CA-Files direkt auf unsere VPN-Systeme. Deshalb können wir auch diese .csr-Files ignorieren. Wir dürfen nur eines NIEMALS tun, und zwar .key-Dateien über potentiell unsichere Wege zu transportieren, wie z.B. via EMails oder per Whatsapp oder als Facebook-Message, oder über eine Cloud (Google/Microsoft/etc.) oder ganz allgemein durchs Internet. Das ist ein absolutes NoGo! |
|
Jetzt, wo alles wirklich gut vorbereitet ist, ist die abschließende Inbetriebnahme auf den Zielgeräten eine einfache Angelegenheit. Wir kopieren dazu von unserem Entwickler-PC das neu erstellte Tar-Archiv, welches alle notwendigen Dateien enthält, auf unserem künftig als OpenVPN-Server arbeitenden LAN-Server und kopieren aus dem Archiv die relevanten Dateien komfortabel mit dem Midnight Commander und in wenigen Schritten an ihren jeweiligen Zielort. Weil mein Server gleichzeitig auch noch NAS ist, ist das natürlich ganz einfach: Ich kopiere die Files von meinem Debian-PC rauf auf die NAS-Platte und dann von dort dann via SSH-Zugriff lokal auf dem Server angemeldet in dessen Zielverzeichnisse.
Aber falls es keine gemeinsamen Laufwerke gibt, kann man sowohl das Deb-Package als auch das Tar-Archiv mit allen enthaltenen Dateien ganz elegant via SSH kopieren. Bitte beachten, dass ich das hier als user toml tue und nicht als root. Auf meinem Server ist der Login via SSH direkt als root nicht erlaubt. "toml" ist hier der SSH-Anmeldename, der als User sowohl auf meinem PC als auch auf dem Pi (dem Server) existiert.
$ scp "/home/openvpn-setup.tar" "toml@10.0.1.2:/tmp"
$ scp "/home/openvpn-2.5.7_bullseye_amd64.deb" "toml@10.0.1.2:/tmp"
Bevor es nun an die Einrichtung geht, möchte ich noch einen wirklich wichtigen Hinweis geben: Bitte achte IMMER auf Fehlermeldungen, und zwar ausnahmslos bei jedem Befehl, den du an der Tastatur abschickst. Wenn eine Fehlermeldung kommt, bedeutet das nicht, dass Du diesen Schritt erst mal auf Eis legst und mit dem nächsten fortfährst. Das ist FALSCH! Bei einer Fehlermeldung gibt es nur eine einzige Entscheidung ... und die lautet Abbrechen. Der Fehler muss zuerst beseitigt werden. Und erst danach geht es weiter im Programm. Bitte achte unbedingt darauf, das so einzuhalten. |
Der nächste Schritt ist jetzt natürlich der Wechsel zum Server, um dort zuerst die Installation des Programms OpenVPN und danach dann die Inbetriebnahme durchzuführen. Die folgenden Arbeiten werden alle als root durchgeführt. Als erstes wird ein virtueller (völlig unberechtigter) User ohne Password (verhindert eine Anmeldung dieses Users) angelegt, unter dessen UID später die beiden VPN-Daemons laufen, danach wird OpenVPN installiert. Als letztes wird noch geprüft, ob die für OpenVPN notwendigen Abhängigkeiten erfüllt sind…. fehlende Pakete sind zu installieren.
$ ssh 10.0.1.2
$ su -
# adduser vpnuser --no-create-home --gecos "" --disabled-password
# dpkg -l libc6 liblz4-1 liblzo2-2 libpam0g libssl1.1 libsystemd0 iproute2 lsb-base openssl
# apt install $(fehlende)
# cd /tmp
# dpkg -i openvpn-2.5.7_bullseye_amd64.deb
# tar -xf openvpn-setup.tar
In der Datei /etc/sysctl.d/sysctl.conf, mit der Kernel-Parameter gesetzt oder verändert werden können, sind die beiden folgenden Einträge vorzunehmen. Bei einem Dual-Stack-Account beide Einträge, bei einem IPV4-DSL-Vertrag nur der IPv4-Parameter. Das Forwarding zu aktivieren ist notwendig, weil sonst aus dem VPN-Netz kommende Datenpakete u.U. nicht an das Default-Gateway unseres DSL-Routers weitergeleitet werden, womit dann für die Clients die Verbindung ins Internet scheitern würde.
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.accept_ra = 2
Die Änderung der Kernel-Parameter muss aktiviert werden, damit die neuen Einstellungen wirksam sind. Das ist über einen Reboot möglich oder auch mit dem Kernel-Werkzeug sysctl. Der anschließende Befehl zeigt, ob die neuen Werte übernommen wurden. Falls die Schnittstelle nicht eth0 heisst, muss der zweite Befehl natürlich angepasst werden.
# sysctl --system
# sysctl -a | grep "forwarding =\|accept_ra =" | grep eth0 | grep -v mc
Weiter gehts mit den Konfigurationsdateien, Zertifikaten und Key-Files, die in das jeweilige Verzeichnis zu kopieren sind. Bevor wir die jeweils benötigten neuen Dateien erstellen oder kopieren, richten wir natürlich zuerst die notwendigen Verzeichnisse auf dem jeweiligen Zielhost ein:
# mkdir -p /etc/openvpn/keys
Nun werden die aus dem zuvor nach /tmp übertragenen und dort entpackten Tar-Archiv alle Dateien einzeln an ihren jeweiligen Bestimmungsort kopiert. Und bitte nach dem Kopieren immer gewissenhaft die gesetzten Rechte kontrollieren und sie ggf. auch zu korrigieren. Auch dabei unterstützt uns der Midnight Commander, in dem man nach dem Markieren betroffener Dateien (oder Verzeichnisse) mit der Taste F9 im Menü "Datei" je nach Bedarf den Menüpunkt "chmod" oder "chown" auswählt.
Verzeichnis | Rechte | Datei | Rechte |
etc/systemd/system | root:root 755 | openvpn.service openvpn@.service set-nftables-vpn.service | root:root 644 |
/etc/openvpn | root:root 700 | server_udp.conf server_tcp.conf | root:root 600 |
/etc/openvpn/keys | root:root 700 | ca.crt ta.key dh4096.pem server.crt server.key | root:root 600 |
# cd /etc/openvpn/keys
# chown -R root:root /etc/openvpn
# chmod -R 600 /etc/openvpn
# chmod 700 /etc/openvpn
# chmod 700 /etc/openvpn/keys
Löschen der jetzt nicht mehr benötigten Dateien:
# cd /tmp
# rm openvpn-setup.tar
# rm -r OpenVPN
Und ja, ich bin rigoros der Meinung, auch wenn man glaubt, es müsse so sein, dass sich der normale Anwender mal eben eine OpenVPN-Verbindung herstellen darf, das der reguläre Anwender in seiner Login-Session keine Zugriffs-Rechte auf diese Dateien haben sollte. Hat er keine Rechte darauf, können die auch nicht von Angreifern missbräuchlich verwendet werden, um sich Zugang zu diesen wichtigen Dateien zu verschaffen. Die Dateien gehört root, werden von root verwendet und niemand anderes hat darin was zu lesen oder sie gar noch herauszukopieren. Ein Lesezugriff für andere ist für den Betrieb des VPNs nicht notwendig. Bei Bedarf starte ich in einer root-Login-Session auf meinem Laptop das VPN, arbeite mit der Verbindung als normaler User und am Ende schließe ich das VPN wieder in der root-Login-Session. Und garantiert würde ich so etwas nie mit diesem überflüssigen und wirklich gravierenden Sicherheitsrisiko "sudo" tun. .. deswegen beachte ich das auch hier nicht.
Nun wird ein manueller Start vorbereitet, um zu bestätigen, dass der Start des Programms selber keine Fehlermeldungen erzeugt. Dazu benötigen wir 3 gleichzeitig geöffnete Terminalfenster zum Pi, in denen wir uns jeweils via SSH auf dem PI anmelden und dann zu root wechseln. Die Fenster sollte man am besten so anordnen, dass immer alle 3 gleichzeitig zu sehen sind, was ja auf einem normalen PC-Monitor nicht schwer sein sollte. Im ersten lassen wir uns das OpenVPN-upd-log anzeigen:
# mkdir -p /var/log/openvpn
# touch /var/log/openvpn/openvpn_udp.log
# tail -f /var/log/openvpn/openvpn_udp.log
Im zweiten Fenster erfolgt gleich der manuelle Start von OpenVPN als im Vordergrund laufendes Programm. Nur leider, jetzt ganz kurz vor der ersten Inbetriebnahme, habe ich das Problem, dass ich mich nicht mehr erinnern kann, ob das Programm beim Start selber generisch die zwei benötigten Tun-Devices erzeugt oder ob das vom Admin einmalig manuell vorbereitet werden muss. Man kann es einfach mal ohne die zwei folgenden Statements versuchen, und wenn es zu Fehlern führt, werden eben einmalig die beiden Devices eingerichtet. Der dritte Befehl listet zur Kontrolle alle Netzwerk-Devices auf und zeigt deren Status an. Wenn beabsichtigt ist, nur das UDP-Protokoll zu nutzen, ist auch nur tun0 einzurichten. Mit TCP braucht es natürlich beide.
# openvpn --mktun --dev tun0
# openvpn --mktun --dev tun1
# ip a
# openvpn --config /etc/openvpn/server_udp.conf
Im Log-Fenster sollte dann als Reaktion auf den Programmstart die folgende (oder eine sehr ähnliche) Ausgabe angezeigt werden - hier bei mir ohne Fehlermeldungen:
Fri Sep 7 11:21:43 2018 OpenVPN -2.5.7 armv6l-unknown-linux-gnueabihf [SSL (OpenSSL)] .... build Aug 12 2018
Fri Sep 7 11:21:43 2018 library versions: OpenSSL 1.1.0f 25 May 2017, LZO 2.08
Fri Sep 7 11:21:43 2018 Diffie-Hellman initialized with 2048 bit key
Fri Sep 7 11:21:43 2018 Outgoing Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Fri Sep 7 11:21:43 2018 Incoming Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Fri Sep 7 11:21:43 2018 ROUTE_GATEWAY 10.0.1.1/255.255.255.0 IFACE=eth0 HWADDR=k7:ff:gg:za:31:3p
Fri Sep 7 11:21:43 2018 TUN/TAP device tun1 opened
Fri Sep 7 11:21:43 2018 TUN/TAP TX queue length set to 100
Fri Sep 7 11:21:43 2018 do_ifconfig, tt->did_ifconfig_ipv6_setup=1
Fri Sep 7 11:21:43 2018 /sbin/ifconfig tun1 10.0.8.1 pointopoint 10.0.8.2 mtu 1500
Fri Sep 7 11:21:43 2018 /sbin/ifconfig tun1 add fd00:10:0:8::1/64
Fri Sep 7 11:21:43 2018 /sbin/route add -net 10.0.8.0 netmask 255.255.255.0 gw 10.0.8.2
Fri Sep 7 11:21:43 2018 Could not determine IPv4/IPv6 protocol. Using AF_INET
Fri Sep 7 11:21:43 2018 Socket Buffers: R=[163840->163840] S=[163840->163840]
Fri Sep 7 11:21:43 2018 UDPv4 link local (bound): [AF_INET][undef]:55553
Fri Sep 7 11:21:43 2018 UDPv4 link remote: [AF_UNSPEC]
Fri Sep 7 11:21:43 2018 GID set to vpnuser
Fri Sep 7 11:21:43 2018 UID set to vpnuser
Fri Sep 7 11:21:43 2018 MULTI: multi_init called, r=256 v=256
Fri Sep 7 11:21:43 2018 IFCONFIG POOL IPv6: (IPv4) size=62, size_ipv6=65536, netbits=64, base_ipv6=fd00:10:0:8::1000
Fri Sep 7 11:21:43 2018 IFCONFIG POOL: base=10.0.8.4 size=62, ipv6=1
Fri Sep 7 11:21:43 2018 Initialization Sequence Completed
Im dritten Fenster kontrollieren wir, auf welchen Ports durch OpenVPN gelauscht wird. Achtung: Bei mir sind es schon beide Ports, weil ich hier einfach auf mein laufendes Setup zurückgegriffen habe. Es ist aber richtig, wenn bei der Test-Inbetriebnahme jetzt nur UPD angezeigt wird.
# ss -tulpen | grep openvpn
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:55553 *:* users:(("openvpn"))
tcp LISTEN 0 1 *:55554 *:* users:(("openvpn"))
Viel mehr Möglichkeiten haben wir jetzt hier erst mal nicht. Wenn die Terminal-Ausgaben mit denen hier im Artikel übereinstimmen, also keine Fehler angezeigt werden, haben wir bis hierhin alles richtig gemacht. Wir klicken uns nun zurück in das Fenster, in dem wir das Programm im Vordergrund gestartet haben und beenden es mit der Tastenkombination Strg-c. In der Log-Ausgabe-Terminal sehen wir zeitgleich die Reaktion
SIGINT[hard,] received, process exiting
wonach es sicher ist, dass OpenVPN beendet wurde. Danach führen wir den nächsten Test durch und starten OpenVPN über die Service-Unit als regulären Daemon.
# systemctl daemon-reload
# systemctl start set-nftables-vpn.service
# systemctl start openvpn.service
Und auch hier sehen wir sofort wieder die Reaktion in der Log-Ausgabe. Nun schauen wir uns nur noch den Status der Dienste an. Und wenn auch diese Ausgabe übereinstimmt und keine Fehler berichtet, dann hat die Service-Unit "openvpn" die beiden Daemons für die Protokolle TCP und UDP über die jeweils eigene Service-Unit gestartet. Also können wir OpenVPN nun auch für den Systemstart aktivieren:
# systemctl status openvp*.service set-nftables-vpn.service
● openvpn@server_udp.service - thlu:openvpn@server_udp.service Starts a OpenVPN-Daemon
Loaded: loaded (/etc/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
Active: active (running) since Sun 2018-09-09 16:11:06 UTC; 2min 35s ago
Process: 1024 ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/server_udp.pid :::::::>> server_udp.conf
Process: 1021 ExecStartPre=/bin/chown root:vpnuser /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1017 ExecStartPre=/bin/chmod 770 /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1013 ExecStartPre=/bin/mkdir -p /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1010 ExecStartPre=/bin/mkdir -p /var/run/openvpn (code=exited, status=0/SUCCESS)
Main PID:1025 (openvpn)
CGroup: /system.slice/system-openvpn.slice/openvpn@server_udp.service
└─1025 /usr/sbin/openvpn --daemon --writepid /var/run/openvpn/server_udp.pid - :::::::>> server_udp.conf
Sep 09 16:11:05 raspi5 systemd[1]: Starting thlu:openvpn@server_udp.service Starts a OpenVPN-Daemon...
Sep 09 16:11:06 raspi5 systemd[1]: openvpn@server_udp.service: PID file /var/run/openvpn/server_udp.pid not readable (yet?) after start: No such file or directory
Sep 09 16:11:06 raspi5 systemd[1]: Started thlu:openvpn@server_udp.service Starts a OpenVPN-Daemon.
● openvpn@server_tcp.service - thlu:openvpn@server_tcp.service Starts a OpenVPN-Daemon
Loaded: loaded (/etc/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
Active: active (running) since Sun 2018-09-09 16:11:07 UTC; 2min 34s ago
Process: 1049 ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/server_tcp.pid :::::::>> server_udp.conf
Process: 1046 ExecStartPre=/bin/chown root:vpnuser /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1043 ExecStartPre=/bin/chmod 770 /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1040 ExecStartPre=/bin/mkdir -p /var/log/openvpn (code=exited, status=0/SUCCESS)
Process: 1033 ExecStartPre=/bin/mkdir -p /var/run/openvpn (code=exited, status=0/SUCCESS)
Main PID:1050 (openvpn)
CGroup: /system.slice/system-openvpn.slice/openvpn@server_tcp.service
└─1050 /usr/sbin/openvpn --daemon --writepid /var/run/openvpn/server_tcp.pid :::::::>> server_tcp.conf
Sep 09 16:11:06 raspi5 systemd[1]: Starting thlu:openvpn@server_tcp.service Starts a OpenVPN-Daemon...
Sep 09 16:11:07 raspi5 systemd[1]: openvpn@server_tcp.service: PID file /var/run/openvpn/server_tcp.pid not readable (yet?) after start: No such file or directory
Sep 09 16:11:07 raspi5 systemd[1]: Started thlu:openvpn@server_tcp.service Starts a OpenVPN-Daemon.
● openvpn.service - thlu:openvpn.service Starts OpenVPN-Daemon for TCP and UDP
Loaded: loaded (/etc/systemd/system/openvpn.service; disabled; vendor preset: enabled)
Active: active (exited) since Sun 2018-09-09 16:11:07 UTC; 2min 34s ago
Process: 1028 ExecStart=/bin/systemctl start openvpn@server_tcp.service (code=exited, status=0/SUCCESS)
Process: 1009 ExecStart=/bin/systemctl start openvpn@server_udp.service (code=exited, status=0/SUCCESS)
Main PID:1028 (code=exited, status=0/SUCCESS)
Sep 09 16:11:05 raspi5 systemd[1]: Starting thlu:openvpn.service Starts OpenVPN-Daemon for TCP and UDP...
Sep 09 16:11:07 raspi5 systemd[1]: Started thlu:openvpn.service Starts OpenVPN-Daemon for TCP and UDP.
● set-nftables-vpn.service - thlu:set-nftables-vpn .service: Setting some netfilter-rules for openvpn-server
Loaded: loaded (/etc/systemd/system/set-nftables-vpn.service; disabled; vendor preset: enabled)
Active: active (exited) since Sun 2018-09-09 16:11:07 UTC; 2min 34s ago
Main PID: 154 (code=exited, status=0/SUCCESS)
CGroup: /system.slice/set-nftables-vpn .service
Die Services in den Systemstart einplanen:
# systemctl enable openvpn.service
# systemctl enable set-nftables-vpn.service
Sofern das Verzeichnis /tmp nicht auf tmpfs (also eine RAM-Disk) basiert, löschen wir abschließend noch unser Installations-Tar-Archiv. Wenn /tmp jedoch eine RAM-Disk ist, passiert das Löschen automatisch beim nächsten Shutdown. Aber es schadet auf gar keinen Fall, es jetzt bewusst zu löschen, denn wir brauchen es ja hier nicht mehr... und so können wir es auch nicht vergessen, falls der RPi durchläuft.
# rm /tmp/openvpn-setup.tar
Das war's, mehr ist nicht zu tun. Wir lassen das geöffnete Log-Terminal-Fenster einfach mal laufen und richten nun ein Client-System ein. Optimal ist es, wenn uns dafür ein Smartphone und ein Laptop zur Verfügung steht. Ich verwende jetzt hier als Smartphone mein Galaxy S8, sowie den Laptop mit dem Hostnamen D620 und baue damit diesen nächsten Test auf.
|
Dieser Punkt einer ersten Test-Inbetriebnahme ist eigentlich der interessanteste überhaupt. Hier zeigt sich, ob wir bei diesen vielen Einzelschritten auch wirklich sorgfältig gearbeitet haben.
Hier erweist sich jetzt, ob > die Router-Konfiguration und > die Server-OpenVPN-Konfiguration und > Server-Zertifikate und Keyfiles und > die Server-systemd-Komponenten und > Server-Kernel-Parameter und > die Client-OpenVPN-Konfiguration und > die Client-Zertifikate und Keyfiles am Ende auch wirklich erfolgreich zusammenwirken. |
Das sind ziemlich viele Faktoren, die ziemlich viel Raum für Fehler enthalten. Und wenn dann wirklich was falsch ist, ist die Fehlersuche immer absolut mühsam. Der beste Weg ist also der, von Beginn an sehr sorgfältig zu arbeiten, sich selber immer wieder zu kontrollieren und jeden Schritt ein zweites Mal zu prüfen.
Einige der nun folgenden Arbeiten sind exakt die gleichen, wie zuvor schon beim Server: Zunächst kopieren wir wieder von unserem Entwickler-Rechner das Tar-Archiv zur Installation auf den Laptop. Ich habe jetzt hier willkürlich die IP-Adresse 95 eingetragen, aber welche wirklich die richtige des Laptops ist, muss natürlich zuvor am Laptop oder am DSL-Router nachgesehen werden. Ich kommentiere jetzt aber nicht noch einmal erneut die Befehle, wenn es wirklich die gleichen sind wie zuvor, sondern liste sie einfach nur gruppiert auf:
$ scp "/home/openvpn-setup.tar" "toml@10.0.1.95:/tmp"
$ scp "/home/openvpn-2.5.7_amd64.deb" "toml@10.0.1.95:/tmp"
$ ssh 10.0.1.95
$ su -
# dpkg -l libc6 liblz4-1 liblzo2-2 libpam0g libssl1.1 libsystemd0 iproute2 lsb-base
# apt install $(fehlende)
# cd /tmp
# dpkg -i openvpn-2.5.7_bullseye_amd64.deb
# tar -xf openvpn-setup.tar
Auch hier kann der virtuelle VPN-User angelegt werden, wenn der VPN-Prozess mit eingeschränkten Rechten laufen soll. Achtung: In der aktuellen Client-Conf sind die beiden relevanten Parameter (siehe Server-Conf) derzeit nicht eingetragen.
# adduser vpnuser --no-create-home --gecos "" --disabled-password
Weiter geht's mit dem Kopiervorgang der Konfigurationsdateien aus dem Tar-Archiv, sowie Zertifikat und Key-File, die wie gehabt in die jeweiligen Verzeichnisse zu kopieren sind. Dazu entweder die Zielverzeichnisse wie hier folgend manuell anlegen oder in 2 Schritten mit dem Midnight Commander. Und auch hier bitte hinterher wieder gewissenhaft die gesetzten Rechte kontrollieren und ggf. korrigierien:
# mkdir -p /etc/openvpn/keys
Verzeichnis | Rechte | Datei | Rechte |
/etc/openvpn | root:root 700 | client_udp.conf client_tcp.conf | root:root 600 |
/etc/openvpn/keys | root:root 700 | ca.crt ta.key D620.crt D620.key | root:root 600 |
/etc/systemd/system |
| openvpn@.service | root:root 644 |
/usr/local/bin |
| vpn | root:root 755 |
Hier besteht das gleiche Problem wie beim Server, deshalb der Symlink, der den Eintrag in den Client-Conf's passend auf die tatsächlichen Files verlinkt, um das Problem des Namenskonflikts zu beheben:
# cd /etc/openvpn/keys
# ln -s D620.key client.key
# ln -s D620.crt client.crt
# ls -lah
# chown -R root:root /etc/openvpn
# chmod -R 600 /etc/openvpn
# chmod 700 /etc/openvpn
# chmod 700 /etc/openvpn/keys
Löschen der jetzt nicht mehr benötigten Dateien:
# cd /tmp
# rm openvpn.tar
# rm -r OpenVPN
Sofern wir die letzten Schritte auf unserem Laptop auch via SSH durchgeführt haben, müssen wir uns nun dort abmelden. Der jetzt folgende Test erfordert, dass wir uns tatsächlich auf dem Laptop selber anmelden und den finalen Test an seiner Tastatur und Bildschirm durchführen. Der Hintergrund ist einfach, wir müssen jetzt als erstes die bestehende Verbindung unseres Laptops ins lokale WLAN trennen - und mit getrennter WLAN-Verbindung ist natürlich auch der SSH-Zugang getrennt.
Access-Point via Tethering:
Und wie zuvor wird nun auch hier zuerst ein manueller Start vorbereitet, um sicher zu bestätigen, dass der Start des Programms selber keine Fehlermeldungen erzeugt. Dazu benötigen wir 2 gleichzeitig geöffnete Terminalfenster, in denen wir uns beide Male als root anmelden. Die Fenster werden wieder so angeordnet, dass beide gleichzeitig zu sehen sind. Im ersten lassen wir uns das upd-log anzeigen.
# mkdir -p /var/run/openvpn
# touch /var/run/openvpn/client.log
# tail -f /var/run/openvpn/client.log
Im zweiten Terminal-Fenster erfolgt der manuelle Start von OpenVPN als im Vordergrund laufendes Programm, was dann im Log-Fenster zu folgender Ausgabe führen sollte, hier bei mir wieder ohne Fehlermeldungen:
# openvpn --mktun --dev tun0
# /usr/sbin/openvpn --config /etc/openvpn/client_udp.conf
Eigentlich hatte ich erwartet, dass die Terminal-Ausgabe jetzt dem folgenden Listing entspricht... das hats aber nicht.... im Gegenteil... gar nix ging... nicht mal eine brauchbare Fehlermeldung. Das hat mir dann eine volle Stunde echt unnötiger Arbeit beschert, weil ich wirklich Schritt für Schritt und ziemlich ermüdend jeden einzelnen Eintrag in allen betroffenen Dateien und Verzeichnissen kontrollieren musste. Und natürlich habe ich 2 Flüchtigkeitsfehler gefunden. Die Server-Conf enthielt die beiden folgenden Einträge... original hier aus dem Artikel: push "dhcp-option DNS 10.0.1.1" push "dhcp-option DNS fd00:10:0:1:228d:ff77:fe11:2892" |
Der Fehler ist offensichtlich, denn selbstverständlich müssen auch beim Testen dieser Doku in meinem Netzwerk die IPs meines Routers eingesetzt werden. Mit Phantasie-IPs kann das natürlich nicht funktionieren. Und außerdem enthielt im DSL-Router der Eintrag für die statische Route vom VPN-Netz noch einen Dreher, statt 10.0.8.0 war 10.8.0.0 eingetragen.
Also... was sagt uns das? Alle ... und ja, wirklich alle ... verwendeten IP-Adressen stehen auf die eine oder andere Art in Beziehung zueinander. Wenn an irgendeiner Stelle eine bestimmte Verbindung aufgerissen ist, weil eine fehlerhafte IP nicht zum Gesamten passt... tja... dann fällt möglicherweise alles durch diesen Riss und verschwindet im Nirgendwo.... mit dem Endergebnis, dass es nicht funktioniert. Zwei Dinge sind also für den Erfolg maßgebend:
Sorgfalt (beim Arbeiten) und Wissen (um der Zusammenhänge)
Reaktion bzw. Ausgabe im Log-Fenster, nachdem die Fehler behoben waren:
Tue Sep 11 18:38:10 2018 OpenVPN-2.5.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD] built on Aug 2 2018
Tue Sep 11 18:38:10 2018 library versions: OpenSSL 1.1.0f 25 May 2017, LZO 2.08
Tue Sep 11 18:38:10 2018 Outgoing Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Tue Sep 11 18:38:10 2018 Incoming Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Tue Sep 11 18:38:11 2018 TCP/UDP: Preserving recently used remote address: [AF_INET]555.444.333.666:55553
Tue Sep 11 18:38:11 2018 Socket Buffers: R=[212992->212992] S=[212992->212992]
Tue Sep 11 18:38:11 2018 UDP link local (bound): [AF_INET][undef]:55553
Tue Sep 11 18:38:11 2018 UDP link remote: [AF_INET]555.444.333.666:55553
Tue Sep 11 18:38:11 2018 TLS: Initial packet from [AF_INET]555.444.333.666:55553, sid=b8c0dc84 1f9212fb
Tue Sep 11 18:38:11 2018 VERIFY OK: depth=1, CN=Easy-RSA CA
Tue Sep 11 18:38:11 2018 VERIFY KU OK
Tue Sep 11 18:38:11 2018 Validating certificate extended key usage
Tue Sep 11 18:38:11 2018 ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
Tue Sep 11 18:38:11 2018 VERIFY EKU OK
Tue Sep 11 18:38:11 2018 VERIFY OK: depth=0, CN=server
Tue Sep 11 18:38:11 2018 Control Channel: TLSv1.2, cipher TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384, 2048 bit RSA
Tue Sep 11 18:38:11 2018 [server] Peer Connection Initiated with [AF_INET]555.444.333.666:55553
Tue Sep 11 18:38:12 2018 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1)
Tue Sep 11 18:38:13 2018 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,redirect-gateway ipv6 bypass-dhcp
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: timers and/or timeouts modified
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: --ifconfig/up options modified
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: route options modified
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: peer-id set
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: adjusting link_mtu to 1625
Tue Sep 11 18:38:13 2018 OPTIONS IMPORT: data channel crypto options modified
Tue Sep 11 18:38:13 2018 Data Channel: using negotiated cipher 'AES-256-GCM'
Tue Sep 11 18:38:13 2018 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Tue Sep 11 18:38:13 2018 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Tue Sep 11 18:38:13 2018 ROUTE_GATEWAY 192.168.43.1/255.255.255.0 IFACE=wlp2s0 HWADDR=zz:gg:88:77:66:55
Tue Sep 11 18:38:13 2018 GDG6: remote_host_ipv6=n/a
Tue Sep 11 18:38:13 2018 ROUTE6: default_gateway=UNDEF
Tue Sep 11 18:38:13 2018 TUN/TAP device tun0 opened
Tue Sep 11 18:38:13 2018 TUN/TAP TX queue length set to 100
Tue Sep 11 18:38:13 2018 do_ifconfig, tt->did_ifconfig_ipv6_setup=1
Tue Sep 11 18:38:13 2018 /sbin/ifconfig tun0 10.0.8.6 pointopoint 10.0.8.5 mtu 1500
Tue Sep 11 18:38:13 2018 /sbin/ifconfig tun0 add fd00:10:0:8::1000/64
Tue Sep 11 18:38:13 2018 /sbin/route add -net 555.444.333.666 netmask 255.255.255.255 gw 192.168.43.1
Tue Sep 11 18:38:13 2018 /sbin/route add -net 0.0.0.0 netmask 128.0.0.0 gw 10.0.8.5
Tue Sep 11 18:38:13 2018 /sbin/route add -net 128.0.0.0 netmask 128.0.0.0 gw 10.0.8.5
Tue Sep 11 18:38:13 2018 /sbin/route add -net 10.0.1.0 netmask 255.255.255.0 gw 10.0.8.5
Tue Sep 11 18:38:13 2018 /sbin/route add -net 10.0.8.1 netmask 255.255.255.255 gw 10.0.8.5
Tue Sep 11 18:38:13 2018 add_route_ipv6(fd00:10:0:1::/64 -> fd00:10:0:8::1 metric -1) dev tun0
Tue Sep 11 18:38:13 2018 /sbin/route -A inet6 add fd00:10:0:1::/64 dev tun0
Tue Sep 11 18:38:13 2018 add_route_ipv6(::/3 -> fd00:10:0:8::1 metric -1) dev tun0
Tue Sep 11 18:38:13 2018 /sbin/route -A inet6 add ::/3 dev tun0
Tue Sep 11 18:38:13 2018 add_route_ipv6(2000::/4 -> fd00:10:0:8::1 metric -1) dev tun0
Tue Sep 11 18:38:13 2018 /sbin/route -A inet6 add 2000::/4 dev tun0
Tue Sep 11 18:38:13 2018 add_route_ipv6(3000::/4 -> fd00:10:0:8::1 metric -1) dev tun0
Tue Sep 11 18:38:13 2018 /sbin/route -A inet6 add 3000::/4 dev tun0
Tue Sep 11 18:38:13 2018 add_route_ipv6(fc00::/7 -> fd00:10:0:8::1 metric -1) dev tun0
Tue Sep 11 18:38:13 2018 /sbin/route -A inet6 add fc00::/7 dev tun0
Tue Sep 11 18:38:13 2018 Initialization Sequence Completed
Fehlermeldungen = keine, die beiden folgenden Meldung sind aber noch interessant:
Peer Connection Initiated with [AF_INET]555.444.333.666:55553 Verbindung zum Server ist hergestellt
Initialization Sequence Completed Authentifizierung mit Keyfile und Zertifikat war erfolgreich
Wenn diese Meldungen kommen und es sind keine Fehler unterlaufen, sollte der Tunnel mit daran anschließender Funktionalität erfolgreich etabliert sein. Wenn wir nun wieder im Browser nachschauen und erneut unsere aktuelle IP abfragen, so sollten wir nicht mehr die öffentliche IP des Handy-UMTS-Netzwerks sehen, sondern die öffentlichen IPs unseres heimischen Netzwerkes. Das wars... Projekt geglückt.... es funktioniert... Ziel erreicht.
Die OpenVPN-Verbindung auf meinem Laptop ist nicht etwas, was ich ständig benötige. Ich nutze meinen Laptop ja ganz selbstverständlich auch zu Hause und da brauch ich kein VPN. Also starte ich das VPN auf Reisen auf dem Laptop immer nur manuell bei Bedarf. Entweder über meinen eigenen kleinen Netzwerkmanager selnic, der mich bei der Verbindung mit häufig wechselnden WLAN-Access-Points optimal unterstützt. Oder in Einzelfällen auch über ein kleines Script, was im Terminal gestartet wird. Nur mit dem Aufruf vpn startet es den UDP-Client, mit einem beliebigen Parameter wird TCP gestartet. Ich habe jetzt hier mehrere einfache Alternativen beschrieben, die allesamt OpenVPN starten.
Vier einfache Alternativen, um das VPN auf einem Laptop nur bei Bedarf manuell zu starten:
1. Ein direkter manueller Start im Terminal. Der OpenVPN-Prozess läuft dabei im Vordergrund und kann mit der Tastenkombination strg-c unterbrochen/beendet werden. Wenn das die bevorzugte Methode ist, sollte das log-append-Statement in der betroffenen Client.conf mit # einkommentiert werden... aber auch nur bei dieser Alternative. Die Einkommentierung führt dann dazu, das alle Ausgaben des Programms nach dem Start unmittelbar im Terminal-Fenster angezeigt werden. Diesen Aufruf favorisiere ich z.B. bei der Fehlersuche... aber er funktioniert natürlich auch im täglichen Arbeitsablauf.
# /usr/sbin/openvpn --config /etc/openvpn/client_udp.conf |
2. Führt im Grunde genommen den gleichen manuellen Start im Vordergrund durch, wie unter Pkt. 1. Der wichtige Unterschied ist, dass zusätzlich ein zweites Fenster zur laufenden Anzeige der Log-Einträge geöffnet wird, um jederzeit den aktuellen Status der VPN-Sitzung zu sehen. Das VPN-Sitzung wird wie zuvor mit strg-c unterbrochen/beendet.
# /usr/local/bin/vpn |
|
#!/bin/bash # Script-Name : vpn # Date : 15.01.2017 # Version : 1.0 # Usage : vpn {x}
if [[ $EUID -ne 0 ]]; then echo -e "\nThis script must be run as root" 1>&2 exit 1 fi
mkdir -p /var/run/openvpn TerminalApp=$(which xterm) [ -f /var/run/openvpn/client.log ] || touch /var/run/openvpn/client.log [ -n "$TerminalApp" ] && $TerminalApp -geometry 120x20+1+1 -e "/usr/bin/tail /var/run/openvpn/client.log -n 100 --sleep-interval=2 -f --pid=$$" &
if [ -z "$1" ]; then confnme="/etc/openvpn/client_udp.conf" else confnme="/etc/openvpn/client_tcp.conf" fi
echo -e "\r\nstrg-c beendet die OpenVPN-Sitzung\r\n"
[ -f $confnme ] && openvpn --config "$confnme" || echo "$confnme nicht gefunden!" |
3. Ein direkter manueller Start im Terminal über systemd. Dazu muss natürlich die Service-Unit (s.o.) in das Verzeichnis /etc/systemd/system/openvpn@.service kopiert werden. Der OpenVPN-Prozess läuft als Daemon im Hintergrund. Eine begleitende fortlaufende Log-Ausgabe findet hierbei nicht statt. Diese Start-Methode über systemd verwendet auch mein Script "selnic". Das aktive Fenster könnte nach dem Start sogar geschlossen werden. In dem Fall wird für das Stop-Statement bei Bedarf einfach ein neues Terminal-Fenster geöffnet.
# systemctl start openvpn@client_udp.service # tail -n 20 /var/run/openvpn/client.log # systemctl stop openvpn@client_udp.service |
4. Der Start des OpenVPN-Tunnels erfolgt über ein Script durch systemd, der OpenVPN-Prozess läuft hier wie unter Pkt.3 ebenfalls als Daemon und somit im Hintergrund. Der wichtige Unterschied zu Pkt. 3 ist, dass hier wieder zusätzlich ein zweites Fenster zur laufenden Anzeige der Log-Einträge über tail geöffnet wird, um jederzeit den aktuellen Status der VPN-Sitzung zu sehen. Das Script wartet auf Tastendruck (Enter) und beendet dann den laufenden OpenVPN-Prozess. Das ist meine favorisierte Startmethode.
# /usr/local/bin/vpn |
|
#!/bin/bash # Script-Name : vpn # Date : 15.01.2017 # Version : 1.0 # Usage : vpn {x}
if [[ $EUID -ne 0 ]]; then echo -e "\nThis script must be run as root" 1>&2 exit 1 fi
mkdir -p /var/run/openvpn TerminalApp=$(which xterm) [ -f /var/run/openvpn/client.log ] || touch /var/run/openvpn/client.log [ -n "$TerminalApp" ] && $TerminalApp -geometry 120x20+1+1 -e "/usr/bin/tail /var/run/openvpn/client.log -n 100 --sleep-interval=2 -f --pid=$$" &
if [ -z "$1" ]; then confnme="client_udp" else confnme="client_tcp" fi
if [ ! -f /etc/openvpn/$confnme.conf ]; then echo "/etc/openvpn/$confnme.conf nicht gefunden!" exit 1 fi
systemctl start openvpn@$confnme.service read -p "Enter-Taste beendet die laufende OpenVPN-Sitzung" systemctl stop openvpn@$confnme.service
exit 0 |
An der Stelle bleibt nur noch übrig, einen abschließenden wirklich wichtigen Hinweis zu geben. Öffentliche Access-Points für eine WLAN-Verbindung mit dem eigenen Laptop ohne eine Firewall zu nutzen, erachte ich in jeder Hinsicht als grob fahrlässig. Ich hatte das deshalb hier im Artikel mit dem Stichwort 'Paketfilter' schon mehrfach erwähnt, allerdings ohne jeweils näher darauf einzugehen. In diesem Artikel geht es ja um OpenVPN und nicht um eine Firewall. Das Thema Firewall ist aber mindestens genau so umfangreich, mindestens genau so anspruchsvoll und für den Schutz der eigenen digitalen Privatsphäre nicht weniger wichtig. Deswegen habe ich das in einem eigenen Artikel umfassend beschrieben, der sich nur mit dem Thema Firewall befasst |
|
Für die Installation eines VPN-Clients auf unseren Android-Geräten verwende ich seit vielen Jahren "OpenVPN für Android" von Arne Schwabe, dem Autor des Programms. Gefühlsmäßig möchte ich fast sagen, es müssten bestimmt mittlerweile an die 8 Jahre sein, in denen ich diese App nutze. Heute und auf die lange Zeit zurückblickend hat mich die wirklich großartige Umsetzung und die Stabilität dieser App ohne jeden Zweifel davon überzeugt, dieses Programm mit wirklich gutem Gewissen empfehlen zu können. Hier an der Stelle also auch mein Dank an Arne Schwabe für diese großartige Arbeit.
Ebenso wie für die anderen VPN-Client-Geräte wurde auch für mein Smartphone (Galaxy S8) zuvor auf meinem PC mit Easy-RSA (siehe oben) u. a. diese 4 Files (Zertifikate und Keys) erzeugt: S8.crt, S8.key, ca.crt und ta.key. Der schwierigste Teil in der Installation ist es nun, diese 4 notwendigen Dateien abhörsicher aufs das Handy zu übertragen. Auf gar keinen Fall sollte man sich diese 4 Files via Whatsapp, Telegram, EMail oder auf sonstige Weise irgendwie ungeschützt über das öffentliche Netzwerk an das Smartphone zusenden. Denn darüber muss sich ein jeder im Klaren sein, wer diese 4 Files besitzt und die öffentliche IP oder den DDNS-Namen unseres heimischen Netzwerks kennt, hat vollständigen Zugang in unser privates Netzwerk. Zum Kopieren von Dateien zwischen Smartphone und dem Samba-Server in meinem Netzwerk verwende ich auf den Android-Geräten den Total-Commander und das dazugehörige LAN-Plugin. Auf dem Smartphone wird zuerst eine lokale WLAN-Verbindung hergestellt, dann starte ich den TC und öffne mit dem LAN-Plugin den entsprechenden Samba-Share auf meinem Server und kopiere von dort die Dateien in einen temporären Ordner aufs Smartphone, um sie dann von da in das VPN-Profil zu importieren (siehe Screenshots 4 und 8). Der Total-Commander auf den Androids ist für mich schlichtweg unverzichtbar, ebenso wie der Midnight-Commander auf den Debian-PCs - einfacher und noch schneller geht's wirklich kaum noch, Dateien von hier nach dort zu kopieren oder zu verschieben. Nach dem Import werden die 4 Files umgehend wieder gelöscht!
Zwei ergänzende Hinweise: Wenn zuvor erfolgreich eine Client-Verbindung vom Laptop hergestellt werden konnte, wird die Verbindung vom Smartphone ebenfalls sofort funktionieren. Das bedeutet aber auch, solange ich nicht eine erfolgreiche Verbindung mit dem Laptop herstellen konnte, würde ich mich mit dem Smartphone gar erst nicht befassen. Fakt ist, die Fehlersuche gestaltet sich auf meinem Debian-Laptop gravierend einfacher, als das auf dem Smartphone möglich ist. Zuerst muss es grundsätzlich funktionieren... damit meine ich die Komponenten DDNS-Account, Port-Öffnung, Weiterleitung und Routen im DSL-Router, Authentifizierung am VPN-Server, Paketfilter-Regeln. Klappt das alles mit dem Laptop, klappt es auch sofort mit den Android-Geräten. Hat man allerdings nur das Smartphone zur Verfügung... tja... dann muss man halt probieren und schauen, wie man evtl. auftretenden Fehlern und Problemen auf die Schliche kommt.
Und zweitens erachte ich den wirklich geringen Unterschied zwischen UDP- und TCP-Profil auf dem Android-Gerät für erwähnenswert. Wenn ich mit dem neuen UDP-Profil eine erfolgreiche Verbindung zum Server herstellen konnte, kopiere ich das UDP-Profil einfach mit dem App-GUI, vergebe ihm einen neuen Namen und muss dann nur noch im kopierten Profil die beiden Einträge für Protokoll und Port (siehe Screenshot 5) ändern. Sofern auch auf dem Server der OpenVPN-Daemon für TCP läuft und man hat sich keine Tipp-Fehler eingebaut, klappt auch diese Verbindung eigentlich sofort.
Neues Profil hinzu- fügen | Eingerichtete Profile | Globale Einstellungen OpenVPN | Einstellungen für Profil UDP |
| |
Der Profilname ist frei wählbar. Ich empfehle einen "sprechenden" Namen, mit dem sofort der Zweck des Profils erkennbar ist. | Bei mir gibt es nur 1 VPN-Server und nur diese 2 Profile, also kann ich auch einfachste und natürlich selbsterklärende Namen verwenden. | Unveränderte Default-Einstellungen. | Die zuvor auf meinem PC erstellten und aufs Smartphone kopierten Cert- und Keyfiles werden in das VPN-Profil importiert.
Die Eingabe der Cert-Passphrase ist hier optional. Es ist aber schwierig, das generell zu empfehlen oder abzulehnen. Wurden die Certs ohne PWD erzeugt, wird auch keines abgefragt. Siehe Script! | Als alternative Möglichkeit zur Übernahme der einzelnen Dateien in Bild 4 kann auch das zusätzlich erzeugte Zertifikat-Paket (pkcs12) in den Benutzer-Zertifikat-Speicher des Smartphones importiert werden. Damit wird auf jeden Fall die Zugriffssicherheit verbessert. | Der DDNS-Name meines Netzwerks (DSL-Routers), der zu verwendende Port sowie die Festlegung des Protokolls (entweder UDP oder TCP).
Port und Protokoll sind die einzigen Unterschiede zum TCP-Profil. |
1 | 2 | 3 | 4 | 5 | 6 |
|
|
|
|
|
|
Einstellungen für Profil UDP |
|
|
|
| |
Der Server teilt den Client-PCs alle wichtigen Parameter bzw. Informationen mit.
Einstellungen des lokalen Netzwerkes werden ignoriert. | Legt fest, dass kein Datenverkehr am VPN vorbei in das lokale Netz des Gastgeber-Access-Points erfolgt. | HMAC-Firewall durch den Import des Keyfiles aktivieren.
Verschlüsselungs-parameter setzen.
Achtung: Parameter müssen mit denen in der server.conf übereinstimmen! | Keine Authentifizierungs-Informationen im Speicher belassen.
Siehe auch Bild 10b, wenn 9 keine Option für --auth enthält. | Keine Apps zulassen, die am VPN vorbei ins Internet operieren dürfen. | Protokoll einer erfolgreich hergestellten Verbindung. |
7 | 8 | 9 | 10 | 11 | 12 |
|
|
|
|
Speziell auf die Frage nach 'Best Practice', ob man besser Cert & Key als Files in die App importiert oder ob man besser die Android Keychain verwendet, habe ich leider keine Antwort. Auf der GitHub-Web-Site der OpenVPN-App findet man einen Link zu einer ics-openvpn-FAQ, die unter der Absatz-Überschrift 'Security considerations' sinngemäß erklärt, dass auf die einmal in das VPN-Profil importierten Dateien kein Zugriff durch andere Apps besteht ... zumindest solange das Smartphone nicht gerootet ist. Das werte ich für meinen Anspruch als eine ausreichend gute Erklärung für den Schutz gegen Fremdzugriff anderer Apps auf die Einstellungen.
Da es auf der anderen Seite auf meinem Smartphone keine weitere Berechtigungsabfrage beim Import aus der Keychain in das OpenVPN-Profil gab, vermute ich, dass auch andere Apps die Daten importieren könnten... was ich aber mangels Hintergrundkenntnissen zu Android nicht abschließend weiß. Ich würde vermutlich dann die Keychain wählen, wenn ich Verlust oder Diebstahl des Handys in den Vordergrund stellen würde. Weil ich diese Befürchtung aber nicht hege, vertraue ich auf die fehlenden Lese-Berechtigungen durch andere Apps auf meine VPN-Profile.
Schließlich ausschlaggebend für meine Entscheidung war auch der Umstand, dass das als File importierte Zertifikat die bei der Erstellung eingerichtete Password-Abfrage beibehalten hat. Das aus der Keychain importierte Zertifikat hat dieses Password hingegen nicht mehr verlangt.
|
Nachwort: Immer wieder aufs Neue bin ich über den Umfang eines Artikels erschrocken, wenn er denn irgendwann mal fertig ist. Und immer wieder aufs Neue frage ich mich dann, wie kann man eigentlich die Anforderung "mit Sachverstand und verantwortungsbewusst" für ein solches Projekt erfüllen, wenn man nicht wirklich alle Fakten und Rahmenbedingungen verstanden hat und sich nicht deren Bedeutung und mögliche Auswirkungen auch wirklich bewusst gemacht hat. Ein generisch erzeugtes Netzwerk mit Zugriff über das Internet auf sensible persönliche private Daten oder sogar der Home-Automatisierung ist doch nicht etwas, was man mal eben zwischendurch mit einem 75-Zeilen-HowTo per Copy/Paste auf seinen Rechner bringt und dann denkt "das war ja easy". Was liegt denn da für eine Erwartungshaltung zu Grunde? Da stimmt doch irgendwas nicht. Mir kommt es manchmal so vor, als hätte ein Fahranfänger vor seinem allerersten (!) Einstieg in ein modernes Auto die Erwartungshaltung, es wäre völlig ausreichend, mal eben schnell das kurze Quick-Start-Guide der Bedienungsanleitung dieses Autos zu lesen, um dann im Anschluss von Flensburg nach München fahren zu können. Tja... was soll ich sagen ...?... bin sprachlos ... deshalb ist mein Artikel genau so lang, wie ich glaube, dass er es sein muss, ums auch wirklich zu kapieren.... alle anderen begleitet mein Wunsch, sie mögen heil in München ankommen - selbst wenn sie es dem Zufall überlassen. |
|
Datum | Änderungen |
01.10.2018 | Redaktionelle Korrekturen |
| server.conf alt: comp-lzo (wird ab OpenVPN 2.5 nicht mehr unterstützt) server.conf neu: compress lzo Achtung: Die Kompression enthält unter bestimmten Umständen ein Sicherheitsrisiko, bei dem es dann ratsam ist, die Kompression zu deaktivieren:
|
| adduser-Statement hinzugefügt, um den unberechtigten virtuellen User 'vpnuser' ohne Password anzulegen. |
10.10.2018 | Authentifizierung und Verschlüsselung auf dem TLS-Kontrollkanal umgestellt server.conf alt: (signiert alle Pakete mit einer HMAC-Signatur) tls-auth /etc/openvpn/keys/ta.key 0 server.conf neu: (verschlüsselt zusätzlich alle Pakete (Schlüsselrichtung ist hier unnötig)) tls-crypt /etc/openvpn/keys/ta.key |
| Android-Clients: Bild 8.b an tls-crypt angepasst |
| Diffie-Hellman-Schlüsselaustausch von statischem Keyfile auf Elliptic Curves umgestellt server.conf alt: dh /etc/openvpn/keys/dh.pem server.conf neu: ecdh-curve secp384r1 dh none Ohne Angabe tls-cipher wird die Verwendung der 'höchstwertigen' Cipher präferiert, siehe Log-Eintrag nach einer hergestellten Verbindung: 2018-10-01 18:15:42 Control Channel: TLSv1.2, cipher TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384, 2048 bit RSA |
10.10.2018 | Verbindungen "schlechter" als Version 1.2 werden abgewiesen: tls-version-min 1.2 |
05.08.2019 | - Überprüfung und Anpassung des Setups auf Debian Buster - Das Paket 'checkinstall' zur Erzeugung des deb-Packages für OpenVPN durch die Build-Deb-Package-Funktion des Programms dpkg ersetzt - Installationspfad mit der Begründung „eigenes Deb-Package“ nach /opt/openvpn verlegt - symlink für Openvpn-Binary in /usr/sbin erzeugt |
22.08.2019 | Harmonisierung der in den Beispielen verwendeten IP-Adressen in den Artikeln security, openvpn, cameventctl zur Verbesserung der Zusammenhang-Darstellung. |
06.09.2019 | Redaktionell mit dem Ziel "geradliniger" überarbeitet |
15.11.2019 | OpenVPN-2.4.8 |
| Kapitel "Perfect Forward Secrecy" eingefügt... gehe zu. |
| auth SHA512 auf auth SHA256 geändert... siehe Hinweise. |
| Sicherheit durch Wechsel von tls-version-min 1.2 auf tls-version-min 1.3 verbessert... siehe Hinweise. |
| dh none beim Wechsel auf ECC war eine Fehlentscheidung, siehe Änderungen 10.10.2018 dh.pem-File mit 4096 Bit erzeugt... siehe Hinweise unterhalb server.conf. |
| compress lzo entfernt, da es die Sicherheit wegen charakteristischer Merkmale bei der Komprimierung schwächt |
| iptables-Regeln durch nftables ersetzt |
| create-ca3 erzeugt bei Angabe {p12} im Script (siehe Array Hosts) zusätzlich ein pkcs12-File (Archiv-Format) für den Import von Zertifikat und Key in die Keychain eines Android-Geräts |
| Einige 'Unstimmigkeiten' redaktionell korrigiert |
15.12.2019 | explicit-exit-notify in Client-UDP-Conf eingefügt |
15.04.2020 | Erläuterungen zu remote-cert-tls server eingefügt |
26.12.2021 | OpenVPN-2.5.5 Migration der Installation nach Debian 11 (Bullseye) |
| Fehlermeldung „checking for lz4.h... no usable LZ4 library or header not found“ bei ./configure behoben: Paket liblz4-dev hinzugefügt. |
| Update auf EasyRSA 3.08 |
| In beiden Server-Conf-Files das Statement push "redirect-gateway ipv6 bypass-dhcp" entfernt. Damit Fehlermeldung durch Kollision mit push "redirect-gateway def1 bypass-dhcp" beseitigt. |
26.08.2022 | Update: von Easy-RSA 3.0.8 auf 3.1.0 von OpenVPN 2.5.5 auf 2.5.7 |
| create-ca3: Auf Grund geänderter Openssl-Parameter neu entstandene Warnungen korrigiert. Vorherige Syntax ist jetzt deprecated markiert. |