Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Ciao colleghi! Oggi, quando l'intensità delle passioni per il "lavoro a distanza" si è leggermente attenuata, la maggior parte degli amministratori ha vinto il compito di accedere da remoto ai dipendenti alla rete aziendale, è tempo di condividere la mia esperienza pluriennale nel miglioramento della sicurezza VPN. Questo articolo non andrà di moda ora IPSec IKEv2 e xAuth. Si tratta di costruire un sistema. autenticazione a due fattori (2FA) Utenti VPN quando MikroTik funge da server VPN. Vale a dire, quando vengono utilizzati protocolli "classici" come PPP.

Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Oggi ti dirò come proteggere MikroTik PPP-VPN anche in caso di "dirottamento" dell'account utente. Quando questo schema è stato presentato a uno dei miei clienti, lo ha descritto brevemente come "beh, ora è proprio come in una banca!".

Il metodo non utilizza servizi di autenticazione esterni. Le attività vengono eseguite internamente dal router stesso. Nessun costo per il cliente che si connette. Il metodo funziona sia per i client PC che per i dispositivi mobili.

Lo schema generale di protezione è il seguente:

  1. L'indirizzo IP interno di un utente che si è connesso correttamente al server VPN viene automaticamente inserito nella greylist.
  2. L'evento di connessione genera automaticamente un codice monouso che viene inviato all'utente utilizzando uno dei metodi disponibili.
  3. Gli indirizzi in questo elenco hanno un accesso limitato alle risorse della rete locale, ad eccezione del servizio "autenticatore", che è in attesa di ricevere un passcode monouso.
  4. Dopo aver presentato il codice, l'utente ha accesso alle risorse interne della rete.

prima il problema più piccolo che ho dovuto affrontare è stato memorizzare le informazioni di contatto dell'utente per inviargli il codice 2FA. Poiché è impossibile creare campi dati arbitrari corrispondenti agli utenti in Mikrotik, è stato utilizzato il campo "commento" esistente:

/ppp secrets add name=Petrov password=4M@ngr! commento="89876543210"

La seconda il problema si è rivelato più serio: la scelta del percorso e del metodo di consegna del codice. Attualmente sono implementati tre schemi: a) SMS tramite modem USB b) e-mail c) SMS tramite e-mail disponibile per i clienti aziendali dell'operatore cellulare rosso.

Sì, gli schemi SMS comportano costi. Ma se guardi, "la sicurezza riguarda sempre i soldi" (c).
Personalmente non mi piace lo schema con la posta elettronica. Non perché richieda che il server di posta sia disponibile per il client da autenticare: non è un problema dividere il traffico. Tuttavia, se un client salvasse con noncuranza sia la password vpn che quella e-mail in un browser e poi perdesse il proprio laptop, l'attaccante otterrebbe l'accesso completo alla rete aziendale da esso.

Quindi, è deciso: forniamo un codice una tantum utilizzando i messaggi SMS.

terzo Il problema era dove come generare un codice pseudo-casuale per 2FA in MikroTik. Non esiste un analogo della funzione random() nel linguaggio di scripting RouterOS, e ho già visto diversi generatori di numeri pseudo-casuali di stampelle. Non mi è piaciuto nessuno di loro per vari motivi.

In effetti, c'è un generatore di sequenze pseudo-casuali in MikroTik! È nascosto a uno sguardo superficiale nel contesto di /certificates scep-server. Il primo metodo ottenere una password monouso è facile e semplice - con il comando /certificati scep-server otp generate. Se eseguiamo una semplice operazione di assegnazione di variabili, otterremo un valore di matrice che può essere utilizzato successivamente negli script.

secondo metodo ottenere una password monouso facile da applicare, utilizzando un servizio esterno random.org per generare il tipo desiderato di sequenza di numeri pseudo-casuali. Qui è semplificato sbalzo esempio di ottenere dati in una variabile:

codice
: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

