Freeradius + Google Authenticator + LDAP + Fortigate

¿Qué hacer si se quiere y se necesita la autenticación de dos factores, pero no hay dinero para tokens hardware y, en general, se sugiere mantenerse optimista?

Esta solución no es nada superoriginal, más bien es una mezcla de diferentes soluciones encontradas en Internet.

Así que, dado

Dominio Active Directory.

Los usuarios del dominio que trabajan a través de VPN, como muchos hoy en día.

Actuando como una puerta de enlace VPN está Fortigate.

Guardar la contraseña para el cliente VPN está prohibido por la política de seguridad.

La política Fortinet en cuanto a sus propios tokens no se puede considerar menos que codiciosa: ¡hay hasta 10 tokens gratuitos, los demás a un precio muy poco kosher! No consideré RSASecureID, Duo y similares, porque prefiero soluciones de código abierto.

Requisitos previos: host *nix con instalado freeradius, sssd — incluido en el dominio, los usuarios del dominio pueden autenticar sin problemas en él.

Paquetes adicionales: shellinabox, figlet, freeeradius-ldap, fuente rebel.tlf del repositorio https://github.com/xero/figlet-fonts.

En mi ejemplo: CentOS 7.8.

La lógica de funcionamiento es la siguiente: al conectarse a la VPN, el usuario debe introducir su nombre de usuario del dominio y la OTP en lugar de la contraseña.

Configuración de servicios

En /etc/raddb/radiusd.conf solo cambian el usuario y el grupo bajo los cuales se inicia freeradius, ya que el servicio radiusd debe poder leer archivos en todos los subdirectorios /home/.

user = root
group = root

Para que se puedan utilizar grupos en la configuración Fortigate, hay que pasar Vendor Specific Attribute. Para ello, en el directorio raddb/policy.d creo un archivo con el siguiente contenido:

group_authorization {
    if (&LDAP-Group[*] == "CN=vpn_admins,OU=vpn-groups,DC=domain,DC=local") {
            update reply {
                &Fortinet-Group-Name = "vpn_admins" }
            update control {
                &Auth-Type := PAM
                &Reply-Message := "Bienvenido Administrador"
                }
        }
    else {
        update reply {
        &Reply-Message := "No autorizado para vpn"
            }
        reject
        }
}

Después de la instalación freeradius-ldap en el directorio raddb/mods-available se crea un archivo ldap.

Hay que crear un enlace simbólico en el directorio raddb/mods-enabled.

ln -s /etc/raddb/mods-available/ldap /etc/raddb/mods-enabled/ldap

La traigo a esta forma:

ldap {
        server = 'domain.local'
        identity = 'CN=freerad_user,OU=users,DC=domain,DC=local'
        password = "SupeSecretP@ssword"
        base_dn = 'dc=domain,dc=local'
        sasl {
        }
        user {
                base_dn = "${..base_dn}"
                filter = "(sAMAccountname=%{%{Stripped-User-Name}:-%{User-Name}})"
                sasl {
                }
                scope = 'sub'
        }
        group {
                base_dn = "${..base_dn}"
                filter = '(objectClass=Group)'
                scope = 'sub'
                name_attribute = cn
                membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
                membership_attribute = 'memberOf'
        }
}

En los archivos raddb/sites-enabled/default y raddb/sites-enabled/inner-tunnel en la sección autorizar estoy agregando el nombre de la política que se utilizará — group_authorization. Un punto importante — el nombre de la política no se determina por el nombre del archivo en el directorio policy.d, sino por la directiva dentro del archivo antes de las llaves.
En la sección autenticar en estos mismos archivos, es necesario descomentar la línea pam.

En el archivo clients.conf especificamos los parámetros con los que se conectará Fortigate:

cliente fortigate {
    ipaddr = 192.168.1.200
    secret = testing123
    require_message_authenticator = no
    nas_type = other
}

Configuración del módulo pam.d/radiusd:

