Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Hallo Kollegen! Heute, wo die Leidenschaft für „Remote-Arbeit“ etwas nachgelassen hat und die Mehrheit der Administratoren die Aufgabe des Fernzugriffs von Mitarbeitern auf das Unternehmensnetzwerk gewonnen hat, ist es an der Zeit, meine langjährige Erfahrung bei der Verbesserung der VPN-Sicherheit zu teilen. Dieser Artikel wird jetzt nicht mehr in Mode sein, IPSec IKEv2 und xAuth. Es geht darum, ein System aufzubauen. Zwei-Faktor-Authentifizierung (2FA) VPN-Benutzer, wenn MikroTik als VPN-Server fungiert. Nämlich dann, wenn „klassische“ Protokolle wie PPP verwendet werden.

Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Heute erzähle ich Ihnen, wie Sie MikroTik PPP-VPN auch im Falle einer „Entführung“ des Benutzerkontos schützen können. Als einem meiner Kunden dieses System vorgestellt wurde, beschrieb er es kurz als „Na ja, jetzt ist es wie in einer Bank!“.

Die Methode verwendet keine externen Authentifizierungsdienste. Die Aufgaben werden intern vom Router selbst erledigt. Keine Kosten für den verbindenden Client. Die Methode funktioniert sowohl für PC-Clients als auch für mobile Geräte.

Das allgemeine Schutzsystem sieht wie folgt aus:

  1. Die interne IP-Adresse eines Benutzers, der sich erfolgreich mit dem VPN-Server verbunden hat, wird automatisch auf die graue Liste gesetzt.
  2. Das Verbindungsereignis generiert automatisch einen einmaligen Code, der mit einer der verfügbaren Methoden an den Benutzer gesendet wird.
  3. Adressen in dieser Liste haben eingeschränkten Zugriff auf lokale Netzwerkressourcen, mit Ausnahme des „Authenticator“-Dienstes, der auf den Empfang eines Einmalpasscodes wartet.
  4. Nach Vorlage des Codes hat der Benutzer Zugriff auf die internen Ressourcen des Netzwerks.

erste Das kleinste Problem, mit dem ich konfrontiert war, bestand darin, Kontaktinformationen über den Benutzer zu speichern, um ihm den 2FA-Code zu senden. Da es in Mikrotik nicht möglich ist, beliebige Datenfelder für Benutzer zu erstellen, wurde das vorhandene „Kommentar“-Feld verwendet:

/ppp Geheimnisse add name=Petrov passwort=4M@ngr! Kommentar="89876543210"

Die zweite Es stellte sich heraus, dass das Problem schwerwiegender war – die Wahl des Pfads und der Methode zur Bereitstellung des Codes. Derzeit sind drei Schemata implementiert: a) SMS über USB-Modem b) E-Mail c) SMS per E-Mail, verfügbar für Firmenkunden des roten Mobilfunkbetreibers.

Ja, SMS-Programme sind mit Kosten verbunden. Aber wenn Sie sich das ansehen, „geht es bei Sicherheit immer um Geld“ (c).
Mir persönlich gefällt das Schema mit E-Mail nicht. Nicht, weil der Mailserver für den zu authentifizierenden Client verfügbar sein muss – es ist kein Problem, den Datenverkehr aufzuteilen. Wenn ein Kunde jedoch versehentlich sowohl VPN- als auch E-Mail-Passwörter in einem Browser speichert und dann seinen Laptop verliert, erhält der Angreifer von diesem aus vollen Zugriff auf das Unternehmensnetzwerk.

Es ist also beschlossene Sache: Wir übermitteln einen einmaligen Code per SMS-Nachrichten.

Dritte Das Problem war, wo So generieren Sie einen Pseudozufallscode für 2FA in MikroTik. Es gibt kein Analogon zur Funktion random() in der Skriptsprache von RouterOS, und ich habe bereits mehrere Pseudozufallszahlengeneratoren von Crutch Script gesehen. Aus verschiedenen Gründen gefiel mir keiner davon.

Tatsächlich gibt es in MikroTik einen Pseudozufallssequenzgenerator! Im Kontext von /certificates scep-server ist es für den oberflächlichen Blick verborgen. Das erste Verfahren Ein Einmalpasswort zu erhalten ist einfach und unkompliziert – mit dem Befehl /Zertifikate scep-server otp generieren. Wenn wir eine einfache Variablenzuweisungsoperation durchführen, erhalten wir einen Array-Wert, der später in Skripten verwendet werden kann.

zweite Methode Ein Einmalpasswort zu erhalten, das auch einfach anzuwenden ist – über einen externen Dienst Random.org um die gewünschte Art von Folge von Pseudozufallszahlen zu erzeugen. Hier ist eine vereinfachte Darstellung Freischwinger Beispiel für das Einlesen von Daten in eine Variable:

