Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Hallo collega's! Vandaag, toen de intensiteit van de passies rond "werken op afstand" een beetje afnam, won de meerderheid van de beheerders de taak van externe toegang van werknemers tot het bedrijfsnetwerk, het is tijd om mijn jarenlange ervaring met het verbeteren van VPN-beveiliging te delen. Dit artikel zal nu niet in de mode zijn IPSec IKEv2 en xAuth. Het gaat om het bouwen van een systeem. tweefactorauthenticatie (2FA) VPN-gebruikers wanneer MikroTik fungeert als een VPN-server. Namelijk wanneer "klassieke" protocollen zoals PPP worden gebruikt.

Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Vandaag zal ik je vertellen hoe je MikroTik PPP-VPN kunt beschermen, zelfs in het geval van "kaping" van het gebruikersaccount. Toen dit schema bij een van mijn klanten werd geïntroduceerd, beschreef hij het kort als "nou, nu is het net als bij een bank!".

De methode maakt geen gebruik van externe authenticatiediensten. De taken worden intern uitgevoerd door de router zelf. Geen kosten voor de aansluitende klant. De methode werkt voor zowel pc-clients als mobiele apparaten.

Het algemene beschermingsschema is als volgt:

  1. Het interne IP-adres van een gebruiker die met succes verbinding heeft gemaakt met de VPN-server, wordt automatisch op de grijze lijst geplaatst.
  2. De verbindingsgebeurtenis genereert automatisch een eenmalige code die naar de gebruiker wordt verzonden met behulp van een van de beschikbare methoden.
  3. Adressen in deze lijst hebben beperkte toegang tot lokale netwerkbronnen, met uitzondering van de "authenticator"-service, die wacht op het ontvangen van een eenmalige toegangscode.
  4. Na het presenteren van de code heeft de gebruiker toegang tot de interne bronnen van het netwerk.

eerste het kleinste probleem waarmee ik te maken kreeg, was het opslaan van contactgegevens van de gebruiker om hem de 2FA-code te sturen. Aangezien het onmogelijk is om willekeurige gegevensvelden te creëren die overeenkomen met gebruikers in Mikrotik, werd het bestaande veld "commentaar" gebruikt:

/ppp geheimen voeg naam toe=Petrov wachtwoord=4M@ngr! commentaar = "89876543210"

Het tweede het probleem bleek ernstiger te zijn - de keuze van het pad en de methode om de code af te leveren. Er zijn momenteel drie schema's geïmplementeerd: a) SMS via USB-modem b) e-mail c) SMS via e-mail beschikbaar voor zakelijke klanten van de rode mobiele operator.

Ja, sms-regelingen brengen kosten met zich mee. Maar als je kijkt, "veiligheid gaat altijd over geld" (c).
Persoonlijk hou ik niet van het schema met e-mail. Niet omdat de mailserver beschikbaar moet zijn voor de client die wordt geverifieerd - het is geen probleem om het verkeer te splitsen. Als een klant echter achteloos zowel vpn- als e-mailwachtwoorden in een browser opslaat en vervolgens zijn laptop kwijtraakt, krijgt de aanvaller hiermee volledige toegang tot het bedrijfsnetwerk.

Dus, het is besloten - we leveren een eenmalige code via sms-berichten.

Третья Het probleem was waar hoe een pseudo-willekeurige code voor 2FA in MikroTik te genereren. Er is geen analoog van de functie random() in de routerOS-scripttaal, en ik heb al verschillende pseudo-random number generators van crutch-scripts gezien. Ik vond geen van hen leuk om verschillende redenen.

In feite is er een pseudo-willekeurige reeksgenerator in MikroTik! Het is verborgen voor een oppervlakkige blik in de context van /certificates scep-server. De eerste methode een eenmalig wachtwoord krijgen is eenvoudig en eenvoudig - met de opdracht /certificaten scep-server otp genereren. Als we een eenvoudige bewerking voor het toewijzen van variabelen uitvoeren, krijgen we een arraywaarde die later in scripts kan worden gebruikt.

De tweede manier het verkrijgen van een eenmalig wachtwoord dat ook eenvoudig is toe te passen - met behulp van een externe dienst random.org om de gewenste reeks pseudo-willekeurige getallen te genereren. Hier is een vereenvoudigde vrijdragende voorbeeld van het krijgen van gegevens in een variabele:

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

Een verzoek dat is opgemaakt voor de console (ontsnappen aan speciale tekens is vereist in de hoofdtekst van het script) ontvangt een reeks van zes cijfers in de variabele $rnd1. De volgende "put" -opdracht geeft eenvoudig de variabele weer in de MikroTik-console.

Het vierde probleem die snel moest worden opgelost - dit is hoe en waar de aangesloten client zijn eenmalige code zal overdragen in de tweede fase van authenticatie.

Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Er moet een service op de MikroTik-router zijn die de code kan accepteren en matchen met een specifieke client. Als de verstrekte code overeenkomt met de verwachte code, moet het adres van de klant worden opgenomen in een bepaalde "witte" lijst, waarvan adressen toegang hebben tot het interne netwerk van het bedrijf.

Vanwege de slechte keuze aan services werd besloten om codes via http te accepteren met behulp van de webproxy die in Mikrotik is ingebouwd. En aangezien de firewall kan werken met dynamische lijsten met IP-adressen, is het de firewall die de code zoekt, deze vergelijkt met het client-IP en deze toevoegt aan de "witte" lijst met behulp van Layer7 regexp. De router zelf heeft een voorwaardelijke DNS-naam "gw.local" gekregen, er is een statisch A-record op gemaakt voor uitgifte aan PPP-clients:

DNS
/ip dns statisch toevoegen naam=gw.lokaal adres=172.31.1.1

Verkeer van niet-geverifieerde clients op de proxy vastleggen:
/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 dit geval heeft de proxy twee functies.

1. Open tcp-verbindingen met klanten;

2. In geval van succesvolle autorisatie, leidt u de browser van de client door naar een pagina of afbeelding die melding maakt van succesvolle authenticatie:

Proxy-configuratie
/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

Ik zal de belangrijke configuratie-elementen opsommen:

  1. interfacelijst "2fa" - een dynamische lijst met clientinterfaces, waarvan verkeer binnen 2FA moet worden verwerkt;
  2. adreslijst "2fa_jailed" - "grijze" lijst met tunnel-IP-adressen van VPN-clients;
  3. address_list "2fa_approved" - "witte" lijst met tunnel-IP-adressen van VPN-clients die tweefactorauthenticatie met succes hebben doorstaan.
  4. firewallketen "input_2fa" - het controleert tcp-pakketten op de aanwezigheid van een autorisatiecode en koppelt het IP-adres van de afzender van de code aan het vereiste adres. Regels in de keten worden dynamisch toegevoegd en verwijderd.

Een vereenvoudigd stroomschema van pakketverwerking ziet er als volgt uit:

Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Om toegang te krijgen tot de Layer7-controle van verkeer van clients van de "grijze" lijst die de tweede authenticatiefase nog niet hebben doorlopen, is er een regel gemaakt in de standaard "invoer"-keten:

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

Laten we nu beginnen om al deze rijkdom vast te maken aan de PPP-service. Met MikroTik kunt u scripts gebruiken in profielen (ppp-profiel) en deze toewijzen aan de gebeurtenissen van het tot stand brengen en verbreken van een ppp-verbinding. De ppp-profielinstellingen kunnen worden toegepast op zowel de PPP-server als geheel als op individuele gebruikers. Tegelijkertijd heeft het profiel dat aan de gebruiker is toegewezen voorrang, waarbij de parameters van het geselecteerde profiel voor de server als geheel met de opgegeven parameters worden overschreven.

Door deze aanpak kunnen we een speciaal profiel voor tweefactorauthenticatie maken en dit niet aan alle gebruikers toewijzen, maar alleen aan degenen die dat nodig achten. Dit kan relevant zijn als u PPP-diensten niet alleen gebruikt om eindgebruikers te verbinden, maar tegelijkertijd site-to-site-verbindingen opbouwt.

In het nieuw gemaakte speciale profiel gebruiken we de dynamische toevoeging van het adres en de interface van de aangesloten gebruiker aan de "grijze" lijsten met adressen en interfaces:

winbox
Tweefactorauthenticatie van VPN-gebruikers via MikroTik en 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

Het is noodzakelijk om zowel "adreslijst"- als "interfacelijst"-lijsten te gebruiken om verkeer van niet-secundaire VPN-clients in de dstnat-keten (prerouting) te detecteren en vast te leggen.

Wanneer de voorbereiding is voltooid, aanvullende firewallketens en een profiel zijn gemaakt, zullen we een script schrijven dat verantwoordelijk is voor het automatisch genereren van de 2FA-code en individuele firewallregels.

Documentatie wiki.mikrotik.com op PPP-profiel verrijkt ons met informatie over variabelen die zijn gekoppeld aan PPP-client connect-disconnect-gebeurtenissen "Voer script uit bij login-gebeurtenis van gebruiker. Dit zijn beschikbare variabelen die toegankelijk zijn voor het gebeurtenisscript: user, local-address, remote-address, beller-id, belde-id, interface". Sommigen van hen zijn erg nuttig voor ons.

Code gebruikt in profiel voor PPP-verbindingsgebeurtenis

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

Vooral voor degenen die graag gedachteloos kopiëren en plakken, waarschuw ik u - de code is afkomstig uit de testversie en kan kleine typefouten bevatten. Het zal voor een begripvol persoon niet moeilijk zijn om erachter te komen waar precies.

Wanneer een gebruiker de verbinding verbreekt, wordt een "On-Down"-gebeurtenis gegenereerd en wordt het bijbehorende script met parameters aangeroepen. De taak van dit script is het opschonen van de firewallregels die zijn gemaakt voor de niet-verbonden gebruiker.

Code gebruikt in profiel voor PPP on-down verbindingsgebeurtenis

: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]
U kunt vervolgens gebruikers maken en ze allemaal of aan een aantal toewijzen aan een tweefactorauthenticatieprofiel.

winbox
Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

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

Hoe het er aan de kant van de klant uitziet.

Wanneer een VPN-verbinding tot stand is gebracht, ontvangt een Android/iOS-telefoon/-tablet met een simkaart een sms zoals deze:

sms
Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Komt de verbinding direct vanaf de telefoon/tablet tot stand, dan kun je 2FA eenvoudig doorlopen door op de link uit het bericht te klikken. Het is comfortabel.

Als de VPN-verbinding tot stand wordt gebracht vanaf een pc, moet de gebruiker een minimaal wachtwoordformulier invoeren. Een klein formulier in de vorm van een HTML-bestand wordt aan de gebruiker gegeven bij het instellen van de VPN. Het bestand kan zelfs per e-mail worden verzonden, zodat de gebruiker het opslaat en een snelkoppeling op een handige plek maakt. Het ziet er zo uit:

Etiket op tafel
Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

De gebruiker klikt op de snelkoppeling, er wordt een eenvoudig code-invoerformulier geopend, dat de code in de geopende URL plakt:

Scherm formulier
Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Als voorbeeld wordt de meest primitieve vorm gegeven. Wie wil, kan het zelf aanpassen.

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>

Als de autorisatie is gelukt, ziet de gebruiker het MikroTik-logo in de browser, wat een succesvolle authenticatie zou moeten aangeven:

Tweefactorauthenticatie van VPN-gebruikers via MikroTik en SMS

Merk op dat de afbeelding wordt geretourneerd van de ingebouwde MikroTik-webserver met behulp van WebProxy Deny Redirect.

Ik veronderstel dat de afbeelding kan worden aangepast met behulp van de "hotspot" -tool, door uw eigen versie daar te uploaden en de Deny Redirect URL erop in te stellen met WebProxy.

Een groot verzoek aan degenen die proberen de goedkoopste "speelgoed" Mikrotik te kopen voor $ 20 en er een router van $ 500 mee te vervangen - doe dat niet. Apparaten zoals "hAP Lite" / "hAP mini" (thuistoegangspunt) hebben een zeer zwakke CPU (smips) en zullen waarschijnlijk de belasting in het zakelijke segment niet aan.

Waarschuwing! Deze oplossing heeft één nadeel: wanneer clients verbinding maken of de verbinding verbreken, vinden configuratiewijzigingen plaats, die de router probeert op te slaan in zijn niet-vluchtige geheugen. Met een groot aantal clients en frequente verbindingen en verbroken verbindingen kan dit leiden tot verslechtering van de interne opslag in de router.

PS: Methoden voor het leveren van code aan de klant kunnen worden uitgebreid en aangevuld voor zover uw programmeermogelijkheden voldoende zijn. U kunt bijvoorbeeld berichten naar telegram sturen of ... opties voorstellen!

Ik hoop dat het artikel nuttig voor u zal zijn en zal helpen om de netwerken van kleine en middelgrote bedrijven een beetje veiliger te maken.

Bron: www.habr.com