Securité Réseaux Informatiques : Serveur RADIUS - FreeRADIUS
RADIUS
Remote Authentication Dial-In User Service est un système qui fait de « l'AAA » (Authentication, Authorization and Accounting). Utilisé depuis longtemps déjà par bon nombre de fournisseurs d'accès à l'internet pour authentifier leurs clients et leur communiquer une configuration IP.
RADIUS est également très utile pour sécuriser un réseau Wi-Fi, ou même un réseau filaire, dans certaines conditions.
Dans ce sous chapitre, nous verrons comment installer et configurer un serveur RADIUS libre (FreeRADIUS), puis nous le mettrons en oeuvre dans deux situations bien distinctes :
- la sécurisation d'un réseau Wi-Fi (authentification WPA2-TLS),
- la sécurisation d'un réseau filaire (authentification des stations par adresse MAC).
Ce type de solution s'avère fort intéressant si l'on dispose d'un réseau proposant un accès filaire et Wi-Fi, avec des utilisateurs susceptibles de venir y connecter leur ordinateur portable. Par définition, ce type de machine échappe totalement au contrôle de l'administrateur et peut être la source de bien des soucis.
FreeRADIUS
Avant de commencer...
RADIUS (Remote Authentication Dial-In User Service) est un vaste programme. Pour essayer de faire simple (donc schématique et incomplet), ce service est capable :
- d'authentifier un utilisateur distant, suivant de multiples modes plus ou moins sécurisés, en s'appuyant sur une base connaissances allant du simple fichier texte à l'annuaire LDAP, en passant par une base de données de type SQL,
- d'enregistrer des informations sur chaque « login »,
- de renvoyer au demandeur des paramètres variés pouvant, suivant le cas, être une configuration IP, un numéro de LAN virtuel etc.
Étudier dans le détail toutes les possibilités de RADIUS est hors de la portée de cet exposé. (c'est, de toutes façons, également hors de ma propre portée). Nous nous contenterons ici de le mettre en oeuvre dans les deux cas qui nous intéressent :
- authentification depuis leur adresse MAC des stations « connues » sur notre réseau filaire, en utilisant un système de type « login/password », avec le protocole CHAP (Challenge-Handshake Authentication Protocol), éventuellement en assignant un numéro de VLAN suivant la machine,
- authentification avec un certificat x.509 sur le réseau Wi-Fi, en utilisant EAP-TLS.
Installer et surtout configurer un serveur radius pour la première fois a quelque chose d'assez rebutant, voire repoussant. Nous allons passer un peu de temps à détailler cette opération, ceci aidera probablement ceux qui n'ont encore jamais tenté l'aventure. Nous utilisons FreeRADIUS sur une Debian Etch.
FreeRadius peut fonctionner en s'appuyant uniquement sur des fichiers texte. Ce n'est pas forcément ce qu'il y a de plus simple à gérer, si l'on doit manipuler un grand nombre de clients. Ici, nous utiliserons MySQL pour stocker les adresses MAC des clients. Outre la souplesse qu'apportent des outils comme phpmyadmin pour gérer la liste des clients, cette solution offre l'avantage de ne pas nécessiter de redémarrage de FreeRADIUS à chaque modification de la base.
Installation de Freeradius
Pour des raisons de compatibilité de licences, FreeRadius est compilé par défaut sur Debian sans le support de TLS (ni de Postgresql). TLS nous servira pour le WPA2. Nous allons donc reconstruire un paquet binaire à partir du paquet source, en tenant compte de cet usage.
Préparatifs
Nous aurons besoin de quelques outils de compilation et de gestion des paquets source :
# apt-get install build-essential
...
# apt-get install apt-src
Puis nous devons mettre à jour la liste des paquets source :
# apt-src update
Enfin, nous installons le paquet source de FreeRadius dans un répertoire que nous aurons créé dans ce but. La commande apt-src install offre, entre autres, l'avantage d'installer automatiquement les dépendances.
# mkdir ~/build_freeradius
# cd ~/build_freeradius
# apt-src install freeradius
Nous devons retrouver dans notre répertoire :
# ls -l
total 2552
drwxr-xr-x 15 root root 4096 2007-01-11 16:35 freeradius-1.1.3
-rw-r--r-- 1 root root 15130 2006-09-01 20:07 freeradius_1.1.3-3.diff.gz
-rw-r--r-- 1 root root 975 2006-09-01 20:07 freeradius_1.1.3-3.dsc
-rw-r--r-- 1 root root 2587376 2006-09-01 20:07 freeradius_1.1.3.orig.tar.gz
Configuration de la compilation
Dans le répertoire ~/build_freeradius/freeradius-1.1.3/debian nous avons un fichier nommé « rules », qui contient les directives de compilation. Dans ce fichier, nous trouvons dans les premières lignes, quelques informations qui nous intéressent :
# If you want to use SSL and/or the postgres module, comment
# out these two lines and uncomment the two after
# You will also need to add a Build-Depends on libssl-dev and libpq-dev
# and remove the Build-Conflicts on libssl-dev
# Finally you need to cat debian/control.postgresql >> debian/control
Tant que nous y sommes, ajoutons le support de Postgresql, ce qui simplifiera la manipulation et permettra à ceux qui préfèrent, d'utiliser Postgresql plutôt que MySQL.
La première modification est facile à réaliser :
#buildssl=--without-rlm_eap_peap --without-rlm_eap_tls --without-rlm_eap_ttls --without-rlm_otp
--without-rlm_sql_postgresql --without-snmp
#modulelist=krb5 ldap sql_mysql sql_iodbc
buildssl=--with-rlm_sql_postgresql_lib_dir=`pg_config --libdir`
--with-rlm_sql_postgresql_include_dir=`pg_config --includedir`
modulelist=krb5 ldap sql_mysql sql_iodbc sql_postgresql
--without-rlm_sql_postgresql --without-snmp
#modulelist=krb5 ldap sql_mysql sql_iodbc
buildssl=--with-rlm_sql_postgresql_lib_dir=`pg_config --libdir`
--with-rlm_sql_postgresql_include_dir=`pg_config --includedir`
modulelist=krb5 ldap sql_mysql sql_iodbc sql_postgresql
La seconde est peut-être moins évidente si l'on ne sait pas qu'il faut réaliser l'opération dans le fichier ~/build_freeradius/freeradius-1.1.3/debian/control :
Source: freeradius
Build-Depends: debhelper (>= 5), libltdl3-dev, libpam0g-dev, libmysqlclient15-dev | libmysqlclient-
dev, libgdbm-dev,
libldap2-dev, libsasl2-dev, libiodbc2-dev, libkrb5-dev, snmp, autotools-dev, dpatch
(>= 2),
libperl-dev, libtool, dpkg-dev (>= 1.13.19), libssl-dev, libpq-dev
Build-Conflicts:
Build-Depends: debhelper (>= 5), libltdl3-dev, libpam0g-dev, libmysqlclient15-dev | libmysqlclient-
dev, libgdbm-dev,
libldap2-dev, libsasl2-dev, libiodbc2-dev, libkrb5-dev, snmp, autotools-dev, dpatch
(>= 2),
libperl-dev, libtool, dpkg-dev (>= 1.13.19), libssl-dev, libpq-dev
Build-Conflicts:
Enfin, il faut ajouter à ce fichier le contenu de control.postgresql :
# cd ~/build_freeradius/freeradius-1.1.3/debian
# cat control.postgresql >> control
Comme nous avons un peu bousculé les dépendances et les conflits, nous devons réparer ça :
# apt-get install libssl-dev libpq-dev
Se protéger des mises à jour de apt-get upgrade
Si nous compilons maintenant le paquet binaire, nous obtiendrons des paquets ayant le même nom (version comprise), que les binaires de la distribution, et les mises à jour futures ne manqueront pas de nous remplacer notre construction à la première occasion.
Une solution élégante consiste à obtenir des paquets binaires, avec un nom différent. Pour ce faire, nous pouvons agir dans le fichier ~/build_freeradius/freeradius-1.1.3/debian/changelog en ajoutant quelques lignes en tête du fichier. Par exemple :
freeradius (1.1.3-3tls) unstable; urgency=low
* Add TLS support for compilation
-- Christian Caleca <for.spam.only@eme-enseignement.fr> Fri, 11 Jan 2007 15:46:11 +0100
freeradius (1.1.3-3) unstable; urgency=medium
* Fix POSIX compliance problem in init script. Closes: #403384.
-- Mark Hymers <mark@hymers.orgue.uk> Sat, 16 Dec 2006 20:45:11 +0000
...
* Add TLS support for compilation
-- Christian Caleca <for.spam.only@eme-enseignement.fr> Fri, 11 Jan 2007 15:46:11 +0100
freeradius (1.1.3-3) unstable; urgency=medium
* Fix POSIX compliance problem in init script. Closes: #403384.
-- Mark Hymers <mark@hymers.orgue.uk> Sat, 16 Dec 2006 20:45:11 +0000
...
Il nous reste à construire les binaires :
Nous n'avons ici besoin que de deux de ces paquets :
Vérifions que Freeradius est bien lancé :
Nous devons maintenant préparer une base Mysql et configurer FreeRadius pour qu'il s'en serve.
Nous supposons que Mysql est correctement installé. Nous utilisons ici :
Création de la Base « radius » et de l'utilisateur du même nom :
La base est créée mais elle reste vide. Pour créer les tables, le paquet freeradius-mysql nous donne le schéma dans /usr/share/doc/freeradius/examples/mysql.sql.gz :
Tout semble s'être correctement passé. Vérification :
/etc/freeradius/radiusd.conf
Assurez-vous que seules les options définies dans ce qui suit sont activées (certaines options dans radiusd.conf sont à dé commenter, d'autres sont à commenter).
Dans la section « authorize »
Dans la section « authenticate »
Dans la section « accounting »
(Notez que cette section ne concerne pas l'authentification et qu'il est donc possible de la supprimer).
Dans la section « session »
Voici un exemple complet de configuration, qui correspond à notre besoin du moment :
/etc/freeradius/sql.conf
Les fichiers de configuration de FreeRadius se trouvent dans /etc/freeradius. Commençons par le plus « simple » (en réalité, il n'est pas simple du tout, mais il y a peu de choses à y faire). Aménagez en fonction de vos choix lors de la création de la base. Voici un exemple complet, qui est dépouilléde la partie « accounting » :
Faites attention aux droits d'accès des fichiers de ce répertoire. Il suffit maintenant de modifier eap.conf de la sorte :
N'oublions pas de relancer FreeRadius pour qu'il prenne en compte la nouvelle configuration.
Nous créons un « authenticator » de test dans la table « nas » :
Nous créons un utilisateur de test dans « radcheck » :
Notez que l'on utilise un mot de passe en clair dans la base, ce qui correspondra à un protocole « chap » pour l'authentification.
Enfin, depuis le serveur radius lui-même, qui va pour l'occasion cumuler le rôle d'authenticator, nous utilisons l'outil radtest :
Notre solution fonctionne. Il ne nous reste qu'à ajouter dans la table « nas » nos switchs , nos points d'accès Wi-Fi, et dans la table « radcheck » toutes nos adresses MAC en guise d'utilisateurs pour le réseau filaire (« UserName » et « User-Password » identiques).
Il existe plusieurs méthodes pour collecter les adresses MAC de vos postes clients, comme par exemple les logiciels d'inventaire de parc (OCS Inventory NG, en est un).
La table qui doit accueillir les « utilisateurs » s'appelle « radcheck ». Voyons de plus près la structure de cette table :
Entrer dans le détail des nombreuses possibilités de FreeRADIUS nous mènerait beaucoup trop loin. Dans le cadre de notre projet, nous devons créer une ligne par client de la manière suivante :
Comme pour gérer dans la suite une telle collection de valeurs, il faudra savoir à quel client correspond une adresse MAC, je vous conseille vivement d'ajouter dans cette table une rubrique supplémentaire destinée à contenir, par exemple, le nom du client associé :
Il « suffit » ensuite de peupler cette base avec vos adresses MAC par la méthode qui vous conviendra le mieux. Ceci devrait aboutir à quelque chose de la forme :
Il n'est pas nécessaire de relancer FreeRADIUS après modification de cette table.
Il ne faut pas oublier non plus d'ajouter dans la table « nas » les informations concernant vos SWITCHs. La table « nas » est de structure suivante :
Nous devons avoir dans cette table, quelque chose qui ressemble à ceci :
Notez qu'une modification de la table « nas » nécessite (pour l'instant) un redémarrage de FreeRADIUS.
Normalement, tout devrait fonctionner correctement. Le client d'adresse MAC 00:05:5d:df:f4:5b devrait se retrouver sur le VLAN d'IP 2 (PARADIS_VLAN) alors qu'un client d'adresse MAC ne figurant pas dans la table « radcheck » se retrouvera dans le VLAN d'ID 3 (ENFER_VLAN).
Si vous rencontrez des problèmes, la première chose à faire est d'arrêter FreeRADIUS, puis de le relancer en « foreground » (avant-plan) en mode « debug », par la commande :
ou, pour encore plus de détails :
FreeRADIUS est assez verbeux dans ce mode. Si, lors de la connexion d'un client, vous n'observez rien, c'est tout simplement que le switch ne dialogue pas avec le radius. Il faut alors en trouver la raison.
Si le dialogue démarre, il vous faudra déchiffrer le discours pour trouver la raison du disfonctionnement. Les raisons les plus probables étant :
Il nous faut ajouter notre borne Wi-Fi dans la table « nas ». Ici, nous utilisons une borne de type Netgear GW302, qui aura dans notre réseau l'adresse IP 192.168.10.3, comme nom « netgear » et qui utilisera « re-chutt » comme secret partagé avec le serveur radius. Nous devrions avoir dans notre table, quelque chose de ce genre :
Ici, la configuration va être extrêmement simple. Comme nous avons choisi d'utiliser WPA2-TLS, qui nécessite un certificat chez le client, il n'y aura à priori pas de base de noms d'utilisateurs à construire. Le serveur RADIUS va se contenter de vérifier l'authenticité du certificat présenté par le client. Si un client dispose d'un certificat valide, c'est bien qu'il est autorisé à se connecter.
Dans le cas de Windows XP, nous avons besoin du certificat de notre racine de confiance (root_maison_CA) ainsi que du certificat client (user1). Ces certificats sont à installer par l'utilisateur et serviront à authentifier l'utilisateur. Entendez par là deux
points importants :
Commençons par le certificat de la racine de confiance. Double clic dessus, ce qui nous amène à :
Cette Autorité de certification étant inconnue de Microsoft, il nous appartient de décider si oui ou non, nous l'acceptons. Nous allons bien sûr installer ce certificat, non sans être certain que c'est bien le bon. Autrement, dit, il nous appartient de vérifier que ce certificat provient bien de chez nous.
« Installer ce certificat... » va nous conduire à un assistant :
dont le texte explicatif ne nécessite aucun commentaire.
Suivant :
Nous allons choisir nous même l'emplacement où ce certificat sera stocké.
« Parcourir... »
Nous choisissons logiquement les Autorités de certification racines de confiance.
L'assistant a fini son travail.
Mais, tout de même, nous avons encore droit à un bon gros avertissement de sécurité.
Encore une fois, si nous sommes certains de l'origine de ce certificat, nous pouvons y aller.
Certificat du client
Double clic sur le certificat client.
Ceci démarre un nouvel
assistant.
La seconde permet de vérifier le chemin d'accès au certificat que nous voulons enregistrer.
Suivant >
Suivant >
Le mot de passe demandé ici est celui qui a été spécifié lors de l'exportation au format PKCS#12 avec TinyCA (« Export password »).
Ici, nous pouvons choisir de sélectionner automatiquement le magasin.
Suivant >
Le reste ne présente pas d'intérêt particulier, l'installation doit se terminer sans encombres.
Windows XP, même avec le SP2, ne gère pas WPA2. Il faut lui ajouter un correctif à télécharger chez Microsoft (validation d'intégrité « Genuine Advantage » requise). Ce correctif s'appelle :
WindowsXP-KB893357-v2-x86-FRA.exe. A l'heure où ces lignes sont écrites, ce lien est valide.
Sans ce correctif, vous devrez vous contenter de WPA.
Une fois tout ceci réalisé, avec un peu de chance, la connexion devrait s'établir automatiquement pour l'utilisateur qui a installé les certificats.
En cas de problèmesVoici quelques éléments qui devraient vous aider à trouver la solution.
Une console « mmc » va nous venir en aide. Créons une console de gestion des certificats.
exécuter mmc...
Ajouter un composant logiciel enfichable...
Choisir le composant
« certificats »...
« Fermer »
Si vous avez un compte d'administrateur (ce qui, rappelons le, n'est pas une bonne idée, même si c'est le comportement par défaut de WIndows XP), vous aurez droit à choisir s'il s'agit de vos certificats (utilisateur) ou d'autres certificats, comme ceux qui
concernent l'ordinateur.
Si votre compte est celui d'un simple utilisateur, vous n'aurez pas ce choix et ne pourrez gérer que vos propres certificats, ce qui est suffisant dans notre cas.
« Terminer »
Si nous double cliquons
sur le certificat :
Nous voyons apparaître la racine de confiance associée.
La suite sous entend que les connexions wi-fi sont gérées par les outils Windows. Même si l'on peut admettre qu'ils sont plutôt rébarbatifs, peu ergonomiques à première vue, mon expérience personnelle ne m'en a pas fait découvrir de meilleurs parmi les nombreux « gadgets » fournis par les constructeurs de matériel wi-fi.
Faites apparaître les propriétés des connexions réseau sans fils :
Sélectionnez votre réseau et affichez ses propriétés,
Sur l'onglet « Association », assurez-vous que vous êtes bien sur le mode WPA2, avec un chiffrement AES,
Sur l'onglet « Authentification », le type EAP doit être « Carte à puce ou autre certificat ». Affichez ses propriétés,
Utilisez la sélection de certificat recommandée (simple), indiquez le nom complet du serveur RADIUS, tel qu'il a été défini dans son certificat, sélectionnez enfin le certificat de la racine d'autorité.
Ceci devrait enlever toute ambiguïté, en cas de troubles.
Contrairement à Windows, le moyen le plus simple d'obtenir l'attachement à un réseau Wi-Fi est de le faire au niveau du système. Entendez par là que l'authentification se fera lors du montage du réseau, au démarrage du système, ou lors de l'activation de l'interface Wi-Fi. Autrement dit, ce ne sera pas l'utilisateur qui sera authentifié, mais l'administrateur de la machine.
La manipulation est faite sur une distribution Ubuntu 6.10, où wpa-supplicant est normalement installé par défaut. Il y a sur cette distribution, deux interventions à faire. La première est typique aux distributions basées sur Debian et il vous faudra trouver comment adapter à une autre distribution.
L'interface Wi-Fi est une carte PCMCIA (cardbus) D-Link DWL-G650, qui utilise un chipset Atheros (Driver Madwifi).
L'installation du paquet wpasupplicant a créé un répertoire /etc/wpa_supplicant/. Nous pouvons créer dedans un répertoire « certs » et y mettre dedans nos deux certificats :
Comme le contenu de ce répertoire est utilisé lors du démarrage, il n'y a aucune raison qu'il soit accessible par quiconque d'autre que root.
Sur les Distributions Debian et dérivées, il faut agir sur le fichier /etc/network/interfaces :
wpa-supplicant mériterait à lui seul tout un chapitre. Son fonctionnement n'est pas d'une évidence extrême, et sa configuration non plus.
Il faut créer un fichier /etc/wpa_supplicant.conf, comme indiqué dans /etc/network/interfaces, qui indiquera, réseau par réseau (ici, un seul suffira), les paramètres nécessaires à l'attachement.
Voici un exemple de configuration dans notre contexte :
Il n'y a rien d'incompréhensible dans ce fichier, la difficulté réside surtout dans le fait d'utiliser les bons paramètres. Pour vous aider, vous avez dans le répertoire /usr/share/doc/wpasupplicant/examples/ quelques exemples de configuration ainsi qu'un fichier « wpa_supplicant.conf.gz » très largement documenté, qui passe en revue tous les paramètres possibles.
C'est bien mais...
Cette solution ne nous permet pas de gérer les « coups durs ». Comment faire en effet si l'on apprend qu'un certificat encore valide a été compromis ? Car dans cette configuration, une fois un certificat installé, il sera accepté par FreeRADIUS tant qu'il n'aura pas expiré.
Dans notre solution globale, nous gérons le réseau filaire par une authentification de type « login/password » où l'adresse MAC joue le rôle des deux composants. Nous disposons d'une base de données MySQL (ou Postgresql) qui recense toutes les adresses MAC connues. Nous avons pu tester son bon fonctionnement en utilisant un « login/password » introduit dans la base de données.
En ce qui concerne le réseau Wi-Fi, nous avons confié à EAP l'authentification, via le protocole TLS. Nous avons vu que, dans ce cas, tout se passe par l'intermédiaire des certificats, et qu'il n'y a aucune information dans la base de données.
Comment faire alors si pour une raison ou une autre, nous devions être amenés à bloquer un utilisateur disposant d'un certificat en cours de validité ? Il peut y avoir plusieurs raisons qui pourraient amener à cette résolution, comme :
Dans notre configuration actuelle, ce type de situation ne peut être géré, il nous faut trouver une solution, si possible pas trop complexe à maintenir.Deux voies sont à explorer :
TinyCA sait générer simplement des certificats de révocation, et FreeRADIUS peut être configuré assez simplement pour en tenir compte. Cette solution offre cependant deux gros défauts pour la maintenance :
Si nous trouvons un moyen pour que le certificat client ne soit accepté que si l'utilisateur est référencé dans la base, les choses deviendraient beaucoup plus simples, il suffirait d'ajouter ou de supprimer une ligne dans la base pour suspendre, temporairement ou non, un compte d'utilisateur, même si le certificat est encore en cours de validité.
Cette solution nous obligera à créer une ligne par utilisateur Wi-Fi dans notre base de données, en plus du certificat, mais nous permettra de gérer nettement plus facilement les impondérables.
Pour arriver à ce résultat, il va nous falloir entrer plus en profondeur dans le fonctionnement de RADIUS. Dans notre configuration très simple, nous ne définissons pas de type d'authentification approprié à chaque requête. Le résultat est que pour chaque requête, tous les types d'authentification possibles sont testés, si l'un d'entre eux renvoie « Accept », l'autorisation est donnée.
Actuellement, nous avons :
Cette solution n'est clairement pas facile à gérer.
C'est à dire que nous autoriserons les connexions soit par EAP, soit par la base de données sql, et nous n'avons défini nulle part de façon explicite le mode d'authentification pour un utilisateur donné. Le résultat est que :
Que se passerait-il, si nous trouvions le moyen de fixer le mode d'authentification par défaut ?
Ceci peut se réaliser par l'intermédiaire du fichier « users », à la condition d'ajouter « files » dans la section « authorize » de radiusd.conf. Si nous arrivons à forcer le serveur à rejeter par défaut toute authentification, puis à l'autoriser à utiliser un mode particulier pour un utilisateur donné, nous serons proches de la solution.
Nous mettons dans « users » la simple ligne « DEFAULT Auth-Type := Reject ». Par défaut, l'autorisation devrait ainsi être refusée à tout le monde :
Le problème étant maintenant d'attribuer un type d'authentification correct aux utilisateurs Wi-Fi connus. Il faut le faire avant de définir le mode par défaut. Fort heureusement, les autorisations sont lues séquentiellement dans la section « authorize ».
Fichier « radiusd.conf »
A part que, avec cette écriture, lorsque l'on sort d'un module on entre dans le suivant, quelle que soit la réponse du module précédent, pourvu qu'il n'y ait pas eu de « Reject ». Ici, même si SQL accorde un « Auth-Type := EAP » à un utilisateur connu, cette valeur sera écrasée par le Auth-Type par défaut du fichier « users »; et donc personne ne sera autorisé, ce n'est pas ce que nous voulons.
Si nous plaçons files avant sql, ça ne fonctionnera pas non plus, puisque le type d'authentification « Reject » sera rencontré en premier, mettant fin à la procédure.
Fort heureusement, le mode « fail-over » va venir à notre secours sous cette forme :
Ainsi, lorsqu'un utilisateur est trouvé dans la base sql, soit il sera authentifié en mode Local, si son mot de passe est indiqué (pour les autorisations depuis les adresses MAC), soit, si un mode d'authentification de type TLS lui est attribué, EAP fonctionnera.
Si en revanche aucun mode d'authentification n'est attribué, c'est le mode par défaut qui passera et, même avec un certificat valide, l'utilisateur devrait être rejeté.
C'est bon. Essayons maintenant le Wi-Fi avec un certificat valide, présentant le nom d'utilisateur userwifi1, non répertorié dans la base des utilisateurs, l'authentification échouera. Si maintenant nous ajoutons ceci dans la base :
L'authentification eap devrait réussir. Voyons un « best-of » des logs de freeradius lancé en mode « debug » :
Vérifions tout de même que si l'utilisateur est supprimé de la table « radcheck », l'authentification va échouer :
image
Le log de freeradius deviendra beaucoup plus court :
Nous n'avons plus trop besoin de gérer de certificats de révocation.
Ce que nous venons de voir va nous contraindre à mélanger dans la même table les utilisateurs qui disposent d'une authentification de type CHAP (réseau filaire) et EAP (réseau Wi-Fi). Les tables « radgroupcheck » et « usergroup » vont nous aider à séparer les deux types d'utilisateurs, dans des tables différentes.
L'idée est la suivante. Nous allons créer un groupe d'utilisateur nommé « wifiGroup » (dans la table « radgroupcheck »), auquel nous allons appliquer l'attribut « Auth-Type := EAP ». Il suffira ensuite d'intégrer nos utilisateurs Wi-Fi dans ce groupe (dans la table « usergroup »), pour qu'ils héritent de l'attribut.
Freeradius considèrera que tous les membres du groupe « wifiGroup » doivent être identifiés via EAP, et les membres de ce groupe sont tous définis dans la table « usergroup ». De cette manière, il sera plus facile de gérer les deux types d'utilisateurs.
# cd ~/build_freeradius
# apt-src build freeradius
...
...
...
I: Successfully built in /root/build_freeradius/freeradius-1.1.3
# ls -l | grep deb$
-rw-r--r-- 1 root root 761896 2007-01-11 18:10 freeradius_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 114398 2007-01-11 18:09 freeradius-dialupadmin_1.1.3-3tls_all.deb
-rw-r--r-- 1 root root 31892 2007-01-11 18:10 freeradius-iodbc_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 32586 2007-01-11 18:10 freeradius-krb5_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 46894 2007-01-11 18:10 freeradius-ldap_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 31836 2007-01-11 18:10 freeradius-mysql_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 32280 2007-01-11 18:10 freeradius-postgresql_1.1.3-3tls_i386.deb
# apt-src build freeradius
...
...
...
I: Successfully built in /root/build_freeradius/freeradius-1.1.3
# ls -l | grep deb$
-rw-r--r-- 1 root root 761896 2007-01-11 18:10 freeradius_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 114398 2007-01-11 18:09 freeradius-dialupadmin_1.1.3-3tls_all.deb
-rw-r--r-- 1 root root 31892 2007-01-11 18:10 freeradius-iodbc_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 32586 2007-01-11 18:10 freeradius-krb5_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 46894 2007-01-11 18:10 freeradius-ldap_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 31836 2007-01-11 18:10 freeradius-mysql_1.1.3-3tls_i386.deb
-rw-r--r-- 1 root root 32280 2007-01-11 18:10 freeradius-postgresql_1.1.3-3tls_i386.deb
Nous n'avons ici besoin que de deux de ces paquets :
# dpkg -i freeradius_1.1.3-3tls_i386.deb freeradius-mysql_1.1.3-3tls_i386.deb
Vérifions que Freeradius est bien lancé :
# ps aux | grep radius
freerad 4118 0.0 0.8 44608 2224 ? Ssl 18:16 0:00 /usr/sbin/freeradius
Nous devons maintenant préparer une base Mysql et configurer FreeRadius pour qu'il s'en serve.
Configuration de Mysql
Nous supposons que Mysql est correctement installé. Nous utilisons ici :
# mysql -V
mysql Ver 14.12 Distrib 5.0.30, for pc-linux-gnu (i486) using readline 5.2
Création de la Base « radius » et de l'utilisateur du même nom :
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.0.30-Debian_3-log Debian etch distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> create database radius;
Query OK, 1 row affected (0.04 sec)
mysql> grant all on radius.* to radius@'localhost' identified by 'epikoi';
Query OK, 0 rows affected (0.06 sec)
mysql> exit
Bye
La base est créée mais elle reste vide. Pour créer les tables, le paquet freeradius-mysql nous donne le schéma dans /usr/share/doc/freeradius/examples/mysql.sql.gz :
# zcat /usr/share/doc/freeradius/examples/mysql.sql.gz | mysql -u root -p radius
Enter password:
#
Tout semble s'être correctement passé. Vérification :
# mysql -u radius -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 48
Server version: 5.0.30-Debian_3-log Debian etch distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> connect radius
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Connection id: 49
Current database: radius
mysql> show tables;
+------------------+
| Tables_in_radius |
+------------------+
| nas |
| radacct |
| radcheck |
| radgroupcheck |
| radgroupreply |
| radpostauth |
| radreply |
| usergroup |
+------------------+
8 rows in set (0.00 sec)
mysql>
Configuration de FreeRadius
/etc/freeradius/radiusd.conf
Assurez-vous que seules les options définies dans ce qui suit sont activées (certaines options dans radiusd.conf sont à dé commenter, d'autres sont à commenter).
Dans la section « authorize »
authorize {
preprocess
eap
sql
}
Dans la section « authenticate »
authenticate {
Auth-Type CHAP {
chap
}
eap
}
Dans la section « accounting »
accounting {
detail
radutmp
sql
}
(Notez que cette section ne concerne pas l'authentification et qu'il est donc possible de la supprimer).
Dans la section « session »
session {
sql
}
Voici un exemple complet de configuration, qui correspond à notre besoin du moment :
prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = ${exec_prefix}/sbin
logdir = /var/log/freeradius
raddbdir = /etc/freeradius
radacctdir = ${logdir}/radacct
confdir = ${raddbdir}
run_dir = ${localstatedir}/run/freeradius
log_file = ${logdir}/radius.log
libdir = /usr/lib/freeradius
pidfile = ${run_dir}/freeradius.pid
user = freerad
group = freerad
max_request_time = 30
delete_blocked_requests = no
cleanup_delay = 5
max_requests = 1024
bind_address = *
port = 0
hostname_lookups = no
allow_core_dumps = no
regular_expressions = yes
extended_expressions = yes
log_stripped_names = no
log_auth = no
log_auth_badpass = no
log_auth_goodpass = no
usercollide = no
lower_user = no
lower_pass = no
nospace_user = no
nospace_pass = no
checkrad = ${sbindir}/checkrad
security {
max_attributes = 200
reject_delay = 1
status_server = no
}
$INCLUDE ${confdir}/clients.conf
snmp = no
thread pool {
start_servers = 5
max_servers = 32
min_spare_servers = 3
max_spare_servers = 10
max_requests_per_server = 0
}
modules {
chap {
authtype = CHAP
}
$INCLUDE ${confdir}/eap.conf
checkval {
item-name = Calling-Station-Id
check-name = Calling-Station-Id
data-type = string
}
preprocess {
huntgroups = ${confdir}/huntgroups
hints = ${confdir}/hints
with_ascend_hack = no
ascend_channels_per_line = 23
with_ntdomain_hack = no
with_specialix_jetstream_hack = no
with_cisco_vsa_hack = no
}
files {
usersfile = ${confdir}/users
compat = no
}
detail {
detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
detailperm = 0600
}
acct_unique {
key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
}
$INCLUDE ${confdir}/sql.conf
radutmp {
filename = ${logdir}/radutmp
username = %{User-Name}
case_sensitive = yes
check_with_nas = yes
perm = 0600
callerid = "yes"
}
radutmp sradutmp {
filename = ${logdir}/sradutmp
perm = 0644
callerid = "no"
}
attr_filter {
attrsfile = ${confdir}/attrs
}
counter daily {
filename = ${raddbdir}/db.daily
key = User-Name
count-attribute = Acct-Session-Time
reset = daily
counter-name = Daily-Session-Time
check-name = Max-Daily-Session
allowed-servicetype = Framed-User
cache-size = 5000
}
sqlcounter dailycounter {
counter-name = Daily-Session-Time
check-name = Max-Daily-Session
sqlmod-inst = sql
key = User-Name
reset = daily
query = "SELECT SUM(AcctSessionTime - \
GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) \
FROM radacct WHERE UserName='%{%k}' AND \
UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
}
sqlcounter monthlycounter {
counter-name = Monthly-Session-Time
check-name = Max-Monthly-Session
sqlmod-inst = sql
key = User-Name
reset = monthly
query = "SELECT SUM(AcctSessionTime - \
GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) \
FROM radacct WHERE UserName='%{%k}' AND \
UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
}
always fail {
rcode = fail
}
always reject {
rcode = reject
}
always ok {
rcode = ok
simulcount = 0
mpp = no
}
expr {
}
digest {
}
exec {
wait = yes
input_pairs = request
}
exec echo {
wait = yes
program = "/bin/echo %{User-Name}"
input_pairs = request
output_pairs = reply
}
}
authorize {
preprocess
sql
eap
}
authenticate {
Auth-Type CHAP {
chap
}
eap
}
preacct {
preprocess
acct_unique
files
}
session {
sql
}
/etc/freeradius/sql.conf
Les fichiers de configuration de FreeRadius se trouvent dans /etc/freeradius. Commençons par le plus « simple » (en réalité, il n'est pas simple du tout, mais il y a peu de choses à y faire). Aménagez en fonction de vos choix lors de la création de la base. Voici un exemple complet, qui est dépouilléde la partie « accounting » :
sql {
driver = "rlm_sql_mysql"
server = "localhost"
login = "radius"
password = "epikoi"
radius_db = "radius"
acct_table1 = "radacct"
acct_table2 = "radacct"
postauth_table = "radpostauth"
authcheck_table = "radcheck"
authreply_table = "radreply"
groupcheck_table = "radgroupcheck"
groupreply_table = "radgroupreply"
usergroup_table = "usergroup"
nas_table = "nas"
deletestalesessions = yes
sqltrace = no
sqltracefile = ${logdir}/sqltrace.sql
num_sql_socks = 5
connect_failure_retry_delay = 60
sql_user_name = "%{User-Name}"
authorize_check_query = "SELECT id, UserName, Attribute, Value, op \
FROM ${authcheck_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"
authorize_reply_query = "SELECT id, UserName, Attribute, Value, op \
FROM ${authreply_table} \
WHERE Username = '%{SQL-User-Name}' \
ORDER BY id"
authorize_group_check_query = "SELECT ${groupcheck_table}.id, \
${groupcheck_table}.GroupName,${groupcheck_table}.Attribute, \
${groupcheck_table}.Value,${groupcheck_table}.op \
FROM ${groupcheck_table},${usergroup_table} \
WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' \
AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
ORDER BY ${groupcheck_table}.id"
authorize_group_reply_query = "SELECT ${groupreply_table}.id, \
${groupreply_table}.GroupName,${groupreply_table}.Attribute, \
${groupreply_table}.Value,${groupreply_table}.op \
FROM ${groupreply_table},${usergroup_table} \
WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' \
AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
ORDER BY ${groupreply_table}.id"
simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, \
NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol \
FROM ${acct_table1} \
WHERE UserName='%{SQL-User-Name}' \
AND AcctStopTime = 0"
group_membership_query = "SELECT GroupName FROM ${usergroup_table} \
WHERE UserName='%{SQL-User-Name}'"
postauth_query = "INSERT into ${postauth_table} (id, user, pass, reply, date) \
values ('', '%{User-Name}', '%{User-Password:-Chap-Password}', \
'%{reply:Packet-Type}', NOW())"
readclients = yes
}
/etc/freeradius/eap.conf
Nous avons décidé, en préparant notre système Wi-Fi, d'utiliser EAP-TLS pour l'authentification des utilisateurs. Lors de la création des certificats pour WPA2, nous avons créé :
- root_maison_CA-cacert.pem qui est le certificat de notre racine de confiance,
- sysop@maison.mrs-cert.pem qui est le certificat du serveur FreeRADIUS. Nous l'avons créé de manière à ce qu'il contienne la clé privée du serveur.
Nous allons utiliser ici ces deux certificats, qu'il faut placer dans le répertoire /etc/freeradius/certs.
Ce répertoire devrait contenir :
/etc/freeradius/certs# ls -l
total 12
-rw-r----- 1 root freerad 0 2007-03-12 11:11 dh
-rw-r----- 1 root freerad 3242 2007-03-12 15:38 maison.mrs-cert.pem
-rw-r----- 1 root freerad 1024 2007-03-12 11:11 random
-rw-r----- 1 root freerad 2610 2007-03-12 15:25 root_maison_CA-cacert.pem
Faites attention aux droits d'accès des fichiers de ce répertoire. Il suffit maintenant de modifier eap.conf de la sorte :
eap {
default_eap_type = tls
timer_expire = 60
ignore_unknown_eap_types = no
cisco_accounting_username_bug = no
tls {
private_key_password = epikoi
private_key_file = ${raddbdir}/certs/sysop@maison.mrs-cert.pem
certificate_file = ${raddbdir}/certs/sysop@maison.mrs-cert.pem
CA_file = ${raddbdir}/certs/root_maison_CA-cacert.pem
CA_path = ${raddbdir}/certs/
dh_file = ${raddbdir}/certs/dh
random_file = ${raddbdir}/certs/random
fragment_size = 1024
include_length = yes
check_crl = no
}
}
N'oublions pas de relancer FreeRadius pour qu'il prenne en compte la nouvelle configuration.
Premier test
Nous créons un « authenticator » de test dans la table « nas » :
# echo "INSERT INTO nas(nasname,shortname,secret) VALUES ('127.0.0.1','localhost','naspassword');" \
| mysql -u root -p radius
Nous créons un utilisateur de test dans « radcheck » :
# echo "INSERT INTO radcheck(UserName,Attribute,op,Value)
VALUES ('test0','User-Password','==','userpassword');" \
| mysql -u root -p radius
Notez que l'on utilise un mot de passe en clair dans la base, ce qui correspondra à un protocole « chap » pour l'authentification.
Enfin, depuis le serveur radius lui-même, qui va pour l'occasion cumuler le rôle d'authenticator, nous utilisons l'outil radtest :
# radtest test0 userpassword 127.0.0.1 0 naspassword
Sending Access-Request of id 146 to 127.0.0.1 port 1812
User-Name = "test0"
User-Password = "userpassword"
NAS-IP-Address = 255.255.255.255
NAS-Port = 0
rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=146, length=20
Notre solution fonctionne. Il ne nous reste qu'à ajouter dans la table « nas » nos switchs , nos points d'accès Wi-Fi, et dans la table « radcheck » toutes nos adresses MAC en guise d'utilisateurs pour le réseau filaire (« UserName » et « User-Password » identiques).
Pour les VLANs
La gestion des adresses MAC des clients
Il existe plusieurs méthodes pour collecter les adresses MAC de vos postes clients, comme par exemple les logiciels d'inventaire de parc (OCS Inventory NG, en est un).
La table « radcheck »
La table qui doit accueillir les « utilisateurs » s'appelle « radcheck ». Voyons de plus près la structure de cette table :
Entrer dans le détail des nombreuses possibilités de FreeRADIUS nous mènerait beaucoup trop loin. Dans le cadre de notre projet, nous devons créer une ligne par client de la manière suivante :
- Username contiendra l'adresse MAC du client, au format xx:yy:zz:aa:bb:cc, en lettres minuscules,
- Attribute contiendra le texte : « User-Password »,
- op contiendra « == »,
- Value contiendra également l'adresse MAC du client, au format xx:yy:zz:aa:bb:cc, en lettres minuscules.
Comme pour gérer dans la suite une telle collection de valeurs, il faudra savoir à quel client correspond une adresse MAC, je vous conseille vivement d'ajouter dans cette table une rubrique supplémentaire destinée à contenir, par exemple, le nom du client associé :
Il « suffit » ensuite de peupler cette base avec vos adresses MAC par la méthode qui vous conviendra le mieux. Ceci devrait aboutir à quelque chose de la forme :
mysql> select * from radcheck;
Il n'est pas nécessaire de relancer FreeRADIUS après modification de cette table.
La table « nas »
Il ne faut pas oublier non plus d'ajouter dans la table « nas » les informations concernant vos SWITCHs. La table « nas » est de structure suivante :
Nous devons avoir dans cette table, quelque chose qui ressemble à ceci :
Notez qu'une modification de la table « nas » nécessite (pour l'instant) un redémarrage de FreeRADIUS.
Normalement, tout devrait fonctionner correctement. Le client d'adresse MAC 00:05:5d:df:f4:5b devrait se retrouver sur le VLAN d'IP 2 (PARADIS_VLAN) alors qu'un client d'adresse MAC ne figurant pas dans la table « radcheck » se retrouvera dans le VLAN d'ID 3 (ENFER_VLAN).
Si vous rencontrez des problèmes, la première chose à faire est d'arrêter FreeRADIUS, puis de le relancer en « foreground » (avant-plan) en mode « debug », par la commande :
freeradius -x
ou, pour encore plus de détails :
freeradius -xx
FreeRADIUS est assez verbeux dans ce mode. Si, lors de la connexion d'un client, vous n'observez rien, c'est tout simplement que le switch ne dialogue pas avec le radius. Il faut alors en trouver la raison.
Si le dialogue démarre, il vous faudra déchiffrer le discours pour trouver la raison du disfonctionnement. Les raisons les plus probables étant :
- le radius ne reconnaît pas le switch (problème de secret partagé, de configuration du radius sur le switch, de configuration du switch dans la table « nas » du radius),
- le radius ne trouve pas le client dans sa base (erreur dans la table « radcheck »).
Pour WPA2
Configuration de eap
La table « nas »
Il nous faut ajouter notre borne Wi-Fi dans la table « nas ». Ici, nous utilisons une borne de type Netgear GW302, qui aura dans notre réseau l'adresse IP 192.168.10.3, comme nom « netgear » et qui utilisera « re-chutt » comme secret partagé avec le serveur radius. Nous devrions avoir dans notre table, quelque chose de ce genre :
Gestion des certificats des clients
Ici, la configuration va être extrêmement simple. Comme nous avons choisi d'utiliser WPA2-TLS, qui nécessite un certificat chez le client, il n'y aura à priori pas de base de noms d'utilisateurs à construire. Le serveur RADIUS va se contenter de vérifier l'authenticité du certificat présenté par le client. Si un client dispose d'un certificat valide, c'est bien qu'il est autorisé à se connecter.
Installation des certificats sur une machine Windows
Certificat de l'autorité
Dans le cas de Windows XP, nous avons besoin du certificat de notre racine de confiance (root_maison_CA) ainsi que du certificat client (user1). Ces certificats sont à installer par l'utilisateur et serviront à authentifier l'utilisateur. Entendez par là deux
points importants :
- l'attachement à la borne Wi-Fi ne pourra se faire qu'après ouverture d'une session,
- seule la session de l'utilisateur qui aura installé les certificats pourra permettre un attachement.
Commençons par le certificat de la racine de confiance. Double clic dessus, ce qui nous amène à :
Cette Autorité de certification étant inconnue de Microsoft, il nous appartient de décider si oui ou non, nous l'acceptons. Nous allons bien sûr installer ce certificat, non sans être certain que c'est bien le bon. Autrement, dit, il nous appartient de vérifier que ce certificat provient bien de chez nous.
« Installer ce certificat... » va nous conduire à un assistant :
dont le texte explicatif ne nécessite aucun commentaire.
Suivant :
Nous allons choisir nous même l'emplacement où ce certificat sera stocké.
« Parcourir... »
Nous choisissons logiquement les Autorités de certification racines de confiance.
L'assistant a fini son travail.
Mais, tout de même, nous avons encore droit à un bon gros avertissement de sécurité.
Encore une fois, si nous sommes certains de l'origine de ce certificat, nous pouvons y aller.
Certificat du client
Double clic sur le certificat client.
Ceci démarre un nouvel
assistant.
La seconde permet de vérifier le chemin d'accès au certificat que nous voulons enregistrer.
Suivant >
Suivant >
Le mot de passe demandé ici est celui qui a été spécifié lors de l'exportation au format PKCS#12 avec TinyCA (« Export password »).
Ici, nous pouvons choisir de sélectionner automatiquement le magasin.
Suivant >
Le reste ne présente pas d'intérêt particulier, l'installation doit se terminer sans encombres.
WPA2 et Windows XP
Windows XP, même avec le SP2, ne gère pas WPA2. Il faut lui ajouter un correctif à télécharger chez Microsoft (validation d'intégrité « Genuine Advantage » requise). Ce correctif s'appelle :
WindowsXP-KB893357-v2-x86-FRA.exe. A l'heure où ces lignes sont écrites, ce lien est valide.
Sans ce correctif, vous devrez vous contenter de WPA.
Une fois tout ceci réalisé, avec un peu de chance, la connexion devrait s'établir automatiquement pour l'utilisateur qui a installé les certificats.
En cas de problèmesVoici quelques éléments qui devraient vous aider à trouver la solution.
Voir les certificats installés
Une console « mmc » va nous venir en aide. Créons une console de gestion des certificats.
exécuter mmc...
Ajouter un composant logiciel enfichable...
Choisir le composant
« certificats »...
« Fermer »
Si vous avez un compte d'administrateur (ce qui, rappelons le, n'est pas une bonne idée, même si c'est le comportement par défaut de WIndows XP), vous aurez droit à choisir s'il s'agit de vos certificats (utilisateur) ou d'autres certificats, comme ceux qui
concernent l'ordinateur.
Si votre compte est celui d'un simple utilisateur, vous n'aurez pas ce choix et ne pourrez gérer que vos propres certificats, ce qui est suffisant dans notre cas.
« Terminer »
Si nous double cliquons
sur le certificat :
Nous voyons apparaître la racine de confiance associée.
La suite sous entend que les connexions wi-fi sont gérées par les outils Windows. Même si l'on peut admettre qu'ils sont plutôt rébarbatifs, peu ergonomiques à première vue, mon expérience personnelle ne m'en a pas fait découvrir de meilleurs parmi les nombreux « gadgets » fournis par les constructeurs de matériel wi-fi.
Faites apparaître les propriétés des connexions réseau sans fils :
Sélectionnez votre réseau et affichez ses propriétés,
Sur l'onglet « Association », assurez-vous que vous êtes bien sur le mode WPA2, avec un chiffrement AES,
Sur l'onglet « Authentification », le type EAP doit être « Carte à puce ou autre certificat ». Affichez ses propriétés,
Utilisez la sélection de certificat recommandée (simple), indiquez le nom complet du serveur RADIUS, tel qu'il a été défini dans son certificat, sélectionnez enfin le certificat de la racine d'autorité.
Ceci devrait enlever toute ambiguïté, en cas de troubles.
Installation du certificat sur une machine Linux
Contrairement à Windows, le moyen le plus simple d'obtenir l'attachement à un réseau Wi-Fi est de le faire au niveau du système. Entendez par là que l'authentification se fera lors du montage du réseau, au démarrage du système, ou lors de l'activation de l'interface Wi-Fi. Autrement dit, ce ne sera pas l'utilisateur qui sera authentifié, mais l'administrateur de la machine.
La manipulation est faite sur une distribution Ubuntu 6.10, où wpa-supplicant est normalement installé par défaut. Il y a sur cette distribution, deux interventions à faire. La première est typique aux distributions basées sur Debian et il vous faudra trouver comment adapter à une autre distribution.
L'interface Wi-Fi est une carte PCMCIA (cardbus) D-Link DWL-G650, qui utilise un chipset Atheros (Driver Madwifi).
Copie des certificats
L'installation du paquet wpasupplicant a créé un répertoire /etc/wpa_supplicant/. Nous pouvons créer dedans un répertoire « certs » et y mettre dedans nos deux certificats :
- root_maison_CA-cacert.pem pour l'autorité de certification,
- user1@maison.mrs-cert.pem pour le client.
Comme le contenu de ce répertoire est utilisé lors du démarrage, il n'y a aucune raison qu'il soit accessible par quiconque d'autre que root.
Configuration de l'interface wi-fi
Sur les Distributions Debian et dérivées, il faut agir sur le fichier /etc/network/interfaces :
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
auto ath0
iface ath0 inet dhcp
wpa-driver madwifi
wpa-conf /etc/wpa_supplicant.conf
...
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
auto ath0
iface ath0 inet dhcp
wpa-driver madwifi
wpa-conf /etc/wpa_supplicant.conf
...
Configuration de wpa-supplicant
wpa-supplicant mériterait à lui seul tout un chapitre. Son fonctionnement n'est pas d'une évidence extrême, et sa configuration non plus.
Il faut créer un fichier /etc/wpa_supplicant.conf, comme indiqué dans /etc/network/interfaces, qui indiquera, réseau par réseau (ici, un seul suffira), les paramètres nécessaires à l'attachement.
Voici un exemple de configuration dans notre contexte :
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
network={
ssid="maison"
scan_ssid=0
key_mgmt=WPA-EAP
eap=TLS
proto=WPA2
pairwise=CCMP TKIP
group=CCMP TKIP
identity="user1"
ca_cert="/etc/wpa_supplicant/certs/root_maison_CA-cacert.pem"
client_cert="/etc/wpa_supplicant/certs/user1@maison.mrs-cert.pem"
private_key="/etc/wpa_supplicant/certs/user1@maison.mrs-cert.pem"
private_key_passwd="epikoi"
}
Il n'y a rien d'incompréhensible dans ce fichier, la difficulté réside surtout dans le fait d'utiliser les bons paramètres. Pour vous aider, vous avez dans le répertoire /usr/share/doc/wpasupplicant/examples/ quelques exemples de configuration ainsi qu'un fichier « wpa_supplicant.conf.gz » très largement documenté, qui passe en revue tous les paramètres possibles.
C'est bien mais...
Cette solution ne nous permet pas de gérer les « coups durs ». Comment faire en effet si l'on apprend qu'un certificat encore valide a été compromis ? Car dans cette configuration, une fois un certificat installé, il sera accepté par FreeRADIUS tant qu'il n'aura pas expiré.
Révocations
Comment gérer les impondérables ?
Dans notre solution globale, nous gérons le réseau filaire par une authentification de type « login/password » où l'adresse MAC joue le rôle des deux composants. Nous disposons d'une base de données MySQL (ou Postgresql) qui recense toutes les adresses MAC connues. Nous avons pu tester son bon fonctionnement en utilisant un « login/password » introduit dans la base de données.
En ce qui concerne le réseau Wi-Fi, nous avons confié à EAP l'authentification, via le protocole TLS. Nous avons vu que, dans ce cas, tout se passe par l'intermédiaire des certificats, et qu'il n'y a aucune information dans la base de données.
Comment faire alors si pour une raison ou une autre, nous devions être amenés à bloquer un utilisateur disposant d'un certificat en cours de validité ? Il peut y avoir plusieurs raisons qui pourraient amener à cette résolution, comme :
- un vol déclaré de la machine sur laquelle le certificat a été installé,
- un utilisateur autorisé pour une certaine durée, mais qui pour une raison ou une autre, n'a plus rien à faire sur notre réseau, temporairement ou définitivement (non respect de la charte des utilisateurs, démission, etc.).
Dans notre configuration actuelle, ce type de situation ne peut être géré, il nous faut trouver une solution, si possible pas trop complexe à maintenir.Deux voies sont à explorer :
- l'utilisation de certificats de révocation,
- trouver un moyen pour qu'en plus de l'authentification par certificats, le nom d'utilisateur doive être présent dans la base de données pour autoriser l'attachement.
Certificat de révocation
TinyCA sait générer simplement des certificats de révocation, et FreeRADIUS peut être configuré assez simplement pour en tenir compte. Cette solution offre cependant deux gros défauts pour la maintenance :
- à chaque nouvelle suspension de compte, il faut révoquer le certificat correspondant au compte suspendu, recréer un nouveau certificat de révocations, l'exporter, l'installer sur le serveur puis redémarrer le serveur,
- en cas de suspension provisoire, un certificat révoqué doit être recréé puis réinstallé sur la machine cliente à la fin de la suspension du compte.
Usage de la base de données
Etat des lieux
Si nous trouvons un moyen pour que le certificat client ne soit accepté que si l'utilisateur est référencé dans la base, les choses deviendraient beaucoup plus simples, il suffirait d'ajouter ou de supprimer une ligne dans la base pour suspendre, temporairement ou non, un compte d'utilisateur, même si le certificat est encore en cours de validité.
Cette solution nous obligera à créer une ligne par utilisateur Wi-Fi dans notre base de données, en plus du certificat, mais nous permettra de gérer nettement plus facilement les impondérables.
Pour arriver à ce résultat, il va nous falloir entrer plus en profondeur dans le fonctionnement de RADIUS. Dans notre configuration très simple, nous ne définissons pas de type d'authentification approprié à chaque requête. Le résultat est que pour chaque requête, tous les types d'authentification possibles sont testés, si l'un d'entre eux renvoie « Accept », l'autorisation est donnée.
Actuellement, nous avons :
Cette solution n'est clairement pas facile à gérer.
authorize {
preprocess
eap
sql
}
C'est à dire que nous autoriserons les connexions soit par EAP, soit par la base de données sql, et nous n'avons défini nulle part de façon explicite le mode d'authentification pour un utilisateur donné. Le résultat est que :
- tout client présentant un certificat valide sera autorisé via « eap »,
- tout client présentant un « login/password » présent dans la base sera autorisé en mode « local » via « sql ».
Que se passerait-il, si nous trouvions le moyen de fixer le mode d'authentification par défaut ?
Fixer un mode d'authentification par défaut
Ceci peut se réaliser par l'intermédiaire du fichier « users », à la condition d'ajouter « files » dans la section « authorize » de radiusd.conf. Si nous arrivons à forcer le serveur à rejeter par défaut toute authentification, puis à l'autoriser à utiliser un mode particulier pour un utilisateur donné, nous serons proches de la solution.
Fichier « users »
Nous mettons dans « users » la simple ligne « DEFAULT Auth-Type := Reject ». Par défaut, l'autorisation devrait ainsi être refusée à tout le monde :
# cat users
DEFAULT Auth-Type := Reject
Le problème étant maintenant d'attribuer un type d'authentification correct aux utilisateurs Wi-Fi connus. Il faut le faire avant de définir le mode par défaut. Fort heureusement, les autorisations sont lues séquentiellement dans la section « authorize ».
Fichier « radiusd.conf »
authorize {
preprocess
sql
files
eap
}
A part que, avec cette écriture, lorsque l'on sort d'un module on entre dans le suivant, quelle que soit la réponse du module précédent, pourvu qu'il n'y ait pas eu de « Reject ». Ici, même si SQL accorde un « Auth-Type := EAP » à un utilisateur connu, cette valeur sera écrasée par le Auth-Type par défaut du fichier « users »; et donc personne ne sera autorisé, ce n'est pas ce que nous voulons.
Si nous plaçons files avant sql, ça ne fonctionnera pas non plus, puisque le type d'authentification « Reject » sera rencontré en premier, mettant fin à la procédure.
Fort heureusement, le mode « fail-over » va venir à notre secours sous cette forme :
authorize {
preprocess
redundant {
sql
files
eap
}
}
Ainsi, lorsqu'un utilisateur est trouvé dans la base sql, soit il sera authentifié en mode Local, si son mot de passe est indiqué (pour les autorisations depuis les adresses MAC), soit, si un mode d'authentification de type TLS lui est attribué, EAP fonctionnera.
Si en revanche aucun mode d'authentification n'est attribué, c'est le mode par défaut qui passera et, même avec un certificat valide, l'utilisateur devrait être rejeté.
Essayons un « login/password » :
Sending Access-Request of id 25 to 127.0.0.1 port 1812
User-Name = "test0"
User-Password = "userpassword"
NAS-IP-Address = 255.255.255.255
NAS-Port = 0
rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=25, length=20
C'est bon. Essayons maintenant le Wi-Fi avec un certificat valide, présentant le nom d'utilisateur userwifi1, non répertorié dans la base des utilisateurs, l'authentification échouera. Si maintenant nous ajoutons ceci dans la base :
# echo "INSERT INTO radcheck(UserName,Attribute,op,Value)
VALUES ('userwifi1','Auth-Type',':=','EAP');" \
| mysql -u root -p radius
L'authentification eap devrait réussir. Voyons un « best-of » des logs de freeradius lancé en mode « debug » :
rad_recv: Access-Request packet from host 192.168.10.3:1046, id=19, length=163
User-Name = "userwifi1"
NAS-IP-Address = 192.168.10.3
Connect-Info = "CONNECT 802.11"
Called-Station-Id = "000f3dab9ac9"
Calling-Station-Id = "000fb572abe0"
NAS-Identifier = "00-0f-b5-72-ab-e0"
NAS-Port-Type = Wireless-802.11
NAS-Port = 1
NAS-Port-Id = "1"
Framed-MTU = 1400
EAP-Message = 0x0201001201636c6e74302e6274732e656d65
Message-Authenticator = 0x417f19394ab35a5eda42ffb628855e41
rlm_sql (sql): Reserving sql socket id: 3
rlm_sql (sql): Released sql socket id: 3
Sending Access-Challenge of id 19 to 192.168.10.3 port 1046
EAP-Message = 0x010200060d20
Message-Authenticator = 0x00000000000000000000000000000000
State = 0xee660260336863b8917d0c319918e83e
...
...
...
error=0
--> User-Name = userwifi1
--> BUF-Name = root_maison_CA
--> subject =
/C=FR/ST=France/L=Marseille/O=Maison/OU=Reseau_maison/CN=root_maison_CA/emailAddress=user1@maison.mr
s
--> issuer =
/C=FR/ST=France/L=Marseille/O=Maison/OU=Reseau_maison/CN=root_maison_CA/emailAddress=user1@maison.mr
s
--> verify return:1
chain-depth=0,
error=0
--> User-Name = userwifi1
--> BUF-Name = userwifi1
--> subject =
/C=FR/ST=France/L=Marseille/O=Maison/OU=Reseau_maison/CN=userwifi1/emailAddress=userwifi1
--> issuer =
/C=FR/ST=France/L=Marseille/O=Maison/OU=Reseau_maison/CN=root_maison_CA/emailAddress=user1@maison.mr
s
--> verify return:1
rlm_eap: SSL error error:00000000:lib(0):func(0):reason(0)
Sending Access-Challenge of id 26 to 192.168.10.3 port 1046
EAP-Message = 0x010900350d800000002b1403010001011603010020bea471f3b5...
Message-Authenticator = 0x00000000000000000000000000000000
State = 0xf22d9e05e6fc415b67c3b36def7a809d
rad_recv: Access-Request packet from host 192.168.10.3:1046, id=27, length=169
User-Name = "userwifi1"
NAS-IP-Address = 192.168.10.3
Connect-Info = "CONNECT 802.11"
Called-Station-Id = "000f3dab9ac9"
Calling-Station-Id = "000fb572abe0"
NAS-Identifier = "00-0f-b5-72-ab-e0"
NAS-Port-Type = Wireless-802.11
NAS-Port = 1
NAS-Port-Id = "1"
Framed-MTU = 1400
State = 0xf22d9e05e6fc415b67c3b36def7a809d
EAP-Message = 0x020900060d00
Message-Authenticator = 0x1a08bc62c3852a0b6436c016ba81dfd6
rlm_sql (sql): Reserving sql socket id: 0
rlm_sql (sql): Released sql socket id: 0
Sending Access-Accept of id 27 to 192.168.10.3 port 1046
MS-MPPE-Recv-Key = 0xd6a70248ae96a9e5621d6053bad74de70db8b358ad3e79bcda1351ec50375873
MS-MPPE-Send-Key = 0xf418a1cf92136b7e5b948dd0fbf51a0b7a95b06456abc4e15c4df200e57cc29c
EAP-Message = 0x03090004
Message-Authenticator = 0x00000000000000000000000000000000
User-Name = "userwifi1"
Vérifions tout de même que si l'utilisateur est supprimé de la table « radcheck », l'authentification va échouer :
image
Le log de freeradius deviendra beaucoup plus court :
rad_recv: Access-Request packet from host 192.168.10.3:1046, id=28, length=163
User-Name = "userwifi1"
NAS-IP-Address = 192.168.10.3
Connect-Info = "CONNECT 802.11"
Called-Station-Id = "000f3dab9ac9"
Calling-Station-Id = "000fb572abe0"
NAS-Identifier = "00-0f-b5-72-ab-e0"
NAS-Port-Type = Wireless-802.11
NAS-Port = 1
NAS-Port-Id = "1"
Framed-MTU = 1400
EAP-Message = 0x0201001201636c6e74302e6274732e656d65
Message-Authenticator = 0x0c3f20db2c9341cac65bff1c4bf17e37
rlm_sql (sql): Reserving sql socket id: 3
rlm_sql (sql): User userwifi1 not found in radcheck
rlm_sql (sql): User userwifi1 not found in radgroupcheck
rlm_sql (sql): Released sql socket id: 3
rlm_sql (sql): User not found
Sending Access-Reject of id 28 to 192.168.10.3 port 1046
Nous n'avons plus trop besoin de gérer de certificats de révocation.
Une méthode encore plus propre
Ce que nous venons de voir va nous contraindre à mélanger dans la même table les utilisateurs qui disposent d'une authentification de type CHAP (réseau filaire) et EAP (réseau Wi-Fi). Les tables « radgroupcheck » et « usergroup » vont nous aider à séparer les deux types d'utilisateurs, dans des tables différentes.
L'idée est la suivante. Nous allons créer un groupe d'utilisateur nommé « wifiGroup » (dans la table « radgroupcheck »), auquel nous allons appliquer l'attribut « Auth-Type := EAP ». Il suffira ensuite d'intégrer nos utilisateurs Wi-Fi dans ce groupe (dans la table « usergroup »), pour qu'ils héritent de l'attribut.
mysql> INSERT INTO radgroupcheck(GroupName,Attribute,op,Value) \
VALUES ('wifiGroup','Auth-Type',':=','EAP');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO usergroup(UserName,GroupName) VALUES ('userwifi1','wifiGroup');
Query OK, 1 row affected (0.00 sec)
Freeradius considèrera que tous les membres du groupe « wifiGroup » doivent être identifiés via EAP, et les membres de ce groupe sont tous définis dans la table « usergroup ». De cette manière, il sera plus facile de gérer les deux types d'utilisateurs.
--------------------------------------------------------------------------------------------
Article plus récent Article plus ancien