Code
:global rnd1 [:pick ([/tool fetch url="https://www.random.org/strings/?num=1&len=7&digits=on&unique=on&format=plain&rnd=new" as-value output=user ]->"da
ta") 1 6] :put $rnd1

Eine für die Konsole formatierte Anfrage (Escape-Sonderzeichen sind im Hauptteil des Skripts erforderlich) empfängt eine sechsstellige Zeichenfolge in der Variablen $rnd1. Der folgende „put“-Befehl zeigt einfach die Variable in der MikroTik-Konsole an.

Das vierte Problem Das musste schnell gelöst werden: So und wohin übermittelt der verbundene Client seinen Einmalcode in der zweiten Phase der Authentifizierung.

Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Auf dem MikroTik-Router muss ein Dienst vorhanden sein, der den Code akzeptieren und einem bestimmten Client zuordnen kann. Wenn der bereitgestellte Code mit dem erwarteten übereinstimmt, sollte die Adresse des Kunden in eine bestimmte „weiße“ Liste aufgenommen werden, deren Adressen Zugriff auf das interne Netzwerk des Unternehmens gewährt werden.

Aufgrund der schlechten Auswahl an Diensten wurde beschlossen, Codes über http mit dem in Mikrotik integrierten Webproxy zu akzeptieren. Und da die Firewall mit dynamischen Listen von IP-Adressen arbeiten kann, ist es die Firewall, die die Suche nach dem Code durchführt, ihn mit der Client-IP abgleicht und ihn mithilfe von Layer7-Regexp zur „weißen“ Liste hinzufügt. Dem Router selbst wurde ein bedingter DNS-Name „gw.local“ zugewiesen, auf ihm wurde ein statischer A-Record zur Ausgabe an PPP-Clients erstellt:

DNS
/ip dns static add name=gw.local address=172.31.1.1

Erfassen des Datenverkehrs nicht verifizierter Clients auf dem Proxy:
/ip firewall nat add chain=dstnat dst-port=80,443 in-interface=2fa protocol=tcp !src-address-list=2fa_approved action=redirect to-ports=3128

In diesem Fall hat der Proxy zwei Funktionen.

1. Öffnen Sie TCP-Verbindungen mit Clients.

2. Im Falle einer erfolgreichen Autorisierung leiten Sie den Client-Browser auf eine Seite oder ein Bild um, das über die erfolgreiche Authentifizierung informiert:

Proxy-Konfiguration
/ip proxy
set enabled=yes port=3128
/ip proxy access
add action=deny disabled=no redirect-to=gw.local./mikrotik_logo.png src-address=0.0.0.0/0

Ich werde die wichtigen Konfigurationselemente auflisten:

  1. Schnittstellenliste „2fa“ – eine dynamische Liste von Client-Schnittstellen, deren Datenverkehr innerhalb von 2FA verarbeitet werden muss;
  2. Adressliste „2fa_jailed“ – „graue“ Liste der Tunnel-IP-Adressen von VPN-Clients;
  3. address_list „2fa_approved“ – „weiße“ Liste der Tunnel-IP-Adressen von VPN-Clients, die die Zwei-Faktor-Authentifizierung erfolgreich bestanden haben.
  4. Firewall-Kette „input_2fa“ – sie prüft TCP-Pakete auf das Vorhandensein eines Autorisierungscodes und gleicht die IP-Adresse des Code-Absenders mit der erforderlichen ab. Regeln in der Kette werden dynamisch hinzugefügt und entfernt.

Ein vereinfachtes Flussdiagramm der Paketverarbeitung sieht folgendermaßen aus:

Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Um in die Layer7-Prüfung des Datenverkehrs von Clients aus der „grauen“ Liste zu gelangen, die die zweite Authentifizierungsstufe noch nicht bestanden haben, wurde in der Standard-„Eingabe“-Kette eine Regel erstellt:

Code
/ip firewall filter add chain=input !src-address-list=2fa_approved action=jump jump-target=input_2fa

Beginnen wir nun damit, all diesen Reichtum an den PPP-Dienst zu binden. Mit MikroTik können Sie Skripte in Profilen (ppp-Profile) verwenden und diese den Ereignissen beim Aufbau und Abbau einer PPP-Verbindung zuordnen. Die PPP-Profileinstellungen können sowohl auf den PPP-Server als Ganzes als auch auf einzelne Benutzer angewendet werden. Gleichzeitig hat das dem Benutzer zugewiesene Profil Vorrang und überschreibt mit seinen angegebenen Parametern die Parameter des für den gesamten Server ausgewählten Profils.

Durch diesen Ansatz können wir ein spezielles Profil für die Zwei-Faktor-Authentifizierung erstellen und es nicht allen Benutzern, sondern nur denen zuweisen, die dies für erforderlich halten. Dies kann relevant sein, wenn Sie PPP-Dienste nicht nur zur Verbindung von Endbenutzern, sondern gleichzeitig auch zum Aufbau von Site-to-Site-Verbindungen nutzen.

Im neu erstellten Spezialprofil nutzen wir die dynamische Hinzufügung der Adresse und Schnittstelle des verbundenen Benutzers zu den „grauen“ Listen von Adressen und Schnittstellen:

Gewinnbox
Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Code
/ppp profile add address-list=2fa_jailed change-tcp-mss=no local-address=192.0.2.254 name=2FA interface-list=2fa only-one=yes remote-address=dhcp_pool1 use-compression=no use-encryption= required use-mpls=no use-upnp=no dns-server=172.31.1.1

Es ist notwendig, sowohl „Adressliste“- als auch „Schnittstellenlisten“-Listen zu verwenden, um Datenverkehr von nicht sekundären VPN-Clients in der dstnat-Kette (Prerouting) zu erkennen und zu erfassen.

Wenn die Vorbereitung abgeschlossen ist, zusätzliche Firewall-Ketten und ein Profil erstellt werden, schreiben wir ein Skript, das für die automatische Generierung des 2FA-Codes und einzelner Firewall-Regeln verantwortlich ist.

Dokumentation wiki.mikrotik.com auf PPP-Profile bereichert uns mit Informationen über Variablen, die mit PPP-Client-Verbindungs-/Trennungsereignissen verbunden sind „Skript bei Benutzeranmeldeereignis ausführen. Dies sind verfügbare Variablen, auf die das Ereignisskript zugreifen kann: Benutzer, lokale Adresse, entfernte Adresse, Anrufer-ID, aufgerufene ID, Schnittstelle.. Einige davon sind für uns sehr nützlich.

Code, der im Profil für das PPP-On-Up-Verbindungsereignis verwendet wird

#Логируем для отладки полученные переменные 
:log info (

quot;local-address")
:log info (


quot;remote-address")
:log info (


quot;caller-id")
:log info (


quot;called-id")
:log info ([/int pptp-server get (


quot;interface") name])
#Объявляем свои локальные переменные
:local listname "2fa_jailed"
:local viamodem false
:local modemport "usb2"
#ищем автоматически созданную запись в адрес-листе "2fa_jailed"
:local recnum1 [/ip fi address-list find address=(


quot;remote-address") list=$listname]

#получаем псевдослучайный код через random.org
#:local rnd1 [:pick ([/tool fetch url="https://www.random.org/strings/?num=1&len=7&digits=on&unique=on&format=plain&rnd=new" as-value output=user]->"data") 0 4] #либо получаем псевдослучайный код через локальный генератор
#:local rnd1 [pick ([/cert scep-server otp generate as-value minutes-valid=1]->"password") 0 4 ]

#Ищем и обновляем коммент к записи в адрес-листе. Вносим искомый код для отладки
/ip fir address-list set $recnum1 comment=$rnd1
#получаем номер телефона куда слать SMS
:local vphone [/ppp secret get [find name=$user] comment]

#Готовим тело сообщения. Если клиент подключается к VPN прямо с телефона ему достаточно
#будет перейти прямо по ссылке из полученного сообщения
:local msgboby ("Your code: ".$comm1."n Or open link http://gw.local/otp/".$comm1."/")

# Отправляем SMS по выбранному каналу - USB-модем или email-to-sms
if $viamodem do={
/tool sms send phone-number=$vphone message=$msgboby port=$modemport }
else={
/tool e-mail send server=a.b.c.d [email protected] [email protected] subject="@".$vphone body=$msgboby }

#Генерируем Layer7 regexp
local vregexp ("otp\/".$comm1)
:local vcomment ("2fa_".(


quot;remote-address"))
/ip firewall layer7-protocol add name=(


quot;vcomment") comment=(


quot;remote-address") regexp=(


quot;vregexp")

#Генерируем правило проверяющее по Layer7 трафик клиента в поисках нужного кода
#и небольшой защитой от брутфорса кодов с помощью dst-limit
/ip firewall filter add action=add-src-to-address-list address-list=2fa_approved address-list-timeout=none-dynamic chain=input_2fa dst-port=80,443,3128 layer7-protocol=(


quot;vcomment") protocol=tcp src-address=(


quot;remote-address") dst-limit=1,1,src-address/1m40s

Besonders für diejenigen, die gerne gedankenlos kopieren und einfügen, warne ich Sie – der Code stammt aus der Testversion und kann kleinere Tippfehler enthalten. Für einen verständnisvollen Menschen wird es nicht schwer sein, genau herauszufinden, wo.

Wenn ein Benutzer die Verbindung trennt, wird ein „On-Down“-Ereignis generiert und das entsprechende Skript mit Parametern aufgerufen. Die Aufgabe dieses Skripts besteht darin, die für den nicht verbundenen Benutzer erstellten Firewall-Regeln zu bereinigen.

Code, der im Profil für das PPP-Verbindungsereignis „Ein/Aus“ verwendet wird

:local vcomment ("2fa_".(

quot;remote-address"))
/ip firewall address-list remove [find address=(


quot;remote-address") list=2fa_approved] /ip firewall filter remove [find chain="input_2fa" src-address=(


quot;remote-address") ] /ip firewall layer7-protocol remove [find name=$vcomment]
Anschließend können Sie Benutzer erstellen und alle oder einige davon einem Zwei-Faktor-Authentifizierungsprofil zuweisen.

Gewinnbox
Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Code
/ppp secrets set [find name=Petrov] profile=2FA

Wie es auf der Clientseite aussieht.

Wenn eine VPN-Verbindung hergestellt wird, erhält ein Android/iOS-Telefon/Tablet mit SIM-Karte eine SMS wie diese:

SMS
Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Wenn die Verbindung direkt vom Telefon/Tablet aus hergestellt wird, können Sie 2FA nutzen, indem Sie einfach auf den Link in der Nachricht klicken. Das ist bequem.

Wenn die VPN-Verbindung von einem PC aus hergestellt wird, muss der Benutzer ein minimales Passwort eingeben. Bei der Einrichtung des VPN wird dem Nutzer ein kleines Formular in Form einer HTML-Datei übergeben. Die Datei kann sogar per E-Mail versendet werden, sodass der Benutzer sie speichert und an einem geeigneten Ort eine Verknüpfung erstellt. Es sieht aus wie das:

Etikett auf dem Tisch
Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Wenn der Benutzer auf die Verknüpfung klickt, öffnet sich ein einfaches Code-Eingabeformular, das den Code in die geöffnete URL einfügt:

Bildschirmformular
Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Als Beispiel wird die primitivste Form gegeben. Wer möchte, kann es selbst modifizieren.

2fa_login_mini.html

<html>
<head> <title>SMS OTP login</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head>
<body>
<form name="login" action="location.href='http://gw.local/otp/'+document.getElementById(‘text').value"  method="post"
 <input id="text" type="text"/> 
<input type="button" value="Login" onclick="location.href='http://gw.local/otp/'+document.getElementById('text').value"/> 
</form>
</body>
</html>

War die Autorisierung erfolgreich, sieht der Nutzer im Browser das MikroTik-Logo, das eine erfolgreiche Authentifizierung signalisieren sollte:

Zwei-Faktor-Authentifizierung von VPN-Benutzern über MikroTik und SMS

Beachten Sie, dass das Bild vom integrierten MikroTik-Webserver mithilfe von WebProxy Deny Redirect zurückgegeben wird.

Ich nehme an, dass das Bild mit dem „Hotspot“-Tool angepasst werden kann, indem Sie dort Ihre eigene Version hochladen und mit WebProxy die URL „Umleitung verweigern“ festlegen.

Eine große Bitte an diejenigen, die versuchen, das billigste „Spielzeug“ Mikrotik für 20 US-Dollar zu kaufen und damit einen 500 US-Dollar teuren Router zu ersetzen – tun Sie das nicht. Geräte wie „hAP Lite“ / „hAP mini“ (Home Access Point) verfügen über eine sehr schwache CPU (Smips) und dürften der Belastung im Business-Segment nicht gewachsen sein.

Warnung! Diese Lösung hat einen Nachteil: Wenn sich Clients verbinden oder trennen, kommt es zu Konfigurationsänderungen, die der Router versucht, in seinem nichtflüchtigen Speicher zu speichern. Bei einer großen Anzahl von Clients und häufigen Verbindungs- und Verbindungsabbrüchen kann dies zu einer Verschlechterung des internen Speichers im Router führen.

PS: Methoden zur Auslieferung von Code an den Client können erweitert und ergänzt werden, soweit Ihre Programmierfähigkeiten ausreichen. Sie können beispielsweise Nachrichten an Telegram senden oder ... Optionen vorschlagen!

Ich hoffe, dass der Artikel für Sie nützlich ist und dazu beiträgt, die Netzwerke kleiner und mittlerer Unternehmen ein wenig sicherer zu machen.

Source: habr.com