Freeradius + Google Authenticator + LDAP + Fortigate

Co dělat, pokud je dvoufaktorová autentizace nutná, ale nemáme peníze na hardwarové tokeny, a vůbec, snažíme se mít dobrou náladu.

Toto řešení není nijak originální, spíše je to mix různých řešení nalezených na internetu.

Takže, dáno

Doména Active Directory.

Uživatelé domény, kteří pracují přes VPN, jak je nyní běžné.

VPN bránu zastává Fortigate.

Uložení hesla pro VPN klienta je zakázáno bezpečnostní politikou.

Politiku Fortinet ohledně vlastních tokenů nelze nazvat jinak než velkorysou — zdarma je 10 tokenů, ostatní za opravdu vysokou cenu. RSASecureID, Duo a podobné jsem nezvažoval, protože chci open-source.

Požadavky: host *nix s nainstalovaným freeradius, sssd — přidán do domény, doménoví uživatelé se na něm mohou bez problémů autentizovat.

Další balíčky: shellinabox, figlet, freeeradius-ldap, font rebel.tlf z repozitáře https://github.com/xero/figlet-fonts.

V mém příkladu — CentOS 7.8.

Logika fungování je následující: při připojení k VPN musí uživatel zadat doménové přihlašovací údaje a OTP místo hesla.

Nastavení služeb

V /etc/raddb/radiusd.conf se mění pouze uživatel a skupina, pod kterými služba startuje freeradius, protože služba radiusd musí mít možnost číst soubory ve všech podadresářích /home/.

user = root
group = root

Aby bylo možné používat skupiny v nastavení Fortigate, je třeba předat Vendor Specific Attribute. K tomu v adresáři raddb/policy.d vytvořím soubor se následujícím obsahem:

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 := "Vítejte Admin"
                }
        }
    else {
        update reply {
        &Reply-Message := "Není autorizováno pro vpn"
            }
        reject
        }
}

Po instalaci freeradius-ldap v adresáři raddb/mods-available se vytvoří soubor ldap.

Je třeba vytvořit symbolický odkaz v adresáři raddb/mods-enabled.

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

Upravuji jeho obsah na následující:

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

V souborech raddb/sites-enabled/default a raddb/sites-enabled/inner-tunnel v sekci authorize přidávám název politiky, která se bude používat — group_authorization. Důležitý bod — název politiky se určuje nikoli podle názvu souboru ve složce policy.d, ale podle direktivy uvnitř souboru před složenými závorkami.
V sekci authenticate v těchto souborech je nutné odkomentovat řádek pam.

V souboru clients.conf zapisujeme parametry, s kterými se bude připojovat Fortigate:

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

Konfigurace modulu 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

Výchozí možnosti implementace kombinace freeradius s google authenticator předpokládají, že uživatel zadá přihlašovací údaje ve formátu: uživatelské jméno/heslo+OTP.

S ohledem na množství nadávek, které by na mě dopadly v případě použití výchozí kombinace freeradius s Google Authenticator, bylo rozhodnuto použít konfiguraci modulu pam tak, aby se kontroloval pouze token Google Authenticator.

Při připojení uživatele dochází k následujícímu:

  • Freeradius kontroluje přítomnost uživatele v doméně a v určité skupině a v případě úspěchu probíhá kontrola OTP tokenu.

Všechno vypadalo dost dobře, dokud jsem se nezamyslel: „Jak provést registraci OTP pro více než 300 uživatelů?“

Uživatel se musí přihlásit na server s freeradius a pod svým uživatelským účtem spustit aplikaci Google authenticator, která vygeneruje pro uživatele QR kód pro aplikaci. A zde přichází na pomoc shellinabox v kombinaci s .bash_profile.

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

Konfigurační soubor démona se nachází v /etc/sysconfig/shellinabox.
Uvádím tam port 443 a mohu uvést svůj certifikát.

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

Uživatel by se měl pouze přihlásit na odkazu, zadat doménové údaje a získat QR kód pro aplikaci.

Algoritmus je následující:

  • Uživatel se přihlásí na stroj přes prohlížeč.
  • Ověřuje se, zda je uživatel doménový. Pokud ne, není podniknuto žádné opatření.
  • Pokud je uživatel doménový, kontroluje se příslušnost ke skupině administrátorů.
  • Pokud není admin, zkontroluje se, zda je nastaven Google Authenticator. Pokud ne, generuje se QR kód a uživatel se odhlašuje.
  • Pokud není admin a Google Authenticator je nastaven, odhlásí se jednoduše.
  • Pokud je admin, opět se kontroluje Google Authenticator. Pokud není nastaven, generuje se QR kód.

Veškerá logika se provádí pomocí /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

Nastavení Fortigate:

  • Vytváříme Radius-server

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Vytváříme potřebné skupiny, v případě potřeby rozdělení přístupu podle skupin. Název skupiny na Fortigate musí odpovídat skupině, která je předávána v Vendor Specific Attribute Fortinet-Group-Name.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Upravujeme potřebné SSL-portály.

    Freeradius + Google Authenticator + LDAP + Fortigate

  • Přidáváme skupiny do politik.

    Freeradius + Google Authenticator + LDAP + Fortigate

Výhody tohoto řešení:

  • Je možná autentizace pomocí OTP na Fortigate open-source řešení.
  • Uživatelský doménový heslo není nutné zadávat při připojení přes VPN, což poněkud usnadňuje proces připojení. Šestimístné heslo je snadnější zadat než to, které je dáno politikou zabezpečení. V důsledku toho se snižuje počet tiketů na téma: 'Nemohu se připojit k VPN'.

P.S. Plánuji toto řešení přetvořit na plnohodnotnou dvoufaktorovou autorizaci s challenge-response.

Update:

Jak jsem slíbil, přetvořil jsem na variantu s challenge-response.
Takže:
V souboru /etc/raddb/sites-enabled/default sekce authorize vypadat následovně:

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

Sekce authenticate nyní má následující podobu:

authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        mschap
        digest
        # Pokus o autentizaci s přímým LDAP bind:
        Auth-Type LDAP {
        ldap
        if (ok) {
            update reply {
                # Vytvořit náhodný atribut State:
                State := "%{randstr:aaaaaaaaaaaaaaaa}"
                Reply-Message := "Zadejte OTP"
                }
            # Vrátit Access-Challenge:
            challenge
            }
        }
        pam
        eap
}

Nyní se kontrola uživatele provádí podle následujícího algoritmu:

  • Uživatel zadává doménové kredity v VPN klientovi.
  • Freeradius kontroluje platnost účtu a hesla.
  • Pokud je heslo správné, odešle se požadavek na token.
  • Probíhá kontrola tokenu.
  • Profit).

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster