Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

¡Hola colegas! Hoy, cuando la intensidad de las pasiones en torno al "trabajo remoto" disminuyó un poco, la mayoría de los administradores ganaron la tarea de acceso remoto de los empleados a la red corporativa, es hora de compartir mi larga experiencia en la mejora de la seguridad VPN. Este artículo no estará de moda ahora IPSec IKEv2 y xAuth. Se trata de construir un sistema. autenticación de dos factores (2FA) Usuarios de VPN cuando MikroTik actúa como un servidor VPN. Es decir, cuando se utilizan protocolos "clásicos" como PPP.

Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

Hoy les contaré cómo proteger MikroTik PPP-VPN incluso en caso de "secuestro" de la cuenta de usuario. Cuando le presentaron este esquema a uno de mis clientes, lo describió brevemente como "bueno, ¡ahora es como en un banco!".

El método no utiliza servicios de autenticadores externos. Las tareas son realizadas internamente por el propio enrutador. Sin coste para el cliente conectado. El método funciona tanto para clientes de PC como para dispositivos móviles.

El régimen general de protección es el siguiente:

  1. La dirección IP interna de un usuario que se ha conectado con éxito al servidor VPN se incluye automáticamente en la lista gris.
  2. El evento de conexión genera automáticamente un código único que se envía al usuario mediante uno de los métodos disponibles.
  3. Las direcciones en esta lista tienen acceso limitado a los recursos de la red local, con la excepción del servicio de "autenticador", que está esperando recibir un código de acceso de un solo uso.
  4. Después de presentar el código, el usuario tiene acceso a los recursos internos de la red.

primero el problema más pequeño que tuve que enfrentar fue almacenar información de contacto sobre el usuario para enviarle el código 2FA. Dado que es imposible crear campos de datos arbitrarios correspondientes a usuarios en Mikrotik, se utilizó el campo de "comentario" existente:

/ppp secretos agregar nombre=Petrov contraseña=4M@ngr! comentario="89876543210"

El segundo el problema resultó ser más serio: la elección de la ruta y el método de entrega del código. Actualmente se encuentran implementados tres esquemas: a) SMS vía USB-modem b) e-mail c) SMS vía e-mail disponible para clientes corporativos de la operadora red celular.

Sí, los esquemas de SMS traen costos. Pero si te fijas, "la seguridad siempre tiene que ver con el dinero" (c).
Personalmente, no me gusta el esquema con el correo electrónico. No porque requiera que el servidor de correo esté disponible para el cliente que se está autenticando; no es un problema dividir el tráfico. Sin embargo, si un cliente guarda por descuido las contraseñas de vpn y de correo electrónico en un navegador y luego pierde su computadora portátil, el atacante obtendrá acceso total a la red corporativa desde allí.

Entonces, está decidido: entregamos un código de un solo uso mediante mensajes SMS.

Третья El problema era donde cómo generar un código pseudoaleatorio para 2FA en MikroTik. No existe un análogo de la función random() en el lenguaje de secuencias de comandos de RouterOS, y he visto varios generadores de números pseudoaleatorios de secuencias de comandos antes. No me gustó ninguno de ellos por varias razones.

De hecho, ¡hay un generador de secuencias pseudoaleatorias en MikroTik! Está oculto a una mirada superficial en el contexto de /certificates scep-server. El primer método obtener una contraseña de un solo uso es fácil y simple, con el comando /certificados scep-servidor otp generar. Si realizamos una operación de asignación de variable simple, obtendremos un valor de matriz que se puede usar más tarde en los scripts.

segundo método obtener una contraseña de un solo uso que también es fácil de aplicar, utilizando un servicio externo Random.org para generar el tipo deseado de secuencia de números pseudoaleatorios. Aquí hay un simplificado voladizo ejemplo de obtener datos en una variable:

código
: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 solicitud formateada para la consola (se requerirán caracteres especiales de escape en el cuerpo del script) recibe una cadena de seis dígitos en la variable $rnd1. El siguiente comando "poner" simplemente muestra la variable en la consola de MikroTik.

El cuarto problema que tuvo que resolverse rápidamente: así es como y dónde el cliente conectado transferirá su código único en la segunda etapa de autenticación.

Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

Debe haber un servicio en el enrutador MikroTik que pueda aceptar el código y emparejarlo con un cliente específico. Si el código proporcionado coincide con el esperado, la dirección del cliente debe incluirse en una determinada lista "blanca", direcciones desde las cuales se permite el acceso a la red interna de la empresa.

Debido a la mala elección de servicios, se decidió aceptar códigos a través de http utilizando el webproxy integrado en Mikrotik. Y dado que el cortafuegos puede trabajar con listas dinámicas de direcciones IP, es el cortafuegos el que realiza la búsqueda del código, lo hace coincidir con la IP del cliente y lo agrega a la lista "blanca" usando la expresión regular de Layer7. Al enrutador en sí se le ha asignado un nombre DNS condicional "gw.local", se ha creado un registro A estático para enviar a los clientes PPP:

DNS
/ip dns static agregar nombre=gw.dirección local=172.31.1.1

Captura de tráfico de clientes no verificados en el 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

En este caso, el proxy tiene dos funciones.

1. Abrir conexiones tcp con clientes;

2. En caso de autorización exitosa, redirija el navegador del cliente a una página o imagen que notifique sobre la autenticación exitosa:

Configuración de 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

Enumeraré los elementos de configuración importantes:

  1. interface-list "2fa": una lista dinámica de interfaces de clientes, cuyo tráfico requiere procesamiento dentro de 2FA;
  2. lista de direcciones "2fa_jailed" - lista "gris" de direcciones IP de túnel de clientes VPN;
  3. address_list "2fa_approved": lista "blanca" de direcciones IP de túnel de clientes VPN que han superado con éxito la autenticación de dos factores.
  4. cadena de cortafuegos "input_2fa": verifica la presencia de un código de autorización en los paquetes tcp y hace coincidir la dirección IP del remitente del código con la requerida. Las reglas de la cadena se agregan y eliminan dinámicamente.

Un diagrama de flujo simplificado del procesamiento de paquetes se ve así:

Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

Para ingresar a la verificación de Layer7 del tráfico de clientes de la lista "gris" que aún no han pasado la segunda etapa de autenticación, se ha creado una regla en la cadena de "entrada" estándar:

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

Ahora comencemos a sujetar toda esta riqueza al servicio PPP. MikroTik le permite usar scripts en perfiles (ppp-profile) y asignarlos a los eventos de establecimiento y ruptura de una conexión ppp. La configuración del perfil ppp se puede aplicar al servidor PPP en su totalidad oa usuarios individuales. Al mismo tiempo, el perfil asignado al usuario tiene prioridad, anulando los parámetros del perfil seleccionado para el servidor en su conjunto con sus parámetros especificados.

Como resultado de este enfoque, podemos crear un perfil especial para la autenticación de dos factores y asignarlo no a todos los usuarios, sino solo a aquellos que lo consideren necesario. Esto puede ser relevante si utiliza los servicios de PPP no solo para conectar a los usuarios finales, sino también para crear conexiones de sitio a sitio.

En el perfil especial recién creado, utilizamos la adición dinámica de la dirección y la interfaz del usuario conectado a las listas "grises" de direcciones e interfaces:

winbox
Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

código
/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 necesario utilizar las listas de "lista de direcciones" y "lista de interfaces" para detectar y capturar tráfico de clientes VPN no secundarios en la cadena dstnat (enrutamiento previo).

Cuando se completa la preparación, se crean cadenas de firewall adicionales y un perfil, escribiremos un script responsable de la generación automática del código 2FA y las reglas de firewall individuales.

Documentación wiki.mikrotik.com on PPP-Profile nos enriquece con información sobre las variables asociadas a los eventos de conexión-desconexión del cliente PPP "Ejecutar secuencia de comandos en el evento de inicio de sesión del usuario. Estas son variables disponibles a las que se puede acceder para el script de eventos: usuario, dirección local, dirección remota, identificador de llamadas, identificador de llamadas, interfaz". Algunos de ellos son muy útiles para nosotros.

Código utilizado en el perfil para el evento de conexión de activación de 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

Especialmente para aquellos a quienes les gusta copiar y pegar sin pensar, les advierto: el código se tomó de la versión de prueba y puede contener errores tipográficos menores. No será difícil para una persona comprensiva averiguar exactamente dónde.

Cuando un usuario se desconecta, se genera un evento "On-Down" y se llama al script correspondiente con parámetros. El propósito de este script es limpiar las reglas de firewall creadas para el usuario desconectado.

Código utilizado en el perfil para el evento de conexión PPP on-down

: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]
A continuación, puede crear usuarios y asignar todos o algunos de ellos a un perfil de autenticación de dos factores.

winbox
Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

código
/ppp secrets set [find name=Petrov] profile=2FA

Cómo se ve en el lado del cliente.

Cuando se establece una conexión VPN, un teléfono/tableta Android/iOS con una tarjeta SIM recibe un SMS como este:

SMS
Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

Si la conexión se establece directamente desde el teléfono / tableta, puede pasar por 2FA simplemente haciendo clic en el enlace del mensaje. Es cómodo.

Si la conexión VPN se establece desde una PC, el usuario deberá ingresar un formulario de contraseña mínima. Se le entrega al usuario un pequeño formulario en forma de archivo HTML al configurar la VPN. El archivo puede incluso enviarse por correo para que el usuario lo guarde y cree un acceso directo en un lugar conveniente. Se parece a esto:

Etiqueta en la mesa
Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

El usuario hace clic en el acceso directo, se abre un formulario de entrada de código simple, que pegará el código en la URL abierta:

Formulario de pantalla
Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

La forma más primitiva se da como ejemplo. Quienes lo deseen pueden modificar por sí mismos.

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>

Si la autorización fue exitosa, el usuario verá el logotipo de MikroTik en el navegador, lo que debería indicar una autenticación exitosa:

Autenticación de dos factores de usuarios de VPN a través de MikroTik y SMS

Tenga en cuenta que la imagen se devuelve desde el servidor web integrado de MikroTik mediante WebProxy Deny Redirect.

Supongo que la imagen se puede personalizar usando la herramienta "punto de acceso", cargando su propia versión allí y configurando la URL de redirección de denegación con WebProxy.

Una gran solicitud para aquellos que están tratando de comprar el "juguete" Mikrotik más barato por $ 20 y reemplazar un enrutador de $ 500 con él: no lo hagan. Los dispositivos como "hAP Lite" / "hAP mini" (punto de acceso doméstico) tienen una CPU (smips) muy débil y es probable que no puedan hacer frente a la carga en el segmento empresarial.

¡Atención! Esta solución tiene un inconveniente: cuando los clientes se conectan o desconectan, se producen cambios de configuración que el enrutador intenta guardar en su memoria no volátil. Con una gran cantidad de clientes y conexiones y desconexiones frecuentes, esto puede conducir a la degradación del almacenamiento interno en el enrutador.

PD: Los métodos para entregar el código al cliente se pueden ampliar y complementar en la medida en que sus capacidades de programación sean suficientes. Por ejemplo, puedes enviar mensajes a telegram o… ¡sugerir opciones!

Espero que el artículo te sea útil y ayude a que las redes de las pequeñas y medianas empresas sean un poco más seguras.

Fuente: habr.com