Una richiesta formattata per la console (i caratteri speciali di escape saranno richiesti nel corpo dello script) riceve una stringa di sei cifre nella variabile $rnd1. Il seguente comando "put" visualizza semplicemente la variabile nella console MikroTik.

Il quarto problema che doveva essere risolto rapidamente: ecco come e dove il client connesso trasferirà il suo codice monouso nella seconda fase dell'autenticazione.

Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Deve essere presente un servizio sul router MikroTik in grado di accettare il codice e abbinarlo a un client specifico. Se il codice fornito corrisponde a quello previsto, l'indirizzo del cliente dovrebbe essere incluso in una determinata lista "bianca", indirizzi dai quali è consentito l'accesso alla rete interna dell'azienda.

A causa della scarsa scelta dei servizi, si è deciso di accettare i codici via http utilizzando il webproxy integrato in Mikrotik. E poiché il firewall può funzionare con elenchi dinamici di indirizzi IP, è il firewall che esegue la ricerca del codice, confrontandolo con l'IP del client e aggiungendolo all'elenco "bianco" utilizzando Layer7 regexp. Al router stesso è stato assegnato un nome DNS condizionale "gw.local", su di esso è stato creato un record A statico da inviare ai client PPP:

DNS
/ip dns statico aggiungi nome=gw.indirizzo locale=172.31.1.1

Acquisizione del traffico di client non verificati sul 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 questo caso, il delegato ha due funzioni.

1. Aprire connessioni tcp con i client;

2. In caso di autorizzazione riuscita, reindirizzare il browser client a una pagina o un'immagine che notifica l'avvenuta autenticazione:

Configurazione proxy
/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

Elencherò gli elementi di configurazione importanti:

  1. interface-list "2fa" - un elenco dinamico di interfacce client, il cui traffico richiede l'elaborazione all'interno di 2FA;
  2. address-list "2fa_jailed" - elenco "grigio" degli indirizzi IP del tunnel dei client VPN;
  3. address_list "2fa_approved" - elenco "bianco" di indirizzi IP tunnel di client VPN che hanno superato con successo l'autenticazione a due fattori.
  4. catena firewall "input_2fa" - controlla i pacchetti tcp per la presenza di un codice di autorizzazione e abbina l'indirizzo IP del mittente del codice con quello richiesto. Le regole nella catena vengono aggiunte e rimosse dinamicamente.

Un diagramma di flusso semplificato dell'elaborazione dei pacchetti si presenta così:

Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Per entrare nel controllo Layer7 del traffico proveniente dai client dell'elenco "grigio" che non hanno ancora superato la seconda fase di autenticazione, è stata creata una regola nella catena "input" standard:

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

Ora iniziamo ad agganciare tutta questa ricchezza al servizio PPP. MikroTik ti consente di utilizzare script nei profili (ppp-profile) e assegnarli agli eventi di stabilire e interrompere una connessione ppp. Le impostazioni del profilo ppp possono essere applicate sia al server PPP nel suo insieme che ai singoli utenti. Allo stesso tempo, il profilo assegnato all'utente ha la priorità, sovrascrivendo i parametri del profilo selezionato per il server nel suo insieme con i suoi parametri specificati.

Come risultato di questo approccio, possiamo creare un profilo speciale per l'autenticazione a due fattori e assegnarlo non a tutti gli utenti, ma solo a coloro che lo ritengono necessario. Ciò può essere rilevante se utilizzi i servizi PPP non solo per connettere gli utenti finali, ma allo stesso tempo per creare connessioni da sito a sito.

Nel profilo speciale appena creato, utilizziamo l'aggiunta dinamica dell'indirizzo e dell'interfaccia dell'utente connesso agli elenchi "grigi" di indirizzi e interfacce:

winbox
Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

codice
/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

È necessario utilizzare entrambi gli elenchi "elenco di indirizzi" e "elenco di interfacce" per rilevare e acquisire il traffico da client VPN non secondari nella catena dstnat (prerouting).

Quando la preparazione è completata, vengono create ulteriori catene di firewall e un profilo, scriveremo uno script responsabile della generazione automatica del codice 2FA e delle singole regole del firewall.

Documentazione wiki.mikrotik.com on PPP-Profile ci arricchisce di informazioni sulle variabili associate agli eventi di connessione-disconnessione del client PPP "Esegui lo script all'evento di accesso dell'utente. Queste sono variabili disponibili accessibili per lo script dell'evento: utente, indirizzo locale, indirizzo remoto, ID chiamante, ID chiamato, interfaccia". Alcuni di loro sono molto utili per noi.

Codice utilizzato nel profilo per l'evento di connessione attiva PPP

#Логируем для отладки полученные переменные 
: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

Soprattutto per coloro a cui piace copiare e incollare senza pensare, ti avverto: il codice è tratto dalla versione di prova e potrebbe contenere piccoli errori di battitura. Non sarà difficile per una persona comprensiva capire esattamente dove.

Quando un utente si disconnette, viene generato un evento "On-Down" e viene chiamato lo script corrispondente con i parametri. Il compito di questo script è quello di ripulire le regole del firewall create per l'utente disconnesso.

Codice utilizzato nel profilo per l'evento di connessione inattiva PPP

: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]
È quindi possibile creare utenti e assegnare tutti o alcuni di essi a un profilo di autenticazione a due fattori.

winbox
Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

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

Come appare sul lato client.

Quando viene stabilita una connessione VPN, un telefono/tablet Android/iOS con una scheda SIM riceve un SMS come questo:

sms
Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Se la connessione viene stabilita direttamente dal telefono / tablet, puoi passare attraverso 2FA semplicemente facendo clic sul collegamento dal messaggio. È comodo.

Se la connessione VPN viene stabilita da un PC, all'utente verrà richiesto di inserire un modulo di password minimo. Un piccolo modulo sotto forma di un file HTML viene fornito all'utente durante l'impostazione della VPN. Il file può anche essere inviato per posta in modo che l'utente lo salvi e crei un collegamento in un posto conveniente. Sembra così:

Etichetta sul tavolo
Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

L'utente fa clic sul collegamento, si apre un semplice modulo di immissione del codice, che incollerà il codice nell'URL aperto:

Forma dello schermo
Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

La forma più primitiva è data come esempio. Chi lo desidera può modificare da sé.

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>

Se l'autorizzazione è andata a buon fine, l'utente vedrà il logo MikroTik nel browser, che dovrebbe segnalare l'avvenuta autenticazione:

Autenticazione a due fattori degli utenti VPN tramite MikroTik e SMS

Si noti che l'immagine viene restituita dal server Web MikroTik integrato utilizzando WebProxy Deny Redirect.

Suppongo che l'immagine possa essere personalizzata utilizzando lo strumento "hotspot", caricando lì la tua versione e impostando l'URL Deny Redirect con WebProxy.

Una grande richiesta a coloro che stanno cercando di acquistare il Mikrotik "giocattolo" più economico per $ 20 e sostituirlo con un router da $ 500: non farlo. Dispositivi come "hAP Lite" / "hAP mini" (punto di accesso domestico) hanno una CPU (smips) molto debole ed è probabile che non faranno fronte al carico nel segmento aziendale.

Attenzione! Questa soluzione ha uno svantaggio: quando i client si connettono o si disconnettono, si verificano modifiche alla configurazione, che il router cerca di salvare nella sua memoria non volatile. Con un numero elevato di client e frequenti connessioni e disconnessioni, ciò può portare al degrado della memoria interna nel router.

PS: i metodi per fornire il codice al cliente possono essere ampliati e integrati nella misura in cui le tue capacità di programmazione sono sufficienti. Ad esempio, puoi inviare messaggi a Telegram o ... suggerire opzioni!

Spero che l'articolo ti sia utile e contribuisca a rendere un po' più sicure le reti delle piccole e medie imprese.

Fonte: habr.com