Mise en place de FreeRadius
 23/03/2007 
 Christian CALECA 
Liste des cours

Révocations

Accueil ] [ FreeRADIUS ] [ Pour les VLANs ] [ Pour WPA2 ] [ 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 :

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 :

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 :

Cette solution n'est clairement pas facile à gérer.

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 :

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 :

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.mrs
--> issuer  = /C=FR/ST=France/L=Marseille/O=Maison/OU=Reseau_maison/CN=root_maison_CA/emailAddress=user1@maison.mrs
--> 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.mrs
--> 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 :

mysql> select * from radcheck;
+----+---------------+---------------+----+--------------+---------+
| id | UserName      | Attribute     | op | Value        | Comment |
+----+---------------+---------------+----+--------------+---------+
|  1 | test0         | User-Password | == | userpassword | NULL    |
| 11 | userwifi1     | Auth-Type     | := | EAP          | NULL    |
+----+---------------+---------------+----+--------------+---------+
2 rows in set (0.00 sec)
mysql> delete from radcheck where id = 11;
Query OK, 1 row affected (0.00 sec)

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.

Conclusion

Nous sommes loin d'avoir vu tout ce qu'il est possible de faire avec RADIUS, mais nous avons réalisé ce que nous voulions faire.

Dans le cas du réseau filaire, il est également possible d'attribuer un ID de VLAN différent suivant l'utilisateur authentifié, de même qu'il est possible de remplacer EAP-TLS par PEAP, si l'on dispose par exemple d'un annuaire ActiveDirectory et que l'on souhaite que les clients Wi-Fi soient authentifiés avec leur "login/password" du réseau Microsoft, plutôt que par un certificat. La machine qui héberge FreeRadius doit alors être intégrée au domaine Microsoft et pouvoir interroger l'annuaire ActiveDirectory. A mon sens, EAP-TLS reste préférable.


Précédente ] [ Accueil ]