Freeradius + Google Authenticator + LDAP + Fortigate

Hvad skal man gøre, hvis man både vil have to-faktor-autentifikation og også gerne vil have det, men ikke har penge til hardware tokens, og man overhovedet får at vide, at man skal holde sig oppe med godt humør.

Denne løsning er ikke noget superoriginalt, snarere en blanding af forskellige løsninger, fundet på internettet.

Så, vi har:

Domæne Active Directory.

Brugere af domænet, der arbejder via VPN, som mange gør i dag.

VPN-gatewayen fungerer som: Fortigate.

At gemme adgangskoden til VPN-klienten er forbudt af sikkerhedspolitikken.

Politikken Fortinet med hensyn til egne tokens kan knap nok betegnes som grådig — der er hele 10 gratis tokens, de øvrige koster en meget høj pris. RSASecureID, Duo og lignende blev ikke overvejet, da der ønskes open source.

Forudsætninger: host *nix installeret med freeradius, sssd — er blevet tilføjet til domænet, domænebrugere kan autentificere sig problemfrit.

Supplerende pakker: shellinabox, figlet, freeradius-ldap, skrifttype rebel.tlf fra lageret. https://github.com/xero/figlet-fonts.

I mit eksempel — CentOS 7.8.

Logikken er sådan: ved tilslutning til VPN skal brugeren indtaste domænebrugernavn og OTP i stedet for adgangskoden.

Konfiguration af tjenester

I /etc/raddb/radiusd.conf ændres kun bruger og gruppe, under hvilke freeradiuskører, da tjenesten radiusd skal kunne læse filer i alle undermapper. /home/.

user = root
group = root

For at kunne bruge grupper i indstillingerne Fortigate, skal man videregive Vendor Specific Attribute. For dette i mappen raddb/policy.d opretter jeg en fil med følgende indhold:

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 af freeradius-ldap public/functions raddb/mods-available oprettes der en fil. ldap.

Der skal oprettes et symbolsk link i mappen raddb/mods-enabled..

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

Jeg tilpasser dens indhold til følgende:

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 og raddb/sites-enabled/inner-tunnel i sektionen authorize jeg tilføjer navnet på politikken, der skal bruges — group_authorization. Et vigtigt punkt — politiknavnet bestemmes ikke af filnavnet i mappen policy.d, men af direktivet inde i filen før de krøllede parenteser.
I sektionen authenticate i disse filer skal linjen afkommenteres pam.

I filen clients.conf vi angiver de parametre, som vil blive brugt til at forbinde 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

Standardimplementeringen af forbindelsen freeradius med google authenticator kræver, at brugeren indtaster legitimationsoplysninger i formatet: brugernavn/adgangskode+OTP.

Tænker på det antal forbandelser, der vil regne ned over hovedet, hvis standardkonfigurationen bruges freeradius med Google Authenticator, blev det besluttet at bruge modulkonfigurationen pam så kun token skal verificeres Google Authenticator.

Ved tilslutning af brugeren sker følgende:

  • Freeradius tjekker brugeren i domænet og i en bestemt gruppe, og hvis det lykkes, kontrolleres OTP token.

Alt så ganske lovende ud, indtil jeg kom til at tænke: «Hvordan registrerer jeg OTP for 300+ brugere?»

Brugeren skal logge ind på serveren med freeradius og fra sin konto og starte appen Google authenticator, som vil generere en QR-kode til brugeren. Her kommer shellinabox ind i billedet sammen med .bash_profile.

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

Konfigurationsfilen for dæmonen findes i /etc/sysconfig/shellinabox.
Jeg angiver port 443, og man kan angive sit eget certifikat.

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

Brugeren skal blot gå til linket, indtaste domænelegitimationsoplysninger og få QR-koden til appen.

Algoritmen er som følger:

  • Brugeren logger ind på maskinen via browseren.
  • Det kontrolleres, om brugeren er domænebruger. Hvis ikke, gøres der ikke noget.
  • Hvis brugeren er domænebruger, kontrolleres det, om vedkommende tilhører administratorgruppen.
  • Hvis ikke admin, kontrolleres det, om Google Authenticator er konfigureret. Hvis ikke, genereres der en QR-kode, og brugeren logges ud.
  • Hvis ikke admin og Google Authenticator er konfigureret, logges brugeren bare ud.
  • Hvis admin, kontrolleres Google Authenticator igen. Hvis ikke konfigureret, genereres der en QR-kode.

Hele logikken udføres med brug af /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 konfiguration:

  • Vi opretter Radius-server

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Opretter de nødvendige grupper for at opdele adgang, hvis det er nødvendigt. Gruppens navn skal Fortigate svare til den gruppe, der sendes i Vendor Specific Attribute Fortinet-Group-Name.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Rediger de nødvendige SSL-portaler.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Tilføj grupper til politikkerne.

    Freeradius + Google Authenticator + LDAP + Fortigate

Fordele ved denne løsning:

  • Der er mulighed for OTP-autentifikation med Fortigate en open source-løsning.
  • Brugen af det domænebaserede kodeord ved VPN-forbindelse er elimineret, hvilket forenkler tilslutningsprocessen. Det er lettere at indtaste en 6-cifret kode end den, der kræves af sikkerhedspolitikken. Som følge heraf reduceres antallet af supportanmodninger med emnet: 'Kan ikke oprette forbindelse til VPN'.

P.S. Planen er at forbedre denne løsning til en fuldgyldig to-faktor-autentifikation med challenge-response.

Opdatering:

Som lovet har jeg tilføjet en løsning med challenge-response.
Så:
I filen /etc/raddb/sites-enabled/default sektion authorize sådan ud:

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
}

Sektion authenticate har nu følgende form:

authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        mschap
        digest
        # Forsøg autentificering med en direkte LDAP bind:
        Auth-Type LDAP {
        ldap
        if (ok) {
            update reply {
                # Opret en tilfældig State-attribut:
                State := "%{randstr:aaaaaaaaaaaaaaaa}"
                Reply-Message := "Indtast venligst OTP"
                }
            # Returner Access-Challenge:
            challenge
            }
        }
        pam
        eap
}

Nu sker brugerens kontrol efter følgende algoritme:

  • Brugeren indtaster domænelegitimationerne i VPN-klienten.
  • Freeradius kontrollerer gyldigheden af brugerkontoen og adgangskoden.
  • Hvis adgangskoden er korrekt, sendes der en forespørgsel om token.
  • Der sker en kontrol af token.
  • Profit).

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster