Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Hallo Kollegen! Heute, nachdem die Spannungen rund um das Thema „Homeoffice” etwas abgeklungen sind und die meisten Administratoren die Herausforderung des Remote-Zugriffs für Mitarbeiter auf das Unternehmensnetzwerk gemeistert haben, ist es an der Zeit, meine langjährige Entwicklung zur Verbesserung der Sicherheit von VPN zu teilen. In diesem Artikel wird es nicht um die derzeit angesagten IPSec IKEv2 und xAuth gehen. Es wird um den Aufbau eines Systems der Zwei-Faktor-Authentifizierung (2FA) für VPN-Nutzer, wenn MikroTik als VPN-Server fungiert. Genauer gesagt, wenn „klassische“ Protokolle wie PPP verwendet werden.

Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Heute werde ich erklären, wie man MikroTik PPP-VPN selbst im Falle eines „Diebstahls“ eines Benutzerkontos schützt. Als dieses Schema einem meiner Kunden vorgestellt wurde, beschrieb er es kurz mit den Worten: „Nun, jetzt ist es wie in einer Bank!“

Die Methode verwendet keine externen Authentifizierungsdienste. Die Aufgaben werden mit den internen Mitteln des Routers selbst durchgeführt. Ohne Kosten für den verbundenen Client. Die Methode funktioniert sowohl für PC-Kunden als auch für mobile Geräte.

Das allgemeine Schutzschema sieht folgendermaßen aus:

  1. Die interne IP-Adresse eines Benutzers, der erfolgreich mit dem VPN-Server verbunden ist, wird automatisch auf die „Graue Liste“ gesetzt.
  2. Das Verbindungsereignis generiert automatisch einen einmaligen Code, der dem Benutzer auf eine der verfügbaren Arten zugesendet wird.
  3. Zugriffsrechte für Adressen in dieser Liste sind auf die Ressourcen des lokalen Netzwerks beschränkt, mit Ausnahme des „Authentifizierungsdienstes“, der auf den Erhalt des einmaligen Codes wartet.
  4. Nach Vorlage des Codes erhält der Benutzer Zugriff auf die internen Ressourcen des Netzwerks.

Erster Das kleinste Problem war die Speicherung der Kontaktdaten des Benutzers, um ihm den 2FA-Code zusenden zu können. Da in MikroTik keine willkürlichen Datenfelder, die den Benutzern entsprechen, erstellt werden können, wurde das vorhandene Feld „Kommentar“ verwendet:

/ppp secrets add name=Petrov password=4M@ngr! comment=«89876543210»

Zweiter Das Problem war jedoch gravierender — die Wahl des Pfades und der Methode zur Übermittlung des Codes. Derzeit sind drei Schemen implementiert: a) SMS über ein USB-Modem b) E-Mail c) SMS via E-Mail für die Unternehmenskunden des roten Mobilfunkanbieters.

Ja, die SMS-Schemas bringen Kosten mit sich. Aber wenn man sich damit auseinandersetzt, „Sicherheit ist immer eine Frage des Geldes“ (c).
Das Schema mit E-Mail gefällt mir persönlich nicht. Nicht weil es die Verfügbarkeit des Mailservers für den authentifizierten Client erfordert - es ist kein Problem, den Verkehr zu trennen. Wenn der Client jedoch sorglos Passwörter sowohl für VPN als auch für E-Mail im Browser speichert und dann sein Laptop verliert, hat ein Angreifer vollständigen Zugriff auf das Unternehmensnetzwerk.

Also, es ist beschlossen - wir liefern einen Einmal-Code per SMS.

Dritte Das Problem war, wo und wie man in MikroTik einen pseudorandomisierten Code für 2FA generiert.In der Skriptsprache RouterOS gibt es kein Pendant zur Funktion random() und ich habe zuvor mehrere provisorische Skriptgeneratoren für pseudorandomisierte Zahlen gesehen. Keiner von ihnen hat mir aus verschiedenen Gründen gefallen.

Tatsächlich gibt es einen Generator für pseudorandomisierte Sequenzen in MikroTik! Er ist im Kontext /certificates scep-server verborgen. Erste Methode Einen Einmal-Passwort zu erhalten ist einfach und unkompliziert - mit dem Befehl /certificates scep-server otp generate. Wenn man eine einfache Zuweisungsoperation für die Variable durchführt, erhält man einen Wert vom Typ Array, der später in Skripten verwendet werden kann.

Zweiter Weg das Einmal-Passwort zu erhalten, was ebenfalls einfach anzuwenden ist - die Nutzung eines externen Dienstes random.org zur Generierung der gewünschten Art von Sequenz pseudorandomisierter Zahlen. Hier ist ein vereinfachtes Konsolen Beispiel zur Datenübertragung 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

Die Anfrage, formatiert für die Konsole (im Skriptkörper müssen Spezialzeichen escaped werden), speichert eine Zeichenkette aus sechs Ziffern in der Variablen $rnd1. Der nächste Befehl „put“ gibt einfach die Variable in der MikroTik-Konsole aus.

Das vierte Problem, das schnell gelöst werden musste, war, wie und wohin der verbundene Client seinen Einmal-Code in der zweiten Authentifizierungsstufe übermitteln würde.

Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Auf dem MikroTik-Router muss ein Dienst vorhanden sein, der den Code annehmen und mit einem bestimmten Client abgleichen kann. Wenn der bereitgestellte Code mit dem erwarteten übereinstimmt, sollte die Adresse des Clients in eine Art „Whitelist“ aufgenommen werden, deren Adressen den Zugriff auf das interne Unternehmensnetzwerk erlaubt.

Aufgrund der begrenzten Auswahl an Diensten wurde beschlossen, die Codes über HTTP mithilfe des in MikroTik integrierten Webproxies zu empfangen. Da die Firewall in der Lage ist, mit dynamischen Listen von IP-Adressen zu arbeiten, erfolgt die Code-Suche, die Zuordnung zur Client-IP und die Aufnahme in die "weiße" Liste durch die Firewall mittels Layer7 regexp. Dem Router wurde der bedingte DNS-Name "gw.local" zugewiesen, und es wurde ein statischer A-Eintrag für die Vergabe an PPP-Clients erstellt:

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

Proxy-Traffic-Überwachung von nicht verifiziertem Client:
/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. TCP-Verbindungen mit Clients öffnen;

2. Bei erfolgreicher Authentifizierung den Client-Browser auf eine Seite oder ein Bild umleiten, das über den erfolgreichen Abschluss der 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 wichtige Konfigurationselemente auflisten:

  1. interface-list "2fa" — eine dynamische Liste von Client-Schnittstellen, deren Traffic im Rahmen von 2FA verarbeitet werden muss;
  2. address-list "2fa_jailed" — eine "graue" Liste von Tunnel-IP-Adressen von VPN-Clients;
  3. address_list "2fa_approved" — eine "weiße" Liste von Tunnel-IP-Adressen von VPN-Clients, die die Zwei-Faktor-Authentifizierung erfolgreich bestanden haben.
  4. Firewall-Kette "input_2fa" — hier erfolgt die Überprüfung von TCP-Paketen auf das Vorhandensein des Autorisierungscodes und die Übereinstimmung der IP-Adresse des Absenders mit der erforderlichen. Die Regeln werden dynamisch in die Kette hinzugefügt und entfernt.

Ein vereinfachtes Blockdiagramm der Paketverarbeitung sieht so aus:

Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Um den Traffic von Clients aus der "grauen" Liste, die die zweite Authentifizierungsstufe noch nicht durchlaufen haben, in die Layer7-Überprüfung zu bringen, wurde in der Standardkette "input" eine Regel erstellt:

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

Jetzt beginnen wir, all diesen Reichtum an den PPP-Dienst anzubinden. MikroTik ermöglicht die Verwendung von Skripten in Profilen (ppp-profile) und deren Zuordnung zu Ereignissen beim Aufbau und Abbruch einer PPP-Verbindung. Die Einstellungen des PPP-Profils können sowohl für den PPP-Server insgesamt als auch für einzelne Benutzer angewendet werden. Dabei hat das dem Benutzer zugewiesene Profil Vorrang und überlagert die für den Server insgesamt festgelegten Parameter.

