En el post anterior vimos concepto de Doble Factor de Autenticación. En este post, vamos a realizar una prueba de concepto para usar doble factor de autenticación en un escenario de VPN.
- 1 – Dispositivos hardware y software usados en este PoC:
Cliente Cisco VPN AnyConnect Firewall Cisco ASA ( servidor VPN SSL ) Radius IAS o NPS integrado en Active Directory Freeradius sobre Ubuntu Server + MultiOTP ( clase PHP ) Token compatible con OATH ( algoritmos TOTP - rfc6238 y HTOP - rfc4226 )
- 2 – Topología:
- 3 – Instalaremos y configuraremos en este post:
Freeradius 2.1.12 MultiOTP 4.0.7 La autenticación doble en el Firewall Cisco.
- 4 – Roles:
Firewall Cisco ASA como servidor de VPN SSL con autenticación primaria basada en Active Directory.
El autenticador de las credenciales de Active Directory será un servidor radius Microsoft IAS o NPS.
El cliente de software VPN que tienen instalados los usuarios es Cisco VPN AnyConnect.
La autenticación secundaria de los clientes vpn anyconnect se basará en un método de doble factor de autenticación mediante un token ( sirven los harware tokens y los soft tokens de los RFC’s mencionados antes ).
El autenticador secundario será un servidor Freeradius sobre Ubuntu Server 13.10 que usará la clase PHP MultiOTP.
- 5 – Proceso de la autenticación múltiple, correcta y simplificada:
5.1 – El usuario arranca el cliente VPN-SSL e inicia la validación.
5.2 – El firewall le pregunta las credenciales de dominio y el OTP al usuario y éste se autentica.
5.3 – El firewall reenvía la autenticación del usuario al servidor Radius IAS o NPS integrado en Active Directory y éste acepta.
5.4 – El firewall reenvía la autenticación del token a un servidor freeradius con MultiOTP.
5.5 – Freeradius ejecuta el módulo MultiOTP y acepta 5.6 – El firewall acepta el túnel VPN con el cliente.
- 6- Instalación de Freeradius y MultiOTP
Partimos de un sistema Ubuntu Server 13.10 recién instalado. Ubuntu Server 13.10 incorpora un cliente ntp que sincroniza cuando arranca el sistema. Debemos confirmar que la hora del sistema es correcta ( para nuestra zona horaria ). 6.1 – Instalamos los paquetes
date
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install build-essential -y
sudo apt-get install freeradius freeradius-utils unzip apache2 php5 php5-gd ntp -y
6.2 – Paramos freeradius y verificamos ntp
sudo initctl stop freeradius
ntpq -p
6.3 – Descargamos y descomprimimos MultiOTP. Lo hacemos accesible via web para visualizar los códigos QR para aprovisionar soft tokens (opcional, pero mejor toma medidas de seguridad)
sudo mkdir /var/www/multiotp
sudo wget -O /var/www/multiotp/multiotp-4.0.7.zip 'http://files.sysco.ch/downloadfile.php?group=3&dir=public%2FmultiOTP&file=multiotp-4.0.7.zip'
cd /var/www/multiotp/
sudo unzip -q /var/www/multiotp/multiotp-4.0.7.zip
6.4 – Nos logamos como root:
sudo su -
6.5 Modificamos la configuración de Freeradius para permitir la autenticación mediante MultiOTP: 6.5.1 – Empezamos con el fichero /etc/freeradius/modules/multiotp Copiamos y pegamos directamente en el terminal:
cat > /etc/freeradius/modules/multiotp <<EOF exec multiotp { wait = yes input_pairs = request output_pairs = reply program = "/var/www/multiotp/multiotp.php %{User-Name} %{User-Password} -chap-challenge=%{CHAP-Challenge} -chap-password=%{CHAP-Password}" shell_escape = yes } EOF #
6.5.2 – Fichero /etc/freeradius/sistes-enabled/default Seguimos con el copy-paste sobre el terminal.
cp /etc/freeradius/sites-enabled/default /etc/freeradius/sites-enabled/default.bkp cat > /etc/freeradius/sites-enabled/default <<EOF authorize { preprocess mschap digest suffix eap { ok = return } files expiration logintime multiotp pap } authenticate { Auth-Type multiotp { multiotp } Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } digest unix eap } preacct { preprocess acct_unique suffix files } accounting { detail unix radutmp exec attr_filter.accounting_response } session { radutmp } post-auth { exec Post-Auth-Type REJECT { attr_filter.access_reject } } pre-proxy { } post-proxy { eap } EOF #
6.5.3 – Fichero /etc/freeradius/sites-enabled/inner-tunnel Seguimos con copy & paste :
cat > /etc/freeradius/sites-enabled/inner-tunnel <<EOF server inner-tunnel { listen { ipaddr = 127.0.0.1 port = 18120 type = auth } authorize { mschap suffix update control { Proxy-To-Realm := LOCAL } eap { ok = return } files expiration logintime multiotp pap } authenticate { Auth-Type multiotp { multiotp } Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } unix eap } session { radutmp } post-auth { Post-Auth-Type REJECT { attr_filter.access_reject } } pre-proxy { } post-proxy { eap } } EOF #
6.5.4 – Le toca al fichero policy.conf. Realizamos un backup y con el editor “vi” insertamos la configuración:
cp /etc/freeradius/policy.conf /etc/freeradius/policy.conf.bkp vi /etc/freeradius/policy.conf
Configuración de policy.conf:
policy { forbid_eap { if (EAP-Message) { reject } } permit_only_eap { if (!EAP-Message) { if (!"%{outer.request:EAP-Message}") { reject } } } deny_realms { if (User-Name =~ /@|\\/) { reject } } do_not_respond { update control { Response-Packet-Type := Do-Not-Respond } handled } filter_username { if (User-Name =~ /^ /) { reject } if (User-Name =~ / $$/) { reject } if (User-Name != "%{tolower:%{User-Name}}") { reject } } cui_authorize { update request { Chargeable-User-Identity:='\\000' } } cui_postauth { if (FreeRadius-Proxied-To == 127.0.0.1) { if (outer.request:Chargeable-User-Identity) { update outer.reply { Chargeable-User-Identity:="%{md5:%{config:cui_hash_key}%{User-Name}}" } } } else { if (Chargeable-User-Identity) { update reply { Chargeable-User-Identity="%{md5:%{config:cui_hash_key}%{User-Name}}" } } } } cui_updatedb { if (reply:Chargeable-User-Identity) { cui } } cui_accounting { if (!Chargeable-User-Identity) { update control { Chargable-User-Identity := "%{cui: SELECT cui FROM cui WHERE clientipaddress = '%{Client-IP-Address}' AND callingstationid = '%{Calling-Station-Id}' AND username = '%{User-Name}'}" } } if (Chargeable-User-Identity && (Chargeable-User-Identity != "")) { cui } } mac-addr = ([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2}) rewrite.called_station_id { if((Called-Station-Id) && "%{Called-Station-Id}" =~ /^%{config:policy.mac-addr}(:(.+))?$/i) { update request { Called-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}" } if ("%{8}") { update request { Called-Station-Id := "%{Called-Station-Id}:%{8}" } } updated } else { noop } } rewrite.calling_station_id { if((Calling-Station-Id) && "%{Calling-Station-Id}" =~ /^%{config:policy.mac-addr}$/i) { update request { Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}" } updated } else { noop } } multiotp.authorize { if (!control:Auth-Type) { update control { Auth-Type := multiotp } } } }
6.5.5 – El último fichero de configuración, vamos a por clients.conf:
En este caso está permitido realizar peticiones radius a any ( 0.0.0.0/0 ), pero por seguridad, acótalo a las ip’s de tus dispositivos de red.
cp /etc/freeradius/clients.conf /etc/freeradius/clients.conf.bkp
cat > /etc/freeradius/clients.conf <<EOF client localhost { ipaddr = 127.0.0.1 secret = 9UFvgA0eK5Veq8APSZC4 require_message_authenticator = no } client 0.0.0.0 { netmask = 0 secret = ZA35Qysrmd7p7Gy7QHXQ } EOF #
- 7 – Verificamos la configuración de Freeradius arrancándolo en modo debug.
root@ubuntu:~# freeradius -X
Deberíamos ver en pantalla las siguientes líneas del listener de freeradius en modo debug:
Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on authentication address 127.0.0.1 port 18120 as server inner-tunnel
Listening on proxy address * port 1814
Ready to process requests.
- 8 – Si ha ido bien, paramos con control+c y lanzamos el daemon:
root@ubuntu:~# initctl start freeradius
- 9 – Permisos de MultiOTP
Permitimos la ejecución de MultiOTP para la creación de usuarios y troubleshooting en terminal:
root@ubuntu:~# cd /var/www/multiotp root@ubuntu:/var/www/multiotp# chmod +x multiotp.php root@ubuntu:/var/www/multiotp# ./multiotp.php -config debug=1 root@ubuntu:/var/www/multiotp# ./multiotp.php -config display-log=1 19 INFO: Requested operation successfully done
- 10 – Creación de usuarios en MultiOTP:
En el siguiente ejemplo, crearemos un usuario “capa3”, que existe con ese sAMAccountName en el dominio de Active Directory, vinculado a un soft token TOTP. Crearemos un código QR que contendrá el seed. Visualizaremos los códigos de “rescate offline”, de un sólo uso, por si no tenemos acceso al soft token (ej. sin batería en el móvil)
cd /var/www/multiotp root@ubuntu:/var/www/multiotp# ./multiotp.php -fastcreate capa3 LOG 2013-12-01 22:30:40 (user capa3) Info: File created: ./users/capa3.db LOG 2013-12-01 22:30:40 (user capa3) Info: User capa3 successfully created and saved. LOG 2013-12-01 22:30:40 (user capa3) Info: user capa3 successfully created 11 INFO: User successfully created or updated root@ubuntu:/var/www/multiotp# ./multiotp.php -qrcode capa3 qrcode/capa3.png 16 INFO: QRcode successfully created root@ubuntu:/var/www/multiotp# ./multiotp.php -scratchlist capa3 328482 812658 073348 887919 320986 435986 964213 267638 985814 003773 19 INFO: Requested operation successfully done
Modificamos permisos para que freeradius funcione correctamente:
root@ubuntu:/var/www/multiotp# chown -R freerad:freerad users/* root@ubuntu:/var/www/multiotp# chmod 660 users/* root@ubuntu:/var/www/multiotp# chown freerad:freerad log/multiotp.log root@ubuntu:/var/www/multiotp# chmod 660 log/multiotp.log
- 11 – Instalación del token del usuario.
Visualizamos el código QR en el navegador yejecutamos Google Authenticator en el smartphone
Este código QR contiene el seed ( semilla ) del usuario que he creado en el ejemplo y tiene sentido en este sistema. En tu servidor, aunque uses el mismo usuario del ejemplo, el código QR debería ser diferente:
http://ip del servidor Freeradius-MultiOTP/multiotp/qrcode/capa3.png
Desde Google Authenticator escaneamos el código QR, se añadirá el seed y creará el soft token:
- 12 – Verificación de MultiOTP:
12.1 – Vamos a probar que el token funciona correctamente para el usuario “capa3”:
12.2 – Lanzamos radtest, cliente radius de terminal El password radius para localhost es 9UFvgA0eK5Veq8APSZC4 , ver clients.conf
root@ubuntu:~# radtest capa3 541938 localhost 1812 9UFvgA0eK5Veq8APSZC4 Sending Access-Request of id 38 to 127.0.0.1 port 1812 User-Name = "capa3" User-Password = "541938" NAS-IP-Address = 127.0.1.1 NAS-Port = 1812 Message-Authenticator = 0x00000000000000000000000000000000 rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=38, length=20
12.3 – Vamos a probar un scratch code de la lista de contraseñas de un sólo uso:
root@ubuntu:~# radtest capa3 328482 localhost 1812 9UFvgA0eK5Veq8APSZC4 Sending Access-Request of id 101 to 127.0.0.1 port 1812 User-Name = "capa3" User-Password = "328482" NAS-IP-Address = 127.0.1.1 NAS-Port = 1812 Message-Authenticator = 0x00000000000000000000000000000000 rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=101, length=20
12.4 – Los logs efectivamente muestran los accesos correctos y el uso del scratch code. 12.4.1 – Logs de MultiOTP:
root@ubuntu:~# tail /var/www/multiotp/log/multiotp.log ======================================== multiotp 4.0.7 Your script is running from /var/www/multiotp/ 2013-12-04 16:05:39 OK: user capa3 successfully logged in 2013-12-04 16:05:39 Info: 0 OK: Token accepted ======================================== multiotp 4.0.7 Your script is running from /var/www/multiotp/ 2013-12-04 16:06:17 OK: user capa3 successfully logged in with a scratch password 2013-12-04 16:06:17 Info: 0 OK: Token accepted
12.4.2 – Logs de Accounting de Freeradius en: /var/log/freeradius/radacct/-ip-del-firewall-vpn-/
root@ubuntu::~# cat /var/log/freeradius/radacct/192.168.5.1/detail-20131204
Wed Dec 4 23:39:27 2013
User-Name = "capa3"
NAS-Port = 90112
Service-Type = Framed-User
Framed-Protocol = PPP
Called-Station-Id = "80.xx.YY.ZZ"
Calling-Station-Id = "zz.zz.zz.zz"
Acct-Status-Type = Start
Acct-Delay-Time = 0
Acct-Session-Id = "EFA00001"
Acct-Authentic = RADIUS
NAS-Port-Type = Virtual
Tunnel-Client-Endpoint:0 = "xx.xx.xx.xx"
Vendor-3076-Attr-146 = 0x61646d696e732d76706e73736c
Vendor-3076-Attr-150 = 0x00000003
Vendor-3076-Attr-151 = 0x00000003
Vendor-3076-Attr-152 = 0x00000001
NAS-IP-Address = 192.168.5.1
Acct-Unique-Session-Id = "6cebde4b13006060"
Timestamp = 1386196767
- 13 – Configuración del Firewall Cisco ASA
En este escenario, la configuración vpn ssl ya está creada. Vamos a ver la configuración necesaria para que el perfil vpn tenga doble factor de autenticación. Así pues, veremos la configuración de los dos servidores radius y del tunnel-group correspondiente a un perfil vpn ssl existente. 13.1 radius
aaa-server radius-ias protocol radius aaa-server radius-ias (inside) host 192.168.5.3 key ***** authentication-port 1812 accounting-port 1813 no mschapv2-capable aaa-server radius-multiotp protocol radius aaa-server radius-multiotp (inside) host 192.168.5.141 retry-interval 4 key ZA35Qysrmd7p7Gy7QHXQ authentication-port 1812 accounting-port 1813 no mschapv2-capable
13.2 Tunnel-Group
tunnel-group perfil-vpnssl type remote-access tunnel-group perfil-vpnssl general-attributes authentication-server-group radius-ias secondary-authentication-server-group radius-multiotp use-primary-username accounting-server-group radius-multiotp default-group-policy perfil-vpnssl tunnel-group perfil-vpnssl webvpn-attributes proxy-auth sdi group-url https://vpn.capa3.es enable
- 14 – Conexión del cliente.
Ya hemos llegado al final y nos conectaremos a la VPN usando el cliente VPN SSL Cisco AnyConnect:
También podemos conectarnos sin cliente ( Clientless VPN ), usando un navegador:
6 Comments
Hello,
multiOTP 4.3.1.1 has been released in December 2014, with a lot of nice functionalities!
– YubiKeys (from Yubico) support
– Active Directory and regular LDAP server users synchronization (like Directory Server on Synology NAS)
– optimized Raspberry Pi edition (much faster than before, using cache, including for the command line implementation)
– and a lot more new functionalities…
Best regards,
Andre Liechti
Project leader for multiOTP open source
2015-03-18 22:36:44 warning capa3 User Error: authentication failed for user capa3
2015-03-18 22:36:44 warning capa3 User *(authentication typed by the user is 6 chars long instead of 10 chars)
este es el error que me da cuando trato de autenticar el usuario que podria faltar?
Hola,
Parece que has descargado una versión posterior de MultiOTP a la del ejemplo del post.
En las nuevas versiones de MultiOTP viene activado por defecto el prefix-pin y el autenticador espera los 4 dígitos del prefix-pin y el token code de 6 dígitos.
Para desactivarlo ejecuta multiotp.php con la siguiente opción:
multiotp.php -config default-request-prefix-pin=0
O bien modifica el fichero multiotp.ini del directorio “config” y configura la siguiente opción:
default_request_prefix_pin=0
Gracias por comentar.
Saludos,
Xavi
Tengo una consulta espero puedas ayudarme
He montado un servidor radius pero quisiera que los usuarios deban acceder sus credenciales a traves de una interfaz web y no atraves del gesto de red del SO que utilicen. Es posible esto ??? Saludos
(un ejemplo con las redes infinitum movil aca en mexico, que debes acceder a la direccion del gateway en el navegador para introducir usuario y contraseña y lograr el acceso)
Hola, en mi caso solamente funciona cuando pruebo con los códigos de rescate, pero cuando intento probar con Google Authenticator no funciona. Que puede estar fallando?
Gracias.
Hola,
primero disculpa que no haya contestado antes, no me activé alertas de cuándo hay un comentario pendiente…
Si sólo funcionan los códigos de rescate el problema apunta a que el token seed es incorrecto o la hora ( en cliente o servidor ) está mal. La respuesta correcta la verás en los logs de multiOTP.
Gracias por participar en el blog!