Freeradius + Google Authenticator + LDAP + Fortigate

Tänk om tvåfaktorsautentisering är både önskvärt och taggigt, men det finns inga pengar för hårdvarutokens och i allmänhet erbjuder de sig att hålla sig på gott humör.

Denna lösning är inget superoriginal, utan snarare en blandning av olika lösningar som finns på Internet.

Så givet

Домен Active Directory.

Domänanvändare som arbetar via ett VPN, som många idag.

Fungerar som en VPN-gateway Fortigate.

Att spara lösenordet för VPN-klienten är förbjudet enligt säkerhetspolicy.

Politik Fortinet När det gäller dina egna tokens, kan du inte kalla det mindre än en zhlob - det finns så många som 10 gratis tokens, resten - till ett mycket icke-kosher pris. Jag övervägde inte RSASecureID, Duo och liknande, eftersom jag vill ha öppen källkod.

Förutsättningar: värd * nix med etablerade freeradius, ssd - när de har skrivits in i domänen kan domänanvändare enkelt autentisera sig på den.

Ytterligare paket: shellina låda, fikling, freeradius-ldap, teckensnitt rebel.tlf från förvaret https://github.com/xero/figlet-fonts.

I mitt exempel - CentOS 7.8.

Arbetets logik är tänkt att vara följande: när användaren ansluter till ett VPN måste användaren ange en domäninloggning och OTP istället för ett lösenord.

Inställning av tjänster

В /etc/raddb/radiusd.conf endast användaren och gruppen som startar freeradius, sedan tjänsten radiusd ska kunna läsa filer i alla underkataloger /Hem/.

user = root
group = root

För att kunna använda grupper i inställningar Fortigate, måste överföras Leverantörsspecifikt attribut. För att göra detta, i katalogen raddb/policy.d Jag skapar en fil med följande innehåll:

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 := "Welcome Admin"
                }
        }
    else {
        update reply {
        &Reply-Message := "Not authorized for vpn"
            }
        reject
        }
}

Efter installationen freeradius-ldap i katalogen raddb/mods-tillgänglig filen skapas ldap.

Behöver skapa en symbolisk länk till katalogen raddb/mods-aktiverad.

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

Jag tar med dess innehåll till denna form:

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'
        }
}

I filer raddb/sites-enabled/default и raddb/sites-enabled/inner-tunnel i avsnitt godkänna Jag lägger till namnet på policyn som ska användas - group_authorization. En viktig punkt - namnet på policyn bestäms inte av namnet på filen i katalogen policy.d, men genom ett direktiv inuti filen före de lockiga hängslen.
I avsnittet autentisera i samma filer måste du avkommentera raden pam.

I fil clients.conf föreskriva parametrarna som den ska anslutas till Fortigate:

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

Modulkonfiguration 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

Standardimplementeringsalternativ för paket freeradius с google autentiserare kräva att användaren anger inloggningsuppgifter i formatet: användarnamn Lösenord+OTP.

Genom att föreställa sig antalet förbannelser som kommer att falla på huvudet, i fallet med att använda standardpaketet freeradius с Google Authenticator, beslutades det att använda modulkonfigurationen pam så att endast token kan kontrolleras Google Authenticator.

När en användare ansluter händer följande:

  • Freeradius kontrollerar om användaren finns i domänen och i en viss grupp och, om det lyckas, kontrolleras OTP-token.

Allt såg tillräckligt bra ut tills jag tänkte "Hur kan jag registrera OTP för 300+ användare?"

Användaren måste logga in på servern med freeradius och från under ditt konto och kör programmet Googles autentiserare, som kommer att generera en QR-kod för applikationen för användaren. Det är här hjälpen kommer in. shellina låda i kombination med .bash_profile.

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

Demonens konfigurationsfil finns på /etc/sysconfig/shellinabox.
Jag anger port 443 där och du kan ange ditt certifikat.

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

Användaren behöver bara följa länken, ange domänkrediter och få en QR-kod för applikationen.

Algoritmen är följande:

  • Användaren loggar in på maskinen via en webbläsare.
  • Om domänanvändaren är markerad. Om inte, vidtas inga åtgärder.
  • Om användaren är en domänanvändare är medlemskap i gruppen Administratörer markerat.
  • Om den inte är administratör kontrollerar den om Google Authenticator är konfigurerad. Om inte, genereras en QR-kod och användarutloggning.
  • Om inte en administratör och Google Authenticator är konfigurerad, logga bara ut.
  • Om administratör, kontrollera sedan Google Authenticator igen. Om den inte är konfigurerad genereras en QR-kod.

All logik görs med hjälp av /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

Fortigate setup:

  • Vi skapar Radie-server

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Vi skapar de nödvändiga grupperna, vid behov åtkomstkontroll av grupper. Gruppnamn på Fortigate måste matcha gruppen som skickas in Leverantörsspecifikt attribut Fortinet-Grupp-namn.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Redigera det nödvändiga SSL-portaler.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Lägga till grupper i policyer.

    Freeradius + Google Authenticator + LDAP + Fortigate

Fördelarna med denna lösning:

  • Det är möjligt att autentisera med OTP på Fortigate öppen källkodslösning.
  • Användaren anger inte ett domänlösenord vid anslutning via VPN, vilket förenklar anslutningsprocessen något. Det 6-siffriga lösenordet är lättare att ange än det som tillhandahålls av säkerhetspolicyn. Som ett resultat minskar antalet biljetter med ämnet: "Jag kan inte ansluta till VPN".

PS Vi planerar att uppgradera den här lösningen till en fullfjädrad tvåfaktorsautentisering med utmaningssvar.

Uppdatering:

Som utlovat anpassade jag det till alternativet utmaning-svar.
Så:
I fil /etc/raddb/sites-enabled/default avsnitt godkänna är som följer:

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

avsnitt autentisera ser nu ut så här:

authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        mschap
        digest
        # Attempt authentication with a direct LDAP bind:
        Auth-Type LDAP {
        ldap
        if (ok) {
            update reply {
                # Create a random State attribute:
                State := "%{randstr:aaaaaaaaaaaaaaaa}"
                Reply-Message := "Please enter OTP"
                }
            # Return Access-Challenge:
            challenge
            }
        }
        pam
        eap
}

Nu sker användarverifiering enligt följande algoritm:

  • Användaren anger domänkrediter i VPN-klienten.
  • Freeradius kontrollerar giltigheten av kontot och lösenordet
  • Om lösenordet är korrekt skickas en begäran om en token.
  • Tokenet håller på att verifieras.
  • vinst).

Källa: will.com

Lägg en kommentar