Durch diesen Ansatz können wir ein spezielles Profil für die Zwei-Faktor-Authentifizierung erstellen und es nicht allen Benutzern zuweisen, sondern nur denjenigen, die wir für notwendig halten. Dies kann relevant sein, wenn die PPP-Dienste nicht nur für die Verbindung von Endbenutzern, sondern gleichzeitig auch für den Aufbau von Site-to-Site-Verbindungen verwendet werden.

Im neu erstellten speziellen Profil verwenden wir die dynamische Hinzufügung der Adresse und der Schnittstelle des verbundenen Benutzers zu den "grauen" Listen von Adressen und Schnittstellen:

winbox
Zwei-Faktor-Authentifizierung für VPN-Nutzer ü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

Die gleichzeitige Verwendung der Listen "address-list" und "interface-list" ist notwendig, um den Datenverkehr von VPN-Clients, die die sekundäre Autorisierung nicht bestanden haben, in der dstnat-Kette (prerouting) zu bestimmen und zu erfassen.

Nachdem die Vorbereitung abgeschlossen ist, und zusätzliche Firewall-Ketten und Profile erstellt wurden, schreiben wir ein Skript zur automatischen Generierung des 2FA-Codes und der einzelnen Firewall-Regeln.

Dokumentation wiki.mikrotik.com auf PPP-Profile bereichert uns mit Informationen über Variablen, die mit den Anmelde- und Abmeldeereignissen des PPP-Clients verbunden sind. "Führe Skript bei Benutzer-Anmeldeereignis aus. Dies sind die verfügbaren Variablen, die für das Ereignisskript zugänglich sind: Benutzer, lokale-Adresse, remote-Adresse, caller-id, called-id, Schnittstelle". Einige davon werden uns sehr nützlich sein.

Der Code, der im Profil für das PPP-Anmeldeereignis on-up verwendet wird

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

lokal-adresse")
:Protokollinformationen (

entfernte-adresse")
:Protokollinformationen (

anrufer-id")
:Protokollinformationen (

angerufene-id")
:Protokollinformationen ([/int pptp-server get (

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

entfernte-adresse") 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
:lokale vphone [/ppp geheimnis abrufen [finden name=$user] kommentar]

#Готовим тело сообщения. Если клиент подключается к VPN прямо с телефона ему достаточно
#будет перейти прямо по ссылке из полученного сообщения
:lokale msgboby ("Ihr Code: ".$comm1."n Oder öffnen Sie den Link http://gw.local/otp/".$comm1."/")

# Отправляем SMS по выбранному каналу - USB-модем или email-to-sms
wenn $viamodem tun={
/tool sms send phone-number=$vphone message=$msgboby port=$modemport }
sonst={
/tool e-mail send server=a.b.c.d from=admin@mydomain.example to=mail2sms@mcommunicator.ru subject="@".$vphone body=$msgboby }

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

entfernte-adresse"))
/ip firewall layer7-protocol add name=(

vcomment") kommentar=(

entfernte-adresse") regexp=(

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=(

vcomment") protokoll=tcp src-adresse=(

entfernte-adresse") dst-limit=1,1,src-adresse/1m40s


Speziell für diejenigen, die gedankenlos kopieren und einfügen — der Code stammt aus einer Testversion und kann geringfügige Tippfehler enthalten. Einem verständigen Menschen wird es nicht schwerfallen, herauszufinden, wo genau.

Bei der Abmeldung eines Benutzers wird das Ereignis „On-Down“ ausgelöst und das entsprechende Skript mit den Parametern aufgerufen. Die Aufgabe dieses Skripts besteht darin, die Firewall-Regeln zu bereinigen, die für den abgemeldeten Benutzer erstellt wurden.

Der Code, der im Profil für das PPP-Abmeldeereignis on-down verwendet wird

:lokale vcomment ("2fa_".

entfernte-adresse"))
/ip firewall address-list remove [find address=(

"remote-address") Liste=2fa_genehmigt]
/ip firewall filter remove [find chain="input_2fa" src-address=(

"remote-address") ]
/ip firewall layer7-protocol remove [find name=$vcomment]


Danach können Benutzer erstellt und allen oder einigen von ihnen ein Profil mit Zwei-Faktor-Authentifizierung zugewiesen werden.

winbox
Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

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

So sieht es auf der Kundenseite aus.

Beim Herstellen der VPN-Verbindung erhält das Telefon/Tablett mit Android/iOS und SIM-Karte eine SMS, die in etwa so aussieht:

SMS
Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Wenn die Verbindung direkt vom Telefon/Tablett hergestellt wird, kann man die 2FA einfach durch Klicken auf den Link in der Nachricht absolvieren. Das ist bequem.

Wenn die VPN-Verbindung mit dem PC hergestellt wird, benötigt der Benutzer ein minimales Formular zur Eingabe des Passworts. Ein kleines Formular in Form einer HTML-Datei wird dem Benutzer bei der Einrichtung des VPN übergeben. Die Datei kann sogar per E-Mail weitergeleitet werden, damit der Benutzer sie bei sich speichert und eine Verknüpfung an einem geeigneten Ort erstellt. So sieht es ungefähr aus:

Verknüpfung auf dem Desktop
Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Der Benutzer klickt mit der Maus auf die Verknüpfung, es öffnet sich ein einfaches Eingabeformular für den Code, das den Code in die geöffnete URL einfügt:

Screenshot des Formulars
Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Das Formular ist sehr einfach, es dient nur als Beispiel. Wer möchte, kann es nach seinen Wünschen anpassen.

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="/de/location.href=&#039;http://gw.local/otp/&#039;+document.getElementById(‘text&#039;).value/"  method="post"
 <input id="text" type="text" data-trp-original-action="location.href='http://gw.local/otp/'+document.getElementById(‘text').value"/><input type="hidden" name="trp-form-language" value="de"/> 
<input type="button" value="Anmelden" onclick="location.href='http://gw.local/otp/'+document.getElementById('text').value"/> 
</form>
</body>
</html>

Wenn die Authentifizierung erfolgreich war, sieht der Benutzer im Browser das Logo von MikroTik, was als Zeichen für eine erfolgreiche Authentifizierung dienen sollte:

Zwei-Faktor-Authentifizierung für VPN-Nutzer über MikroTik und SMS

Ich möchte anmerken, dass das Bild vom integrierten Webserver von MikroTik über WebProxy Deny Redirect zurückgegeben wird.

Ich nehme an, das Bild kann angepasst werden, indem das Tool „Hotspot“ verwendet wird, um eine eigene Version hochzuladen und den Deny Redirect URL mit WebProxy festzulegen.

Bitte an diejenigen, die versuchen, den billigsten „Spielzeug“-Mikrotik für $20 zu kaufen, um damit einen Router für $500 zu ersetzen — das sollte man nicht tun. Geräte wie „hAP Lite“/„hAP mini“ (Home Access Point) haben eine sehr schwache CPU (smips) und werden wahrscheinlich mit der Last im Business-Segment nicht zurechtkommen.

Warnung! Dieses Lösung hat einen Nachteil: Bei der Verbindung und Trennung von Clients gibt es Änderungen an der Konfiguration, die der Router in seinem nichtflüchtigen Speicher zu speichern versucht. Bei einer großen Anzahl von Clients und häufigen Verbindungen und Trennungen kann dies zu einer Degradierung des internen Speichers im Router führen.

P.S.: Die Methoden zur Übermittlung des Codes an den Kunden können erweitert und ergänzt werden, je nach Ihren Programmiermöglichkeiten. Zum Beispiel können Sie Nachrichten in Telegram senden oder… schlagen Sie weitere Optionen vor!

Ich hoffe, der Artikel ist für Sie nützlich und trägt dazu bei, die Netzwerke von kleinen und mittleren Unternehmen noch ein wenig sicherer zu machen.

Quelle: habr.com

60GB SSD 8Gb DDR4