#%PAM-1.0
auth       sufficient   pam_google_authenticator.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
session    include      password-auth

Las opciones predeterminadas para la implementación de la combinación freeradius con google authenticator suponen que el usuario ingrese sus credenciales en el formato: usuario/contraseña+OTP.

Teniendo en cuenta la cantidad de maldiciones que caerán sobre mí en caso de usar la combinación predeterminada freeradius con Google Authenticator, se tomó la decisión de utilizar la configuración del módulo pam para verificar solo el token Google Authenticator.

Al conectar al usuario sucede lo siguiente:

  • Freeradius verifica la existencia del usuario en el dominio y en un grupo específico y, si tiene éxito, verifica el token OTP.

Todo parecía bastante bien hasta que me pregunté «¿Cómo registrar OTP para más de 300 usuarios?»

El usuario debe iniciar sesión en el servidor con freeradius y desde su cuenta e iniciar la aplicación Google authenticator, que generará un código QR para el usuario. Aquí es donde entra en juego shellinabox en combinación con .bash_profile.

[root@freeradius ~]# yum install -y shellinabox

El archivo de configuración del demonio se encuentra en /etc/sysconfig/shellinabox.
Indico el puerto 443 y puedo especificar mi certificado.

[root@freeradius ~]#systemctl enable --now shellinaboxd

El usuario solo necesita acceder al enlace, ingresar las credenciales del dominio y recibir el código QR para la aplicación.

El algoritmo es el siguiente:

  • El usuario inicia sesión en la máquina a través del navegador.
  • Se verifica si el usuario es del dominio. Si no lo es, no se realizan acciones.
  • Si el usuario es del dominio, se verifica la pertenencia al grupo de administradores.
  • Si no es administrador, se verifica si Google Authenticator está configurado. Si no, se genera un código QR y se cierra sesión del usuario.
  • Si no es administrador y Google Authenticator está configurado, simplemente se cierra sesión.
  • Si es administrador, de nuevo se verifica Google Authenticator. Si no está configurado, se genera un código QR.

Toda la lógica se ejecuta utilizando /etc/skel/.bash_profile.

cat /etc/skel/.bash_profile

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs
# Make several commands available from user shell

if [[ -z $(id $USER | grep "admins") || -z $(cat /etc/passwd | grep $USER) ]]
  then
    [[ ! -d $HOME/bin ]] && mkdir $HOME/bin
    [[ ! -f $HOME/bin/id ]] && ln -s /usr/bin/id $HOME/bin/id
    [[ ! -f $HOME/bin/google-auth ]] && ln -s /usr/bin/google-authenticator $HOME/bin/google-auth
    [[ ! -f $HOME/bin/grep ]] && ln -s /usr/bin/grep $HOME/bin/grep
    [[ ! -f $HOME/bin/figlet ]] && ln -s /usr/bin/figlet $HOME/bin/figlet
    [[ ! -f $HOME/bin/rebel.tlf ]] && ln -s /usr/share/figlet/rebel.tlf $HOME/bin/rebel.tlf
    [[ ! -f $HOME/bin/sleep ]] && ln -s /usr/bin/sleep $HOME/bin/sleep
  # Set PATH env to <home user directory>/bin
    PATH=$HOME/bin
    export PATH
  else
    PATH=PATH=$PATH:$HOME/.local/bin:$HOME/bin
    export PATH
fi


if [[ -n $(id $USER | grep "domain users") ]]
  then
    if [[ ! -e $HOME/.google_authenticator ]]
      then
        if [[ -n $(id $USER | grep "admins") ]]
          then
            figlet -t -f $HOME/bin/rebel.tlf "Welcome to Company GAuth setup portal"
            sleep 1.5
            echo "Please, run any of these software on your device, where you would like to setup OTP:
