Cette solution n'est pas quelque chose de super original, mais plutôt un mélange de différentes solutions trouvées sur Internet.
Donc, étant donné
Domaine Active Directory .
Les utilisateurs de domaine utilisant un VPN, comme beaucoup aujourd'hui. Fortigate
agit comme une passerelle VPN . L'enregistrement du mot de passe pour le client VPN est interdit par la politique de sécurité. La politique de Fortinet concernant ses propres jetons ne peut pas être appelée moins que redneck - il y a déjà 10 jetons gratuits, le reste est à un prix très non casher. RSASecureID, Duo et autres n'ont pas été pris en compte, car je veux de l'open source. Prérequis: * hôte nix avec freeradius installé , sssd - entré dans le domaine, les utilisateurs du domaine peuvent facilement s'authentifier dessus. Forfaits supplémentaires:
police shellinabox , figlet , freeeradius-ldap , rebel.tlf du référentiel https://github.com/xero/figlet-fonts .
Dans mon exemple - CentOS 7.8.
La logique de travail est la suivante: lors de la connexion Ă un VPN, un utilisateur doit saisir un login de domaine et un OTP au lieu d'un mot de passe.
Mise en place de services
Dans /etc/raddb/radiusd.conf, seuls l'utilisateur et le groupe sous lesquels freeradius démarre , sont modifiés , car le service radiusd doit pouvoir lire les fichiers dans tous les sous-répertoires de / home / .
user = root
group = root
Pour pouvoir utiliser des groupes dans les paramètres Fortigate , vous devez transmettre l' attribut spécifique au fournisseur . Pour ce faire, dans le répertoire raddb / policy.d, créez 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 := "Welcome Admin"
}
}
else {
update reply {
&Reply-Message := "Not authorized for vpn"
}
reject
}
}
Après avoir installé freeradius-ldap dans le répertoire raddb / mods-available, le fichier ldap .
Vous devez créer un lien symbolique vers le répertoire raddb / mods-enabled .
ln -s /etc/raddb/mods-available/ldap /etc/raddb/mods-enabled/ldap
J'apporte son contenu Ă ce formulaire:
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 stratégie n'est pas déterminé 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 authentifier des mêmes fichiers, décommentez le fichier pam .
Dans le fichier clients.conf, écrivez les paramètres avec lesquels Fortigate se connectera :
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 pour la mise en œuvre du bundle freeradius avec l' authentificateur google impliquent que l'utilisateur saisisse les informations d'identification au format: nom d'utilisateur / mot de passe + OTP .
Après avoir présenté le nombre de malédictions qui vous tomberont sur la tête, dans le cas de l'utilisation du bundle freeradius par défaut avec Google Authenticator , il a été décidé d'utiliser la configuration du module pam afin de ne vérifier que le token Google Authenticator .
Lorsqu'un utilisateur se connecte, ce qui suit se produit:
- Freeradius vérifie la présence de l'utilisateur dans le domaine et dans un groupe spécifique et, en cas de succès, vérifie le jeton OTP.
Tout semblait assez bien jusqu'Ă ce que je me dise: "Comment puis-je enregistrer OTP pour plus de 300 utilisateurs?"
L'utilisateur doit se connecter au serveur avec freeradius et sous son compte et exécuter l'application d' authentification Google , qui générera un code QR pour l'application pour l'utilisateur. C'est là que shellinabox est utile 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 vous pouvez spécifier votre certificat.
[root@freeradius ~]#systemctl enable --now shellinaboxd
L'utilisateur n'a qu'à suivre le lien, saisir les crédits du domaine et recevoir le code QR de l'application.
L'algorithme est le suivant:
- L'utilisateur se connecte Ă la machine via un navigateur.
- L'utilisateur du domaine est vérifié. Sinon, aucune action n'est entreprise.
- Si l'utilisateur est un utilisateur de domaine, l'appartenance au groupe Administrateurs est vérifiée.
- S'il n'est pas administrateur, il vérifie si Google Autheticator est configuré. Sinon, un code QR et une déconnexion de l'utilisateur sont générés.
- Si ce n'est pas un administrateur et que Google Authenticator est configuré, déconnectez-vous simplement.
- Si l'administrateur, vérifiez à nouveau Google Authenticator. S'il n'est pas configuré, un code QR est généré.
Toute la logique se fait 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éer un serveur Radius
- Nous créons les groupes nécessaires, si nécessaire, différencions l'accès par groupes. Le nom du groupe sur Fortigate doit correspondre au groupe qui est passé dans l' attribut spécifique du fournisseur Fortinet-Group-Name .
- Modification des portails SSL requis .
- Ajoutez des groupes aux stratégies.
Les avantages de cette solution:
- Il existe une possibilité d'authentification OTP sur la solution open source Fortigate .
- Il exclut l'utilisateur qui saisit le mot de passe du domaine lors de la connexion via VPN, ce qui simplifie quelque peu le processus de connexion. Le mot de passe à 6 chiffres est plus facile à saisir que la politique de sécurité. En conséquence, le nombre de tickets avec le sujet: "Impossible de se connecter au VPN" diminue.
PS Il est prévu de renforcer cette solution pour une authentification à deux facteurs à part entière avec défi-réponse.
Mise Ă jour:
Comme promis, je l'ai terminé jusqu'à l'option défi-réponse.
Donc:
Dans le fichier / etc / raddb / sites-enabled / default , la section d' autorisation ressemble Ă ceci:
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
}
La section d' authentification ressemble maintenant Ă ceci:
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
}
Maintenant, l'utilisateur est vérifié selon l'algorithme suivant:
- L'utilisateur entre les crédits 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.
- Le jeton est vérifié.
- Profit).