Que faire si l'authentification à deux facteurs est souhaitée, mais que l'on n'a pas d'argent pour des tokens matériels et qu'on nous conseille simplement de rester de bonne humeur ?
Cette solution n'est pas quelque chose de super original, plutÎt un mélange de différentes solutions trouvées sur Internet.
Donc, voici les données
Domaine Active Directory.
Les utilisateurs de domaine qui travaillent via VPN, comme beaucoup aujourd'hui.
Agissant comme passerelle VPN Fortigate.
La sauvegarde du mot de passe pour le client VPN est interdite par la politique de sécurité.
La politique Fortinet concernant les tokens propres n'est pas moins que mesquine â il y a jusqu'Ă 10 tokens gratuits, les autres Ă un prix trĂšs peu avantageux. Je n'ai pas considĂ©rĂ© RSASecureID, Duo et similaires, car je prĂ©fĂšre l'open source.
Exigences prĂ©liminaires : hĂŽte *nix avec installĂ© freeradius, sssd â ajoutĂ© au domaine, les utilisateurs de domaine peuvent s'authentifier sans problĂšme.
Paquets supplémentaires : shellinabox, figlet, freeeradius-ldap, police rebel.tlf du dépÎt .
Dans mon exemple â CentOS 7.8.
La logique de fonctionnement est la suivante : lors de la connexion au VPN, l'utilisateur doit entrer son identifiant de domaine et OTP au lieu d'un mot de passe.
Configuration des services
Dans /etc/raddb/radiusd.conf seul l'utilisateur et le groupe à partir desquels commence freeradius, puisque le service radiusd doit pouvoir lire les fichiers dans tous les sous-répertoires /home/.
user = root
group = root
Pour pouvoir utiliser les groupes dans les paramÚtres Fortigate, il est nécessaire de passer Vendor Specific Attribute. Pour cela, dans le répertoire raddb/policy.d je crée un fichier avec le contenu suivant :
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 := "Bienvenue Admin"
}
}
else {
update reply {
&Reply-Message := "Non autorisé pour le vpn"
}
reject
}
}
AprÚs l'installation freeradius-ldap dans le répertoire raddb/mods-available un fichier est créé ldap.
Il faut créer un lien symbolique dans le répertoire raddb/mods-enabled.
ln -s /etc/raddb/mods-available/ldap /etc/raddb/mods-enabled/ldapJ'adapte son contenu comme suit :
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'
}
} Dans les fichiers raddb/sites-enabled/default et raddb/sites-enabled/inner-tunnel dans la section authorize j'ajoute le nom de la politique qui sera utilisĂ©e â group_authorization. Un point important â le nom de la politique n'est pas dĂ©fini par le nom du fichier dans le rĂ©pertoire policy.d, mais par la directive Ă l'intĂ©rieur du fichier avant les accolades.
Dans la section authenticate dans ces mĂȘmes fichiers, il faut dĂ©commenter la ligne pam.
Dans le fichier clients.conf nous décrivons les paramÚtres avec lesquels il se connectera Fortigate:
client fortigate {
ipaddr = 192.168.1.200
secret = testing123
require_message_authenticator = no
nas_type = other
}
Configuration du module 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
Les options par défaut d'implémentation du lien freeradius avec google authenticator supposent que l'utilisateur entre ses informations d'identification au format : nom d'utilisateur/mot de passe+OTP.
En considĂ©rant le nombre de malĂ©dictions qui tomberaient sur ma tĂȘte en utilisant le lien par dĂ©faut freeradius avec Google Authenticator, il a Ă©tĂ© dĂ©cidĂ© d'utiliser la configuration du module pam de sorte Ă vĂ©rifier uniquement le token Google Authenticator.
Lors de la connexion de l'utilisateur, il se passe ce qui suit :
- Freeradius vérifie la présence de l'utilisateur dans le domaine et dans un groupe spécifique et, en cas de succÚs, procÚde à la vérification du token OTP.
Tout semblait relativement bien jusqu'au moment oĂč je me suis demandĂ© « Comment enregistrer l'OTP pour plus de 300 utilisateurs ? »
L'utilisateur doit se connecter sur le serveur avec freeradius et sous son compte et lancer l'application Google authenticator, qui génÚre pour l'utilisateur un code QR pour l'application. C'est ici qu'intervient shellinabox en combinaison avec .bash_profile.
[root@freeradius ~]# yum install -y shellinabox
Le fichier de configuration du démon se trouve dans /etc/sysconfig/shellinabox.
J'indique le port 443 là -bas et je peux spécifier mon certificat.
[root@freeradius ~]#systemctl enable --now shellinaboxdL'utilisateur n'a plus qu'Ă se rendre Ă l'adresse, entrer les identifiants de domaine et obtenir le code QR pour l'application.
L'algorithme est le suivant :
- L'utilisateur se connecte Ă la machine via le navigateur.
- Vérifie si l'utilisateur est de domaine. Si non, aucune action n'est entreprise.
- Si l'utilisateur est de domaine, il vérifie l'appartenance au groupe des administrateurs.
- S'il n'est pas admin, il vérifie si Google Authenticator est configuré. Si ce n'est pas le cas, un code QR est généré et l'utilisateur est déconnecté.
- S'il n'est pas admin et que Google Authenticator est configuré, il est simplement déconnecté.
- S'il est admin, alors on vérifie encore Google Authenticator. S'il n'est pas configuré, un code QR est généré.
Toute la logique s'exécute en utilisant /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
Configuration de Fortigate :
- Créons Radius-serveur

- Nous créons les groupes nécessaires, en cas de besoin de limiter l'accÚs par groupes. Le nom du groupe pour Fortigate doit correspondre au groupe qui est transmis à Vendor Specific Attribute Fortinet-Group-Name.

- Nous modifions les nécessaires SSL-portails.

- Nous ajoutons des groupes aux politiques.

Avantages de cette solution :
- Il est possible de s'authentifier par OTP sur Fortigate une solution open-source.
- L'utilisateur n'a pas besoin de saisir le mot de passe de domaine lors de la connexion via VPN, ce qui simplifie un peu le processus de connexion. Il est plus facile de saisir un mot de passe à six chiffres que celui prévu par la politique de sécurité. En conséquence, le nombre de tickets avec le sujet : « Je ne peux pas me connecter au VPN » diminue.
P.S. Nous prévoyons d'affiner cette solution pour l'authentification à deux facteurs complÚte avec challenge-response.
Mise Ă jour :
Comme promis, je l'ai effectivement affiné avec une option challenge-response.
Donc :
Dans le fichier /etc/raddb/sites-enabled/default section authorize se présente comme suit :
authorize {
filter_username
preprocess
auth_log
chap
mschap
suffix
eap {
ok = return
}
files
-sql
#-ldap
expiration
logintime
if (!State) {
if (&User-Password) {
# Si !State et User-Password (PAP), alors forcer LDAP :
update control {
Ldap-UserDN := "%{User-Name}"
Auth-Type := LDAP
}
}
else {
reject
}
}
else {
# Si State, alors proxy request :
group_authorization
}
pap
}
Section authenticate a maintenant l'apparence suivante :
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
mschap
digest
# Essayer l'authentification avec une liaison LDAP directe :
Auth-Type LDAP {
ldap
if (ok) {
update reply {
# Créer un attribut State aléatoire :
State := "%{randstr:aaaaaaaaaaaaaaaa}"
Reply-Message := "Veuillez entrer l'OTP"
}
# Retourner Access-Challenge :
challenge
}
}
pam
eap
}
La vérification de l'utilisateur se fait maintenant selon l'algorithme suivant :
- L'utilisateur entre les identifiants de domaine dans le client VPN.
- Freeradius vérifie la validité du compte et du mot de passe
- Si le mot de passe est correct, une demande de jeton est envoyée.
- La vérification du jeton a lieu.
- Profit).
Source : habr.com




