OpenVPN, von dem Sie so wenig wussten

OpenVPN, wie viel in diesem Wort. Ein plattformübergreifender, hochgradig anpassbarer, kostenloser Open-Source-VPN-Server, der eigentlich der Standard für die Organisation des Zugriffs auf interne Unternehmensnetzwerke ist. Die meisten Administratoren verwenden es mit Standardeinstellungen oder mit typischen Konfigurationen, die in verschiedenen HOW-TOs ausführlich beschrieben werden. Aber ist OpenVPN so einfach, wie es auf den ersten Blick scheint? In diesem Artikel werden wir die internen Mechanismen von OpenVPN betrachten, die vor den Augen verborgen sind und die Vorstellung von seinen Fähigkeiten drastisch verändern.


Der OpenVPN- Server wird in Form von Quellcode oder einbaufertig kompilierten Paketen für verschiedene Betriebssysteme verteilt. OpenSSL wird als Bibliothek zur Verschlüsselung verwendet.


Bei den meisten Konfigurationen zum Verbinden von Clients mit dem Server sowie zwischen Servern werden mehrere private oder private / öffentliche Schlüssel verwendet, um die Sicherheit des internen Datenverkehrs zu gewährleisten. Für Unternehmensnetzwerke im MultiPoint-To-SinglePoint-Modus wird normalerweise ein eigenes PKI-Zertifizierungscenter verwendet, das mit easy-rsa oder XCA- basiert einfach aufgebaut werden kann . Für die Punkt-zu-Punkt-Kommunikation zwischen Servern wird hauptsächlich eine Konfiguration mit gemeinsamem Schlüssel verwendet. Erinnern Sie sich an die grundlegenden, bekannten Mechanismen und Fähigkeiten.


Schlüsselmechanismen und -fähigkeiten


  • Zertifikatauthentifizierung


    Es wurde eine große Menge an Dokumentation darüber geschrieben. Der Punkt ist einfach. Es wird eine Zertifizierungsstelle erstellt, die Benutzerzertifikate ausstellt. Mit Hilfe einer Zertifizierungsstelle wird eine Steuerung bereitgestellt, um Benutzer mit dem OpenVPN-Server zu verbinden. Wenn das Zertifikat abläuft oder widerrufen wird, wird der Benutzerzugriff blockiert. Private Schlüssel mit einem Kennwort, die in Verbindung mit dem Zertifikat ausgestellt wurden, bieten Sicherheit gegen nicht autorisierte Verbindungen zu internen Ressourcen.


  • Private Punkt-zu-Punkt-Schlüssel


    Um nur einen Benutzer / Server mit Unternehmensressourcen zu verbinden, wird ein Schema mit privaten Schlüsseln verwendet. Auf einem der Hosts wird ein Schlüssel generiert, der vom Server und vom Client gemeinsam genutzt wird.



In allen Fällen der Verbindung zur Sicherheit des "Handshake" -Handshakes zwischen dem Client und dem Server wird das Diffie-Hellmann-Protokoll verwendet.


  • Externe Benutzerauthentifizierung


    Um die Kontrolle über Benutzerverbindungen zu vereinfachen, können Sie anstelle eines Schemas mit eigener PKI ein Schema mit externer Benutzerauthentifizierung durch Login / Passwort verwenden . Dieses Schema ist praktisch, um Benutzer beispielsweise durch ein Domain-Login / Passwort zu authentifizieren. Um eine Verbindung zum Server herzustellen , werden das Serverzertifikat und der Paketsignaturschlüssel HARDENING OPENVPN SECURITY zur Clientkonfigurationsdatei hinzugefügt.
    Beispiel für eine Client-Konfiguration


    dev tun proto udp #  IP  OpenVPN remote 172.16.111.166 # Port  port 1200 client resolv-retry infinite tls-client key-direction 1 auth SHA1 cipher BF-CBC #comp-lzo persist-key persist-tun # auth-user-pass c:/temp/pass.txt # # just create a file with name pass.txt # and put to it two lines # ------------- #username #password # ------------- #auth-user-pass verb 3 <ca> -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIJAOt3kFH7PxA0MA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD .... -----END CERTIFICATE----- </ca> <tls-auth> -----BEGIN OpenVPN Static key V1----- 83ddd29fa82212f3059d85a41490134c .... a4f2c7df3a22364a49093bca102dedeb -----END OpenVPN Static key V1----- </tls-auth> 

    Teil der Serverkonfiguration für die Clientauthentifizierung per Datei
    Verwenden alternativer Authentifizierungsmethoden


     verify-client-cert none #client-cert-not-required username-as-common-name tls-server tls-auth /usr/local/etc/openvpn/ssl/tlsauth.key key-direction 0 tls-timeout 120 auth SHA1 cipher BF-CBC auth-user-pass-verify /usr/local/etc/openvpn/auth/auth-static-file.pl via-file 

    Dieses Schema ist praktisch, aber sehr unsicher.


  • PAM


    Um die Sicherheit zu erhöhen, können Sie Plug-Ins verwenden, die die Anmeldung / Kennwortüberprüfung in externen Systemen ermöglichen. Die gebräuchlichste Methode ist System PAM (Pluggable Authentication Modules).
    Fügen Sie die Zeile zur OpenVPN-Konfigurationsdatei hinzu


     plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login 

  • Routing


    Weil Die Hauptaufgabe des Servers besteht darin, Remotebenutzern / Servern Zugriff auf interne Ressourcen zu gewähren. Auf dem Server können Sie das statische Routing von Clients zum Server und von Server zu Clients bestimmen. Unter dem Gesichtspunkt des Clientzugriffs auf interne Ressourcen können Sie mit dem Server, der DHCP und die Anweisungen "route" oder "push route" verwendet, interne Netzwerkrouten an den Client übertragen. Um den Server selbst über Remotenetzwerke auf der Clientseite zu benachrichtigen, wird "client config dir" (ccd) verwendet, ein Mechanismus, mit dem mithilfe der Direktive "iroute" die Liste der internen Clientnetzwerke beschrieben werden kann, die sich in der Server-Routing-Tabelle befinden müssen, um den Datenverkehr zu ihnen zu übertragen.



Auf dieser "regulären" weit verbreiteten Funktion endet und die lokale Anpassung für jeden speziellen Fall beginnt.


Zusätzliche OpenVPN-Funktionen


Betrachten Sie die zusätzlichen Funktionen von OpenVPN, von denen möglicherweise jemand gehört hat, die er jedoch in Wirklichkeit nicht gesehen oder verwendet hat.


  • Netzwerksicherheit / Paketfilterung


    Weil OpenVPN leitet den Verkehr weiter und verfügt über zwei reguläre, sich gegenseitig ausschließende Betriebsmodi. Der erste Modus ist das Routing innerhalb des OpenVPN-Servers, der zweite Modus ist das Inter-Interface-Nuclear-Routing. Im ersten Fall ist OpenVPN für das Umschalten und Filtern von Paketen zwischen Clients / Netzwerken verantwortlich, im zweiten Fall für alle auf dem Host unterstützten Systempaketfilter (pf, iptables usw.).
    Nur wenige Menschen wissen, dass OpenVPN über einen integrierten Paketfilter verfügt, mit dem Sie Verbindungen zwischen Benutzern und Netzwerken zulassen oder isolieren können.
    Ja Ja. Du hast es richtig gelesen. OpenVPN verfügt über einen eigenen integrierten Paketfilter. Die Möglichkeit, Datenverkehr zu filtern, wurde bereits 2010 implementiert .
    Der OpenVPN-Paketfilter wird entweder über die Verwaltungsschnittstelle oder über mit OpenVPN verbundene Plug-Ins gesteuert.
    Verkehrsregeln werden über eine Datei verwaltet. Das Dateiformat ist einfach.


     [CLIENTS DROP|ACCEPT] {+|-}common_name1 {+|-}common_name2 . . . [SUBNETS DROP|ACCEPT] {+|-}subnet1 {+|-}subnet2 . . . [END] 

    Blockanweisungen (ACCEPT / DENY) legen die Standardaktion für alle Clients fest, die nicht im Block angegeben sind.
    Zum Beispiel Datei für Client-Benutzer2


     [CLIENTS DROP] +user1 [SUBNETS DROP] [END] 

    blockiert den Datenverkehr für alle Benutzer und Netzwerke, lässt jedoch den Datenverkehr für die Client1-Seite zu. Wenn Benutzer1 die Berechtigung zum Übertragen von Datenverkehr an Benutzer2 nicht explizit beschreibt, wird der Datenverkehr nur in eine Richtung geleitet. Benutzer2-> Benutzer1.



Oder ein anderes Beispiel.
Deaktivieren Sie alles außer dem Zugriff zwischen Benutzern und dem DNS-Server im lokalen Netzwerk und der Testschaltung im Netzwerk 192.168.0.0/24


 [CLIENTS DROP] +user1 +user2 [SUBNETS DROP] +10.150.0.1 +10.150.1.1 +192.168.0.0/24 [END] 

Der Filtermechanismus wird über die Konfigurationsdatei oder beim Anschließen des Plugins aktiviert, das das Flag "OPENVPN_PLUGIN_ENABLE_PF" "setzt".
Wir werden diese Gelegenheit später besprechen.
Der zweite Modus der Verkehrsfilterung ist der im System integrierte Paketfilter. Um es zu aktivieren, sollte die Konfiguration keine "Client-zu-Client" -Anweisung haben. Unter dem Gesichtspunkt der Automatisierung des Ein- und Ausschaltens der erforderlichen Regeln beim Verbinden / Trennen von Clients ist es am bequemsten, separate Einfügungen in die Liste der Regeln zu verwenden, die entweder über CHAINS in Iptables (Linux) oder in Anchors in PF (FreeBSD) implementiert werden. Die Aktivierung / Deaktivierung von Regeln erfolgt normalerweise über die Anweisungen client-connect / client-separect in der Serverkonfigurationsdatei, die die entsprechenden Skripts aufrufen, wenn der Benutzer eine Verbindung herstellt / trennt.


  • Erweiterte PAM-Authentifizierung


    Erweiterte PAM-Authentifizierung bedeutet, die Logik der Benutzeranmeldung und der Kennwortüberprüfung zu ändern. Dies wird entweder durch die Installation der entsprechenden Plug-Ins für OpenVPN erreicht, die das Lesen und Überprüfen von Daten in externen Quellen ermöglichen, oder durch das Verbinden von Bibliotheken mit dem System, mit denen Logikskripte erstellt werden können. Eine dieser Bibliotheken ist pam_python , mit dessen Hilfe jede Anmelde- / Kennwortüberprüfungslogik über Python-Skripte geschrieben werden kann.
    Wenn es verwendet wird, ändert sich die Benutzerüberprüfungszeichenfolge wie folgt.


     plugin openvpn-plugin-auth-pam.so pam_python login USERNAME password PASSWORD domain mydomain.com 

    Da "unter der Haube" von PAM die Dialogalgorithmen des Systems mit dem Benutzer oder externen Bibliotheken sind, können diese Dialoge gesteuert werden. Verbinden Sie beispielsweise OTP-Token mit dem System . Die LinOTP-Bibliothek dient nur als Beispiel, weil Ich habe meine eigene selbstgeschriebene Bibliothek verloren, als ich irgendwo getestet habe ¯ \ (ツ) / ¯
    Beispiele werden auch leicht mit dem Wort "pam_python" gegoogelt.
    Das Hauptproblem bei der Arbeit mit externen PAM-Modulen ist die Unfähigkeit, die OpenVPN-Sitzungsumgebung innerhalb des aufgerufenen Python oder eines anderen über die System-Pam aufgerufenen Skripts abzurufen. Das heißt, Das Skript bietet nur die Funktionen zum Überprüfen des Logins / Passworts, die ihm zugewiesen sind.


  • Aufgeschobene Authentifizierung


    Der OpenVPN-Server unterstützt die sogenannte "verzögerte" Authentifizierung. Die "verzögerte" Authentifizierung wird in Fällen verwendet, in denen der Authentifizierungsdienst die Anmelde- / Kennwortüberprüfungsanforderung nicht in Echtzeit bearbeiten kann.


  • OpenVPN Plugins


    Dies ist ein separates Paralleluniversum, über das es vielleicht bekannt ist, aber aufgrund einiger Verwirrung sind sie nicht in der Lage oder haben Angst, es zu benutzen. In der Tat erfordert das Schreiben eines funktionalen Plug-Ins für OpenVPN die Programmierung in C mit allem, was dazu gehört. Beispiele für einfache Plugins sind im OpenVPN-Quellbaum enthalten, oder es gibt beispielsweise ein Plugin zum Demonstrieren von Methodenaufrufen von OpenVPN .



Versuchen wir herauszufinden, wie Plugins von OpenVPN aus funktionieren.
Funktionen und Parameter für die Arbeit mit Plugins werden in einer separaten Datei beschrieben
Die Hauptaufgabe des Plugins besteht bei der Initialisierung durch den OpenVPN-Server darin, die Liste der vom Plugin unterstützten Funktionen zu übertragen und beim Aufrufen einer der Funktionen den richtigen Antwortcode zurückzugeben, der dem Server klar ist.


 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 

Lassen Sie uns näher auf jede Gruppe eingehen. Wir werden die Arbeitslogik auf der Grundlage der Passwortauthentifizierung des Benutzers betrachten.
Wenn der Server nach dem Lesen der Konfigurationsdatei gestartet wird, ruft der Server die Funktionen OPENVPN_PLUGIN_UP und OPENVPN_PLUGIN_ROUTE_UP auf. In der variablen Umgebung der aufgerufenen Funktionen werden die Hauptparameter des laufenden Servers übertragen.


 OPENVPN_PLUGIN_UP { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "daemon_log_redirect":"1", "daemon":"1", "route_net_gateway":"172.16.100.1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"0", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

 OPENVPN_PLUGIN_ROUTE_UP { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "daemon_log_redirect":"1", "daemon":"1", "route_net_gateway":"172.16.100.1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"2", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

Diese Funktionen können für Warnungen beim Serverstart oder für Konfigurationsänderungen verwendet werden.
Beim Verbinden eines Clients fordert OpenVPN die Möglichkeit an, einen internen Paketfilter zu aktivieren.


 OPENVPN_PLUGIN_ENABLE_PF { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "daemon":"1", "daemon_log_redirect":"1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"11", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

Wie Sie dem Speicherauszug entnehmen können, wurde die Variable pf_file angezeigt. Diese Datei sollte die Regeln des internen Paketfilters für die aktuell verarbeitete Sitzung enthalten.
Als nächstes werden der Benutzername und das Passwort des Benutzers in der Funktion OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY überprüft


 OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "IV_NCP":"2", "IV_COMP_STUB":"1", "daemon_start_time":"1545994898", "IV_LZ4":"1", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_a3d0650a43b88ca1b5f305ce2c8f682.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"2", "IV_PLAT":"win", "daemon_pid":"626", "password":"12312312312312", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"5", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

Dies ist der einzige Ort, an dem das Kennwort in der variablen Umgebung im Klartext vorhanden ist.
Das Ergebnis dieser Funktion sollten drei mögliche Antworten sein.


 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 

Wenn der Server eine Antwort OPENVPN_PLUGIN_FUNC_DEFERRED erhält, wird der Mechanismus der "verzögerten" Authentifizierung aktiviert. Wie wir sehen, wurde die Variable "auth_control_file" in der Variablenumgebung angezeigt. Der Inhalt dieser Variablen enthält den Namen der Datei, in der eine Antwort vom Authentifizierungssystem erwartet wird. Die Antwort ist das Symbol 0 (um den Zugriff zu ermöglichen), 1 (um den Zugriff zu verweigern) in der angegebenen Datei. Der Serverparameter "Handfenster" bestimmt das Zeitlimit in Sekunden, während dessen der Server auf eine Antwort wartet. Während des Wartens wird der Verkehr von anderen Clients nicht unterbrochen.


Da wir mit der Passwortauthentifizierung arbeiten, wird die Zertifikatsüberprüfungsfunktion OPENVPN_PLUGIN_TLS_VERIFY nicht aufgerufen. Stattdessen wird OPENVPN_PLUGIN_TLS_FINAL sofort aufgerufen, um den Aufbau der Sitzung zu bestätigen.


 OPENVPN_PLUGIN_TLS_FINAL { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "IV_NCP":"2", "IV_COMP_STUB":"1", "daemon_start_time":"1545994898", "IV_LZ4":"1", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_a3d0650a43b88ca1b5f305ce2c8f682.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"2", "IV_PLAT":"win", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"10", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

Als nächstes wird der Aufruf OPENVPN_PLUGIN_IPCHANGE aufgerufen, der aufgerufen wird, bevor die IP-Adresse des Clients geändert wird.


 OPENVPN_PLUGIN_IPCHANGE { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "redirect_gateway":"0", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "ifconfig_remote":"10.150.0.2", "IV_NCP":"2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_321bb12075dc0e1b5440d227220bac5d.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"3", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

Die Funktion OPENVPN_PLUGIN_CLIENT_CONNECT_V2 wird aufgerufen, wenn die IP-Adresse vom internen DHCP-Server festgelegt wird.


 OPENVPN_PLUGIN_CLIENT_CONNECT_V2 { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "dev":"tun150", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "time_ascii":"Sat Jan 12 18:54:48 2019", "ifconfig_remote":"10.150.0.2", "IV_NCP":"2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_321bb12075dc0e1b5440d227220bac5d.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "time_unix":"1547319288", "redirect_gateway":"0", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "ifconfig_pool_local_ip":"10.150.0.5", "pluginid":"9", "ifconfig_pool_remote_ip":"10.150.0.6", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

In einer Variablenumgebung werden Variablen mit den Tunnelparametern "ifconfig_pool_local_ip" und "ifconfig_pool_remote_ip" angezeigt.


Die Funktion OPENVPN_PLUGIN_LEARN_ADDRESS wird aufgerufen, wenn der OpenVPN-Server die Verbindung von IP-Adressen lernt und diese weiterleitet. Nach dem Beenden dieser Funktion wird das Verfahren zum Anwenden der Paketfiltereinstellungen aus der Datei aktiviert. Die Umgebungsvariable OPENVPN_PLUGIN_LEARN_ADDRESS entspricht in diesem Fall der Phase OPENVPN_PLUGIN_CLIENT_CONNECT_V2.


 fa56bf61-.../172.16.111.168:1200 ----- pf_check_reload : struct pf_context ----- fa56bf61-.../172.16.111.168:1200 enabled=1 fa56bf61-.../172.16.111.168:1200 filename='/tmp/openvpn_pf_343330698e4acdea34c8a8c7fb87d861.tmp' fa56bf61-.../172.16.111.168:1200 file_last_mod=1547319124 fa56bf61-.../172.16.111.168:1200 n_check_reload=1 fa56bf61-.../172.16.111.168:1200 reload=[1,15,1547319125] fa56bf61-.../172.16.111.168:1200 ----- struct pf_set ----- fa56bf61-.../172.16.111.168:1200 kill=0 fa56bf61-.../172.16.111.168:1200 ----- struct pf_subnet_set ----- fa56bf61-.../172.16.111.168:1200 default_allow=ACCEPT fa56bf61-.../172.16.111.168:1200 ----- struct pf_cn_set ----- fa56bf61-.../172.16.111.168:1200 default_allow=DROP fa56bf61-.../172.16.111.168:1200 12345678-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 fa56bf61-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 ---------- fa56bf61-.../172.16.111.168:1200 fa56bf61-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 12345678-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 -------------------- 

Wenn ein Client getrennt wird, wird die Funktion OPENVPN_PLUGIN_CLIENT_DISCONNECT aufgerufen.


 OPENVPN_PLUGIN_CLIENT_DISCONNECT { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "dev":"tun150", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "time_ascii":"Sat Jan 12 18:54:48 2019", "bytes_received":"30893", "IV_NCP":"2", "untrusted_port":"1200", "ifconfig_remote":"10.150.0.2", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_4bdddbada2885cde42cd3cb1b85d77e5.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "time_unix":"1547319288", "redirect_gateway":"0", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "time_duration":"3781", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "bytes_sent":"22684", "remote_port_1":"1200", "ifconfig_pool_local_ip":"10.150.0.5", "pluginid":"7", "ifconfig_pool_remote_ip":"10.150.0.6", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

In einer variablen Umgebung werden Verbindungsdauer und Benutzerverkehr hinzugefügt.


Wie Sie sehen, ist das Schreiben und Debuggen eines Plug-Ins in der Programmiersprache C (C ++) aufgrund der Fülle an Daten in verschiedenen Aufrufen eine ziemlich zeitaufwändige Aufgabe.
Um die Funktionalität zu erweitern, wurde beschlossen, zuerst ein "Wunder" für das interne Projekt zu vollbringen und es dann öffentlich zugänglich zu machen :)
Nach langem Lesen der OpenVPN-Quellcodes und verschiedenen Beispielen hochspezialisierter Plugins wurde ein Projekt geschrieben, das Python als Programmiersprache für die Sitzungsverarbeitungslogik verwendet. Der Code ist ein Plug-In in der C-Sprache, das eine Verbindung zu OpenVPN herstellt und alle Anforderungen an das Plug-In über die c-api-Referenz in Python an das Modul sendet.


OpenVPN Plugin Python Proxy


Warum ist Python-Modul?


Die Python-C-API-Referenz, die direkt mit Python-Dateien arbeitet, funktioniert beim Laden von Python-Bibliotheken nicht richtig.


Wie funktioniert es


Wenn das Plugin in OpenVPN initialisiert wird, gibt das Plugin eine maskierte Liste aller Funktionen zurück, die es ausführen kann. Wenn die nächste Verbindungsphase oder das nächste interne Ereignis eintritt, ruft OpenVPN die entsprechenden Funktionen vom Plugin aus auf. Das Plugin konvertiert die an die Funktion übergebenen Umgebungsvariablen und Parameter in eine Struktur, initialisiert Python und übergibt die Struktur an die entsprechende Prozedur des Python-Moduls. Die Prozedur gibt eine von drei Antworten an das Plugin zurück (0 - Erfolg, 1 - Fehler, 2 - Zurückgestellt). Die Antwort wird von OpenVPN transformiert und zurückgegeben.


Bitte beachten Sie, dass alle Modulaufrufe "zustandslos" sind, was bedeutet, dass sich die Prozeduren nicht erinnern und nicht wissen, was früher bei anderen Aufrufen passiert ist. Sie können sich nur auf die variable Umgebung konzentrieren, die von OpenVPN an das Plugin übergeben wurde.


Innerhalb des Python-Moduls können Sie jede Logik implementieren, indem Sie die erforderlichen Bibliotheken und Ressourcen verbinden. Wenn Sie sich über die Geschwindigkeit der Überprüfungen nicht sicher sind, verwenden Sie "ausstehende" Bestätigungen.


Mithilfe der Gruppierung von Benutzern, die mit dem Dienst verbunden sind, können Sie über pf_file die Netzwerkinteraktion zwischen Benutzern und anderen Ressourcen optimieren. Durch Anschließen des Plug-Ins zur Überwachung ist es wiederum immer möglich, Client-Sitzungen über die OpenVPN-Verwaltungsoberfläche zu verwalten.


Während des Testens des Projekts wurde ein Mechanismus zur Kennworterzeugung entwickelt, ähnlich wie bei JWT-Token, jedoch mit einer geringeren Größe.


Der Punkt ist einfach. Das Token enthält die Client-ID und das Ablaufdatum des Zugriffs. Zum Signieren des Tokens wird HMAC_SHA1 mit einem privaten Schlüssel verwendet. Nach dem Signieren des Tokens wird der Textinhalt durch die Signatur beschädigt und in base64 konvertiert. Somit wird die "Versiegelung" des Tokens erhalten. Ein versiegeltes Token wird als Passwort des Benutzers verwendet. Wenn eine nicht autorisierte Änderung eines Datenblocks auftritt, wird xor unterbrochen. Wenn xor unterbrochen wird, wird die Signaturüberprüfung unterbrochen. Ohne einen privaten Schlüssel kann die Signatur nicht geändert werden.


Wenn Sie die Uhrzeit des Passworts nicht manuell steuern möchten, generieren Sie ein solches Token und überprüfen Sie die Gültigkeit im Plugin, ohne externe Dienste aufzurufen. Dieses Schema ist sehr praktisch für die Generierung von Sitzungskennwörtern für eine bestimmte Zeit. Gleichzeitig können Sie den Inhalt des Tokens an ein externes Steuerungssystem übertragen, das sich selbst so konfiguriert, dass der Benutzer nach Ablauf des Tokens getrennt wird.


Ich hoffe, die Informationen in diesem Artikel haben Ihnen geholfen.
Vielen Dank, dass Sie sich die Zeit genommen haben, es zu lesen.
Wenn Sie Fragen haben, werde ich versuchen zu beantworten, was ich kann.


© Aborche 2019
Aborche

Source: https://habr.com/ru/post/de435802/


All Articles