Google Autheticator:
AppStore - https://apps.apple.com/us/app/google-authenticator/id388497605
Play Market - https://play.google.com/stor/apps/details?id=com.google.android.apps.authenticator2&hl=en
FreeOTP:
AppStore - https://apps.apple.com/us/app/freeotp-authenticator/id872559395
Play Market - https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en

And prepare to scan QR code.

"
            sleep 5
            google-auth -f -t -w 3 -r 3 -R 30 -d -e 1
            echo "Congratulations, now you can use an OTP token from application as a password connecting to VPN."
          else
            figlet -t -f $HOME/bin/rebel.tlf "Welcome to Company GAuth setup portal"
            sleep 1.5
            echo "Please, run any of these software on your device, where you would like to setup OTP:
Google Autheticator:
AppStore - https://apps.apple.com/us/app/google-authenticator/id388497605
Play Market - https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en
FreeOTP:
AppStore - https://apps.apple.com/us/app/freeotp-authenticator/id872559395
Play Market - https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en

And prepare to scan QR code.

"
            sleep 5
            google-auth -f -t -w 3 -r 3 -R 30 -d -e 1
            echo "Congratulations, now you can use an OTP token from application as a password to VPN."
            logout
        fi
      else
        echo "You have already setup a Google Authenticator"
        if [[ -z $(id $USER | grep "admins") ]]
          then
          logout
        fi
    fi
  else
    echo "You don't need to set up a Google Authenticator"
fi

Configuración de Fortigate:

  • Creamos Radio-servidor

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Creando los grupos necesarios, en caso de ser necesario restringir el acceso por grupos. El nombre del grupo en Fortigate debe coincidir con el grupo que se transmite en Vendor Specific Attribute Fortinet-Group-Name.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Editando los necesarios SSL-portales.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Añadiendo grupos a las políticas.

    Freeradius + Google Authenticator + LDAP + Fortigate

Ventajas de esta solución:

  • Hay posibilidad de autenticación por OTP en Fortigate una solución de código abierto.
  • Se elimina la necesidad de que el usuario ingrese la contraseña de dominio al conectarse por VPN, lo que simplifica un poco el proceso de conexión. Es más fácil ingresar una contraseña de 6 dígitos que la prevista por la política de seguridad. Como consecuencia, se reduce el número de tickets con el tema: 'No puedo conectarme a la VPN'.

P.D. Planeo mejorar esta solución para que sea una autenticación de dos factores completa con challenge-response.

Update:

Como prometí, finalmente lo mejoré a la opción con challenge-response.
Así que:
En el archivo /etc/raddb/sites-enabled/default sección autorizar se ve de la siguiente manera:

authorize {
    filter_username
    preprocess
    auth_log
    chap
    mschap
    suffix
    eap {
        ok = return
    }
    files
    -sql
    #-ldap
    expiration
    logintime
    if (!State) {
        if (&User-Password) {
            # Si !State y User-Password (PAP), forzar LDAP:
            update control {
                Ldap-UserDN := "%{User-Name}"
                Auth-Type := LDAP
            }
        }
        else {
            reject
        }
    }
    else {
        # Si State, entonces proxy request:
        group_authorization
    }
pap
}

Sección autenticar ahora tiene la siguiente forma:

authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        mschap
        digest
        # Intentar autenticación con un enlace LDAP directo:
        Auth-Type LDAP {
        ldap
        if (ok) {
            update reply {
                # Crear un atributo de Estado aleatorio:
                State := "%{randstr:aaaaaaaaaaaaaaaa}"
                Reply-Message := "Por favor, ingrese OTP"
                }
            # Devolver Access-Challenge:
            challenge
            }
        }
        pam
        eap
}

Ahora la verificación del usuario se realiza según el siguiente algoritmo:

  • El usuario ingresa las credenciales de dominio en el cliente VPN.
  • Freeradius verifica la validez de la cuenta y la contraseña.
  • Si la contraseña es correcta, se envía una solicitud de token.
  • Se realiza la verificación del token.
  • ¡Beneficio!).

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster