Mettre en place de l’OTP pour les connexions VPN des pare-feux Stormshield

Stormshield, filiale de Airbus CyberSecurity et fusion d’Arkoon et Netasq, propose les produits Network Security, pare-feux de nouvelle génération embarquant une plétore de fonctionnalités : IDS/IPS, filtrage HTTP/HTTPS, déchiffrement SSL/TLS, analyse profonde des packets (Deep Packet Inspection), passerelle VPN IPSec et SSL (OpenVPN)…

Ces produits ont acquis une certaine maturité depuis la dernière version 4 du firmware. Plus rapides, plus ergonomiques, ces derniers sont une solution de choix pour les entreprises, correspondants aux besoins des TPE jusqu’à ceux des grandes entreprises, grâce un firmware unique, des fonctionnalités unifiées et des modèles répondant à toutes les tailles de systèmes d’informations.

Travaillant avec ce matériel depuis les modèles proposés par Netasq, j’ai pu mettre en place une trentaine d’entre eux, des modèles allant du SN160 jusqu’au SN910. Ceci m’a permis d’acquérir une certaine maîtrise du produit (la certification CSNE aidant) et d’avoir un recul critique sur les appliances proposées par Stormshield.

L’une des puissances du produit est de proposer une passerelle VPN SSL basée sur OpenVPN, clé en main, permettant en quelques minutes de déployer des accès distants sécurisés à des clients mobiles. Connecté à un annuaire Active Directory, la solution est facile d’utilisation pour des utilisateurs nomades, qui n’ont qu’à renseigner leurs identifiants de domaine pour établir un tunnel sécurisé avec la passerelle.

Mais à l’heure d’un télétravail de plus en plus fréquent et de la recrudescence des attaques, ces accès nomades sont une porte d’entrée négligée et difficilement protégeables avec la solution de base. L’une des solutions et de mettre en place une authentification multi-facteurs, basée par exemple sur un mot de passe à usage unique (OTP). Je vous propose dans cet article de voir comment mettre en place une authentification multi-facteurs pour vos nomades utilisant du VPN SSL. La solution proposée ici fonctionne également pour du VPN IPSEC basé sur un couple certificat/XAUTH.

Démo de la connexion au tunnel VPN par l’utilisateur

LinOTP et FreeRADIUS, des solutions libres et gratuites

Les pare-feux Stormshield proposent les méthodes d’authentification suivantes :

  • LDAP
  • Certificat
  • RADIUS
  • Kerberos
  • Authentification transparente (SPNEGO)
  • Authentification unique (SSO)

Généralement, lors du paramétrage de la passerelle VPN SSL, c’est l’authentification LDAP qui sera utilisée pour authentifier et identifier les nomades. Cependant, il est tout à fait possible d’utiliser la méthode RADIUS pour authentifier ces derniers. Grâce à cette fonctionnalité de notre pare-feu, nous allons pouvoir utiliser la solution libre de l’éditeur allemand Key Identity, LinOTP, qui peut fonctionner avec un serveur RADIUS. J’utiliserai ici le projet FreeRADIUS, implémentation libre du protocole RADIUS normalisé par l’IETF en 2000 via la RFC2865.

Au niveau du fonctionnement, nous aurons ceci :

  1. Le client OpenVPN envoie la demande d’authentification avec le couple <username> et <password><OTP> au service d’authentification du pare-feu
  2. Le pare-feu fait une requête au serveur FreeRadius, via une requête standard RADIUS, lui demandant de valider la demande d’authentification.
  3. Le serveur FreeRADIUS, via un script Perl, fait une requête REST sur l’API de LinOTP
  4. Le serveur LinOTP, sépare le couple <password><OTP> et valide le One Time Password. Si ce dernier est correct, il transmet la demande d’authentification LDAP du couple <username> et <password> au contrôleur de domaine.
  5. Si l’authentification LDAP est correcte, le contrôleur de domaine répond positivement au serveur LinOTP
  6. Le serveur LinOTP répond positivement au serveur FreeRADIUS via une réponse en tant qu’objet JSON
  7. Le serveur FreeRADIUS, après avoir vérifié la réponse JSON, répond positivement au pare-feu
  8. Le pare-feu autorise le client OpenVPN à établir un tunnel VPN SSL.

Au niveau des pré-requis, nous aurons besoin :

  • Debian/Ubuntu ou RHEL/CentOS 7. Je traiterai dans cet article l’installation sur RHEL 7.9, dernière version de RHEL 7.
  • Une base de données (MySQL, MariaDB, PostGreSQL) pour stocker les tokens. J’utiliserai ici MariaDB
  • FreeRADIUS, pour s’interfacer entre le pare-feu et LinOTP
  • Une appliance Stormshield, physique ou virtuelle
  • Un serveur de domaine Active Directory

Il est tout à fait possible de séparer chaque service sur un serveur distinct (base de données, LinOTP, FreeRADIUS). C’est à votre convenance, il faudra seulement modifier les adresses utilisées par les différents services. Pour ma part, j’utilise un serveur déjà existant dédiée aux bases de données, où sera localisée la base de données des tokents. LinOTP et FreeRADIUS, seront eux, sur un autre serveur.

Malheureusement, je n’ai pas pu faire fonctionner l’authentification à double facteur avec le client VPN SSL officiel de Stormshield. Ce dernier utilise deux phase : l’authentification sur le portail pour récupérer la configuration OpenVPN et la configuration OpenVPN en elle même. Cependant, l’authentification à double facteur fonctionne parfaitement avec le client OpenVPN officiel, que ce soit la version 2.5 ou 3. Vous n’aurez qu’à déployer la configuration .openvpn sur vos nomades.

I. Installation et configuration de LinOTP

Une fois votre serveur fraîchement installé, et à jour, nous allons installer et paramétrer la base de données hébergeant les tokens de LinOTP. Peu importe que votre base de données soit déportée ou sur le même serveur. Attention, si vous êtes sur RHEL, assurez-vous que votre système soit enregistré et abonné.

I.1. Installation et paramétrage de la base de données

Commençons par installer MariaDB via les dépôts officiels :

sudo yum install mariadb-server

Lançons ensuite le script automatisé d’initialisation du SGBD, de manière interactive :

sudo mysql_secure_installation

Je vous conseille de paramétrer MariaDB comme ci-dessous :

Set root password? [Y/n] y
New password: <password>
Re-enter new password: <password>
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y

Assurez de vous de mettre un mot de passe assez complexe, de retirer les utilisateurs anonymes, de désactiver l’authentification du compte root à distance, de supprimer la base de données de test, et enfin de rechargé la table des privilèges.

Une fois MariaDB installé et initialisé, créons la base de données le compte d’accès à la base pour LinOTP :

mysql -u root -p

Un conseil, ne renseignez jamais vos mots de passe directement dans la ligne de commande de connexion à la base, ils se retrouveraient dans l’historiqued de commande. Vous ne savez pas qui peut être amené à opérer sur le serveur 😉

CREATE DATABASE <nom_de_la_base> ;
CREATE USER ‘<nom_user>’@’<IP_USER>’ IDENTIFIED BY ‘<mdp_user>’ ;
GRANT ALL PRIVILEGES ON <nom_de_la_base>.* TO ‘<nom_utilisateur>’@’<IP_de_l’utilisateur>’ IDENTIFIED BY ‘<mdp_user>’ ;
FLUSH PRIVILEGES ;
quit ;

Si votre serveur de base de données est déporté sur un autre serveur, ouvrez le port TCP/3306 sur le pare-feu système. N’hésitez pas à n’ouvrir l’accès que pour votre serveur LinOTP si ce dernier est le seul à se connecter à la base de données. De manière générale, je vous conseille de n’ouvrir que le strict nécessaire sur vos pare-feux.

firewall-cmd --new-zone=mariadb-access --permanent
firewall-cmd --reload
firewall-cmd --zone=special --add-source=<adresse ip de LinOTP>/32
firewall-cmd --zone=special --add-port=3306/tcp

Grâce à la création d’une zone spécifique, en cas de création d’une nouvelle base de données sur MariaDB pour un autre service, vous n’aurez qu’à rajouter l’adresse IP supplémentaire dans cette zone.

Cependant, vous pouvez également ouvrir de manière plus large grâce à la commande suivante :

firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload

I.2 Installation de LinOTP

Nous allons tout d’abord rajouter un dépôt pour Yum :

sudo yum localinstall http://linotp.org/rpm/el7/linotp/x86_64/Packages/LinOTP_repos-1.1-1.el7.x86_64.rpm

Pensez à vérifier qu’une nouvelle version n’est pas présente sur http://linotp.org/rpm/el7/linotp/x86_64/Packages/

On active les packages supplémentaires EPEL (Extra Packages for Enterprise Linux) :

sudo yum install epel-release

Enfin, on installe LinOTP et le client MariaDB :

sudo yum install LinOTP LinOTP_mariadb

Une fois LinOTP installé, il faut indiquer à LinOTP comment se connecter à la base de données. Pour cela, on modifie le fichier /etc/linotp2/linotp.ini et on modifie le paramètre sqlalchemy.url, normalement situé à la ligne 170 du fichier :

sqlalchemy.url = mysql://<user>:<Password>@<@IP_BDD>/<nom_de_la_base>

Je vous conseille de tester avant l’utilitaire CLI de MariaDB de vous connecter à la base de données, ça vous évitera de perdre du temps en cas d’erreur 🙂

I.3 Installation de l’interface web de LinOTP

Nous avons installé précédemment le coeur de LinOTP, mais il existe également un service web servant pour l’administration de LinOTP et pour le selfservice des utilisateurs. Le paquet LinOTP_apache HTTPD et des fichiers de configurations pré-générés. Pour l’installer :

sudo yum install LinOTP_apache

On active ensuite le démarrage du service HTTPD au démarrage du serveur :

systemctl enable httpd.service

On génère les clés de chiffrement permettant de chiffrer la base de données précédemment crée sur le serveur MariaDB, grâce au script suivant :

/etc/linotp2/linotp-create-enckey -f /etc/linotp2/linotp.ini

On fixe les permissions et la propriété des fichiers de configurations pour le compte de service linotp :

/etc/linotp2/linotp-fix-access-rights -f /etc/linotp2/linotp.ini -u linotp

On ouvre le port TCP/443 pour notre service web :

firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd--reload

I.3. Configuration de l’interface web

Un fichier de configuration est fourni par défaut, faisons une copie de la configuration initiale et utilisons celle donnée avec le paquet :

mkdir /etc/httpd/conf.d.old
mv /etc/httpd/conf.d/* /etc/httpd/conf.d.old
cp /etc/httpd/conf.d.old/ssl_linotp.conf.template /etc/httpd/conf.d/ssl_linotp.conf

Modifions dès à présent le mot de passe du compte administrateur de base, via le fichier :

vim /etc/linotp2/admins

Enfin, démarrons le serveur web :

systemctl start httpd.service

Attention, de base, LinOTP utilise un certificat auto-signé pour chiffrer les connexions TLS. Je vous recommande bien sûr de générer un certificat signé par une autorité de certification. Rien de bien compliqué, il suffit d’indiquer au fichier de configuration /etc/httpd/conf.d/ssl_linotp.conf quel certificat utiliser.

L’interface d’administration est accessible via l’url : https://<LinOTP_IP>/manage/

Il est possible d’utiliser un groupe d’utilisateurs du domaine Active Directory pour administrer LinOTP. Pratique si vous souhaitez déléguer l’accès à une équipe d’administrateurs systèmes. Pour cela, il faut modifier la configuration d’Apache. Vous pouvez passer à l’étape I.4 si cela ne vous intèresse pas.

Paramétrage d’un groupe d’utilisateurs AD/LDAP pour administrer LinOTP

Installer le module mod_ldap d’Apache :

sudo yum install mod_ldap

Modifier le VirtualHost afin d’utiliser l’authentification LDAP :

sudo vim /etc/httpd/conf.d/ssl_linotp.conf

Le AuthLDAPURL doit être sous cette forme:

ldap://@IP(ou nom)/<BaseDN>?sAMAccountName?sub?(objectClass=user)” NONE.

Aidez-vous de ce que vous avez renseigné pour le UserIdResolver de LinOTP

Pour le AuthLDAPBindDN, saisissez ce que vous aviez mis pour le UserIdResolver de LinOTP entre parenthèses

Pour le AuthLDAPBindPassword, c’est le mot de passe du compte entre parenthèses

Pour Require ldap-group, mettez le chemin du groupe ldap que vous souhaitez autoriser à la connexion

I.4. Connexion de LinOTP à l’Active Directory

Nous allons ici connecter LinOTP à notre Active Directory. Assurez vous d’avoir un compte dédié à ce bind. Je vous rappelle qu’un compte non privilégie suffit et qu’il n’est en aucun cas nécessaire d’utiliser un compte ayant des droits d’administration sur le domaine.

Dans un environnement de production, générez une chaîne de charactères aléatoire pour le nom du compte et générez un mot de passe fort. Evitez de remplir le champ description de l’objet. Conservez ces informations dans un gestionnaire de mot de passe sûr. Moins d’infos vous laissez à un potentiel attaquant, mieux votre AD se portera. Pour finir, limitez la connection du compte au contrôleur de domaine. Ceci évitera la réutilisation du compte sur d’autres machines de votre réseau.

Nous allons créer un UserIdResolver, où nous allons pouvoir renseigner notre annuaire. Aller dans « Configuration LinOTP » ou « LinOTP Configuration » selon la langue de votre interface, puis dans « UserIdResolvers ».

Créer un « LDAP Resolver », et compléter le resolveur selon votre environnement. Si vous avez plusieurs contrôleurs de domaine, mettez les, cela vous assurera une redondance.

Vérifier que les attributs du schéma soient adaptés pour Active Directory. Cliquer sur « Preset Active Directory » pour les forcer.

Je vous conseille de filtrer sur un groupe préalablement créé, pour limiter l’import des utilisateurs dans LinOTP. Vous pouvez adapter le filtre suivant, sur le champ « Searchfilter » :

(&(Objectclass=user)(objectCategory=person)(memberOf=CN=LinOTP Users,OU=Users groups,DC=LAB,DC=INFO-SEC,DC=FR)))

Une fois notre résolveur créé, on le configure pour un domaine. Pour cela, aller dans « Configuration LinOTP » ou « LinOTP Configuration » puis dans « Domaines » ou « Realms ». Créer ensuite un nom de domaine et configurer le pour utiliser le résolveur précédemment créé.

I.5 Configuration du self service

Le Self-Service permet à des utilisateurs de générer et supprimer eux-mêmes leur token sans passer par la console de management, elle peut être personnalisée pour des groupes d’utilisateurs, ici nous allons configurer le Self-Service pour que les utilisateurs puissent générer eux-mêmes des tokens compatible avec Google-Authentificator – FreeOTP basé sur le temps (renouvellement toutes les 30sec)

Pour cela il va falloir créer une directive que l’on va appliquer sur le résolveur créé précédemment. Aller dans le menu Directives puis en créer une :

II. Paramétrage de FreeRADIUS

II.1. Paramétrage de base

Pour commencer, installer les paquets suivants :

sudo yum install freeradius freeradius-perl perl-Config-IniFiles perl-Try-Tiny perl-LWP-Protocol-https

Faire un backup du dossier /etc/raddb/ :

sudo cp -a /etc/raddb /etc/raddb.old/

Modifier alors le fichier /etc/raddb/clients.conf, pour rajouter un client, avec les élèments suivants :

Client  <nom_du_client> {
        ipaddr = <IPduClient>
        secret = <presharedkey>
}

Soit par exemple :

Client  sn310 {
        ipaddr = 172.16.1.254
        secret = QWfQLtEggxJQAtpANVjd
}

Veiller à choisir un secret fort pour protéger correctement les échanges entre le client (Stormshield) et le serveur Radius.

On vérifie que le fichier /etc/raddb/users contient la directive suivante :

DEFAULT Auth-type := perl

Si ce n’est pas le cas, supprimer le contenu éventuel et renseigner la directive ci-dessus.

II.2. Liaison à LinOTP

Le plugin officiel fourni par LinOTP ne fonctionne pas pour RHEL/CentOS 7. Il faut donc récupérer une version modifiée et proposée par Mark VANDEBOS sur son GitHub :

wget https://github.com/mark-vandenbos/linotp-freeradius3-centos7/archive/master.zip

unzip master.zip

Copier le plugin à l’emplacement dédié :

cp linotp-freeradius3-centos7-master/linotp-perl.pm /etc/raddb/mods-config/perl/radius_linotp.pm

III. Configuration du pare-feu Stormshield

Je vais assumer ici que votre passerelle VPN (SSL ou IPSEC) est déjà en place et que votre appliance est connectée à votre Active Directory. Si ce n’est pas le cas, je vous renvoie vers les guides techniques pas à pas de Stormshield :

VPN SSL -> https://documentation.stormshield.eu/SNS/v4/fr/Content/SSL_VPN_tunnels/100-Introduction.htm

III.1. Paramétrage de la méthode d’authentification Radius

Premièrement, nous allons paramétrer une nouvelle méthode d’authentification, notre serveur FreeRADIUS. Pour cela, aller « Configuration »/ »Users »/ »Authentication » ou « Configuration »/ »Utilisateurs »/ »Authentification » en français.

Dans « Available methods » ou « Méthodes disponibles » en français, ajouter une nouvelle méthode, et choissisez « Radius ».

Configurer le serveur Radius avec l’adresse IP de notre serveur FreeRADIUS et la clé de chiffrement pré-partagée. Laissez le port par défaut.

Rendez-vous ensuite dans l’onglet « Authentication policy » ou « Politiques d’authentification », et rajouter une règle standard avec les élèments suivants :

  • Ajouter en source l’interface sslvpn.
  • Puis pour finir, supprimer la méthode par défaut et ajouter la méthode RADIUS.

Vous devriez avoir une règle comme celle ci-dessous :

Vous pouvez également rajouter comme source votre interface WAN, si vous voulez que votre portail captif utilise également LinOTP.

III.2. Empêcher le tunnel de se fermer après 3600 secondes (1 heure)

https://kb.stormshield.eu/en/network-security/sns-appliance/vpn/ssl-vpn/using-t-otp-to-mount-a-vpn-ssl-tunnel-the-tunnel-is-closed-down-after-3600-seconds

Et voilà ! Tout est configuré, testons à présent tout cela 🙂

IV. Test de la connexion VPN

Comme expliqué plus haut, je n’ai pas réussi à faire fonctionner la connexion VPN avec l’authentification à double facteurs avec le client VPN SSL officiel de Stormshield. Néanmoins, cela fonctionne parfaitement avec OpenVPN (version 2.5 et version 3).

Attention, sur OpenVPN en version 3, vous devez absolument activer la compression dans les paramètres genéraux d’OpenVPN. En effet, sans ce paramètre, la connexion s’établira mais vous rencontrerez des problèmes pour communiquer avec vos réseaux distants. (Cf. KB de Stormshield).

N’hésites pas à me faire des retours pour tout problème rencontré ou erreur se trouvant dans l’article.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *