Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Bonjour collègues ! Aujourd'hui, alors que la passion autour du télétravail a légèrement diminué, la plupart des administrateurs ont réussi à permettre l'accès à distance des employés au réseau de l'entreprise. Il est temps de partager mon ancienne expérience sur l'amélioration de la sécurité VPN. Cet article n'abordera pas les tendances actuelles comme IPSec IKEv2 et xAuth. Nous parlerons de la construction d'un système d'authentification à deux facteurs (2FA) pour les utilisateurs VPN, lorsque MikroTik agit en tant que serveur VPN. En particulier, lorsque des protocoles « classiques » tels que PPP sont utilisés.

Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Aujourd'hui, je vais vous expliquer comment protéger MikroTik PPP-VPN même en cas de « détournement » d'un compte utilisateur. Lorsque ce schéma a été mis en œuvre pour l'un de mes clients, il l'a décrit comme « eh bien, c'est presque comme à la banque ! »

Cette méthode n'utilise pas de services d'authentification externes. Les tâches sont exécutées par les moyens internes du routeur lui-même. Sans coûts pour le client connecté. Cette méthode fonctionne aussi bien pour les clients PC que pour les appareils mobiles.

Le schéma général de protection est le suivant :

  1. L'adresse IP interne de l'utilisateur qui s'est correctement connecté au serveur VPN est automatiquement ajoutée à une liste « grise ».
  2. L'événement de connexion génère automatiquement un code unique, qui est envoyé à l'utilisateur par l'un des moyens disponibles.
  3. Les adresses figurant sur cette liste ont un accès restreint aux ressources du réseau local, à l'exception du service « authentificateur », qui attend la réception du code de mot de passe unique.
  4. Après présentation du code, l'utilisateur obtient accès aux ressources internes du réseau.

Premier Le plus petit problème rencontré a été le stockage des informations de contact de l'utilisateur pour l'envoi du code 2FA. Étant donné qu'il n'est pas possible de créer des champs de données arbitraires correspondant aux utilisateurs dans MikroTik, le champ existant « commentaire » a été utilisé :

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

Deuxième Le problème s'est avéré plus sérieux — le choix de la méthode et du mode de livraison du code. Actuellement, trois schémas ont été mis en œuvre : a) SMS via un modem USB b) e-mail c) SMS par e-mail, disponibles pour les clients d'entreprise du fournisseur de téléphonie mobile rouge.

Oui, les schémas avec SMS entraînent des coûts. Mais si l'on y réfléchit, « la sécurité, c'est toujours une question d'argent ».
Le schéma par e-mail ne me plaît pas. Ce n'est pas parce qu'il exige l'accessibilité du serveur de messagerie pour le client authentifié — ce n'est pas un problème de diviser le trafic. Toutefois, si le client a négligemment enregistré ses mots de passe à la fois sur le VPN et sur le mail dans le navigateur, et qu'il a ensuite perdu son ordinateur portable, un malfaiteur obtiendra un accès complet au réseau d'entreprise.

Eh bien, c'est décidé — nous livrons un code temporaire par SMS.

Troisième Le problème était de savoir où et comment générer un code pseudo-aléatoire pour 2FA sur MikroTik.Dans le langage de script RouterOS, il n'existe pas d'équivalent à la fonction random(), et j'ai déjà vu plusieurs scripts générateurs de nombres pseudo-aléatoires, mais aucun d'eux ne m'a satisfait pour diverses raisons.

En réalité, il existe un générateur de séquences pseudo-aléatoires dans MikroTik ! Il est caché au premier coup d'œil dans le contexte /certificates scep-server. Première méthode Obtenir un mot de passe temporaire est facile — avec la commande. /certificates scep-server otp generateSi nous effectuons une simple opération d'attribution de variable, nous obtiendrons une valeur de type tableau, que nous pourrons utiliser ultérieurement dans les scripts.

Deuxième méthode Pour obtenir un mot de passe temporaire qui peut également être facilement utilisé — utilisation d'un service externe. random.org pour générer la séquence de nombres pseudo-aléatoires souhaitée. Voici un exemple simplifié. en ligne de commande. Voici un exemple de récupération de données dans une 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

La requête formatée pour la console (dans le corps du script, il sera nécessaire d'échapper les caractères spéciaux) récupère une chaîne de six caractères-chiffres dans la variable $rnd1. La commande suivante « put » affiche simplement la variable dans la console MikroTik.

Le quatrième problème, que j'ai dû résoudre rapidement — est de savoir comment et où le client connecté transmettra son code temporaire à la deuxième étape d'authentification.

Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Un service doit exister sur le routeur MikroTik capable de recevoir le code et de le faire correspondre à un client spécifique. Si le code fourni correspond au code attendu, l'adresse du client doit être ajoutée à une sorte de liste blanche, où les adresses sont autorisées à accéder au réseau interne de l'entreprise.

Étant donné le choix limité des services, il a été décidé d'accepter les codes via http à l'aide du webproxy intégré dans MikroTik. Comme le pare-feu peut travailler avec des listes d'adresses IP dynamiques, la recherche du code, sa correspondance avec l'IP du client et son ajout à la liste « blanche » est effectuée par le pare-feu au moyen de Layer7 regexp. Au routeur a été attribué un nom DNS conditionnel « gw.local », sur lequel un enregistrement A statique a été créé pour attribuer aux clients PPP :

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

Capture sur le proxy du trafic des clients non vérifiés :
/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

Dans ce cas, le proxy a deux fonctions.

1. Ouvrir des connexions tcp avec les clients ;

2. En cas d'autorisation réussie, rediriger le navigateur du client vers une page ou une image informant de la réussite de l'authentification :

Configuration du proxy
/ip proxy
définir enabled=yes port=3128
/ip proxy access
ajouter action=deny disabled=no redirect-to=gw.local./mikrotik_logo.png src-address=0.0.0.0/0

Je vais énumérer les éléments importants de la configuration :

  1. interface-list « 2fa » — liste dynamique des interfaces clients dont le trafic nécessite un traitement dans le cadre de la 2FA ;
  2. address-list « 2fa_jailed » — liste « grise » des adresses IP de tunnel des clients VPN ;
  3. address_list « 2fa_approved » — liste « blanche » des adresses IP de tunnel des clients VPN ayant réussi l'authentification à deux facteurs.
  4. chaîne de pare-feu « input_2fa » — c'est là que les paquets tcp sont vérifiés pour la présence d'un code d'autorisation et la correspondance de l'adresse IP de l'expéditeur du code avec celle requise. Les règles sont ajoutées et supprimées dynamiquement dans la chaîne.

Un schéma simplifié du traitement des paquets ressemble à ceci :

Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Pour que le trafic des clients figurant sur la liste « grise » et n'ayant pas encore passé la seconde étape d'authentification soit vérifié par Layer7, une règle a été créée dans la chaîne standard « input » :

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

Nous allons maintenant intégrer toute cette richesse au service PPP. MikroTik permet d'utiliser des scripts dans les profils (ppp-profile) et de les attribuer aux événements d'établissement et de rupture de la connexion PPP. Les paramètres du ppp-profile peuvent être appliqués tant au serveur PPP dans son ensemble qu'à des utilisateurs individuels. Dans ce cas, le profil attribué à l'utilisateur a la priorité, remplaçant ses paramètres par ceux définis pour le profil choisi pour le serveur dans son ensemble.

Avec cette approche, nous pouvons créer un profil spécial pour l'authentification à deux facteurs et l'attribuer non pas à tous les utilisateurs, mais seulement à ceux que nous jugeons nécessaires. Cela peut être pertinent si les services PPP sont utilisés non seulement pour connecter des utilisateurs finaux, mais aussi pour établir des connexions site-à-site.

Dans le nouveau profil spécial, nous utilisons l'ajout dynamique de l'adresse et de l'interface de l'utilisateur connecté aux listes «grises» d'adresses et d'interfaces :

winbox
Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et 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

Il est nécessaire d'utiliser conjointement les listes «address-list» et «interface-list» pour identifier et capturer le trafic des clients VPN n'ayant pas passé l'authentification secondaire dans la chaîne dstnat (prerouting).

Lorsque la préparation est terminée, les chaînes de pare-feu supplémentaires et le profil sont créés, nous allons écrire un script responsable de l'autogénération du code 2FA et des règles de pare-feu séparées.

Documentation wiki.mikrotik.com Concernant le PPP-Profile, il nous enrichit d'informations sur les variables liées aux événements de connexion-déconnexion des clients PPP «Exécuter le script lors de l'événement de connexion de l'utilisateur. Voici les variables accessibles pour le script d'événement : user, local-address, remote-address, caller-id, called-id, interface». Certaines d'entre elles nous seront très utiles.

Le code utilisé dans le profil pour l'événement de connexion PPP on-up

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

"adresse-locale")
:journaliser info (

"adresse-distance")
:journaliser info (

"identifiant-appelant")
:journaliser info (

"identifiant-appelé")
:journaliser info ([/int pptp-server get (

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

"adresse-distance") 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 ("Votre code : " . $comm1 . " Ou ouvrez le lien http://gw.local/otp/" . $comm1 . " /")

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

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

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

"vcomment") commentaire=(

"adresse-distance") 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") protocole=tcp src-address=(

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


Pour ceux qui aiment copier-coller sans réfléchir, je préviens — le code provient d'une version de test et peut contenir quelques erreurs mineures. Il ne sera pas difficile pour une personne compréhensive de comprendre où se trouvent ces erreurs.

Lors de la déconnexion de l'utilisateur, un événement «On-Down» est généré et le script correspondant est appelé avec des paramètres. La tâche de ce script est de nettoyer les règles de pare-feu créées pour l'utilisateur déconnecté.

Le code utilisé dans le profil pour l'événement de connexion PPP on-down

:local vcomment ("2fa_" . (

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

"adresse distante") liste=2fa_approuvée]
/ip firewall filter remove [find chain="input_2fa" src-address=(

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


Après cela, vous pouvez créer des utilisateurs et attribuer à tous ou à certains d'entre eux un profil d'authentification à deux facteurs.

winbox
Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

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

À quoi cela ressemble du côté client.

Lors de l'établissement d'une connexion VPN, un SMS de type similaire arrive sur le téléphone/tablette Android/iOS avec une carte SIM :

SMS
Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Si la connexion est établie directement depuis le téléphone/tablette, vous pouvez passer le 2FA simplement en cliquant sur le lien du message. C'est pratique.

Si une connexion VPN est établie avec PC, l'utilisateur devra saisir un formulaire minimal de mot de passe. Un petit formulaire sous forme de fichier HTML est transmis à l'utilisateur lors de la configuration du VPN. Ce fichier peut même être envoyé par e-mail, afin que l'utilisateur puisse le sauvegarder et créer un raccourci à un endroit pratique. Voici à quoi cela ressemble :

Raccourci sur le bureau
Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

L'utilisateur clique sur le raccourci, un simple formulaire de saisie de code s'ouvre, qui insérera le code dans l'URL ouverte :

Capture d'écran du formulaire
Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Le formulaire est très basique, fourni à titre d'exemple. Ceux qui le souhaitent peuvent l'adapter à leurs besoins.

2fa_login_mini.html

<html>
<head> <title>Connexion par SMS OTP</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head>
<body>
<form name="login" action="/fr/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="fr"/> 
<input type="button" value="Connexion" onclick="location.href='http://gw.local/otp/'+document.getElementById('text').value"/> 
</form>
</body>
</html>

Si l'authentification réussit, l'utilisateur verra le logo MikroTik dans son navigateur, ce qui devrait indiquer une authentification réussie :

Authentification à deux facteurs pour les utilisateurs VPN via MikroTik et SMS

Je note que l'image est renvoyée par le serveur Web intégré de MikroTik à l'aide de WebProxy Deny Redirect.

Je pense que l'image peut être personnalisée en utilisant l'outil «hotspot», en y téléchargeant votre propre version et en définissant l'URL Deny Redirect avec WebProxy.

Je demande à ceux qui essaient de remplacer un routeur à 500 $ par le modèle «jouet» MikroTik à 20 $ de ne pas le faire. Les appareils tels que «hAP Lite»/«hAP mini» (point d'accès domestique) ont un processeur très faible (smips), et il est très probable qu'ils ne puissent pas gérer la charge dans le segment commercial.

Avertissement ! Cette solution a un inconvénient : lors de la connexion et déconnexion des clients, des modifications de configuration se produisent, que le routeur essaie de préserver dans sa mémoire non volatile. Avec un grand nombre de clients et des connexions/déconnexions fréquentes, cela peut entraîner une dégradation du stockage interne du routeur.

P.S. : Les méthodes de livraison du code au client peuvent être étendues et complétées selon vos capacités en programmation. Par exemple, vous pouvez envoyer des messages sur telegram ou… proposez d'autres options !

J'espère que cet article vous sera utile et aidera à rendre les réseaux des petites et moyennes entreprises un peu plus sécurisés.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster