Freeradius style « DHCP » et haute disponibilité
Aujourd’hui, nous allons installer des serveurs Radius qui distribueront des adresses IP à des équipements munis de cartes SIM Data.
Le contexte
Nous sommes dans une entreprise qui a environ 2000 équipements équipés de cartes SIM Data. Ces équipements doivent être capables de récupérer une adresse IP et des serveurs DNS via un APN dédié.
Facile ! Il suffit d’aller voir Bouygues Telecom, SFR ou Orange (FT, Orange Business Services et C°), et ils nous installent un bel APN dédié avec le nom qu’on veut en 5 minutes (ou plutôt 6 mois minimum avec 100 réunions, 100 tests qui échouent et pas mal d’€ dépensés). Bref le sujet est autre et enfin, un jour, l’APN dédié est livré.
Nous, on souhaite avoir les radius chez nous pour mieux contrôler ce qu’il se passe de bout en bout. On choisit bien entendu une solution Open Source qui sera faite de 2 serveurs Linux Debian Squeeze pour la haute disponibilité et qui embarqueront chacun un service FreeRadius.
La gestion de l’authentification et de l’autorisation
Il faut bien comprendre que le client Radius est le GGSN/NAS de l’opérateur Télécom et c’est donc lui qui va demander à notre serveur Radius de délivrer l’adresse IP. Dans un 1er temps, l’équipement va s’authentifier sur l’APN dédié et communiquer son login utilisateur et son mot de passe. Le GGSN va relayer les identifiants de connexion à notre Radius en créant une requête Access-Request qui contiendra la futur IP destinée à l’équipement.
Exemple de requête :
Packet-Type = Access-Request Calling-Station-Id = "33650xxxxxx" User-Name = "user@mondomaine.fr" NAS-IP-Address = 192.xx.xx.xx NAS-Identifier = "ggsn1" Service-Type = Framed-User Framed-Protocol = GPRS-PDP-Context NAS-Port-Type = Wireless-Other Called-Station-Id = "apn.fr" NAS-Port = 235858
Notre Radius va lui répondre par un Access-Accept (ou Access-Reject).
Exemple de requête :
Packet-Type = Access-Accept Login-IP-Host = IP du radius Framed-Route = (?) MS-Primary-DNS-Server = IP DNS primaire MS-Secondary-DNS-Server = IP DNS secondaire Framed-IP-Address = IP allouée à l'équipement
Accounting request
Une fois que l’équipement est autorisé à utiliser le réseau, le GGSN/NAS va envoyer une requête Accounting Start à notre Radius pour lui indiquer que l’équipement est actuellement connecté au réseau. Lorsque l’équipement se déconnectera du réseau, le GGSN le détectera et l’indiquera à notre Radius en envoyant une requête Accounting Stop. La conséquence pour notre Radius sera de libérer l’adresse IP.
Le module rlm_ippool de Freeradius
Par la suite on comprend vite quand utilisant le module rlm_ippool de Freeradius, on va se retrouver très vite avec un problème au niveau du pool d’adresses IP. En effet le vieillissement des IP n’est pas pris en compte avec ce module.
Lorsqu’un équipement va se connecter la 1ère fois, tout va bien se passer. Puis cet équipement va rebooter ou se déconnecter, alors le GGSN/NAS de l’opérateur Télécom va indiquer à notre Freeradius de libérer l’adresse IP (requête Accounting Stop). Cependant il arrive souvent (par expérience) que la requête de libération d’IP envoyée par le GGSN/NAS n’arrive pas au Radius. Comme l’architecture redondée des GGSN de notre opérateur Télécom fonctionne en ACTIF/ACTIF ou en ACTIF/PASSIF, il se peut que le GGSN qui avait initié la connexion ne soit pas le même qui la termine. Par conséquent, lentement mais surement, il n’y a plus d’adresse à distribuer et plus aucun nouvel équipement ne peut se connecter.
Nous allons donc utiliser dans cet article le module rlm_sqlippool qui permet d’indiquer une durée de vie aux adresses IP, un peu à la façon d’un serveur DHCP.
Installation des Freeradius avec le module rlm_sqlippool
Après avoir installé la Debian, on installe sur chaque serveur :
Mysql
apt-get update apt-get install mysql-server
Freeradius
apt-get update apt-get install freeradius apt-get install freeradius-mysql
Configuration
Mysql
Création de la base :
# mysql -u root -p mysql> CREATE DATABASE freeradius
Création de l’utilisateur pour la base :
mysql> CREATE USER 'userfreeradius'@'localhost' IDENTIFIED BY 'pwdfreeadius'; mysql>GRANT USAGE ON * . * TO 'userfreeradius'@'localhost' IDENTIFIED BY '
pwdfreeadius
'; mysql>GRANT ALL PRIVILEGES ON `freeradius` . * TO 'userfreeradius'@'localhost';
Création des tables :
# mysql -u userfreeradius -p pwdfreeadius freeradius < /etc/freeradius/sql/mysql/schema.sql # mysql -u userfreeradius -p pwdfreeadius freeradius< /etc/freeradius/sql/mysql/nas.sql # mysql -u userfreeradius -p pwdfreeadius freeradius < /etc/freeradius/sql/mysql/ippool.sql
Paramétrage des fichiers Freeradius
– Éditer le fichier /etc/freeradius/radiusd.conf et décommenter dans la section « modules » les lignes suivantes :
$INCLUDE sqlippool.conf $INCLUDE sql.conf
– Éditer le fichier /etc/freeradius/sql.conf et renseigner les champs relatifs à la base de données :
sql { database = "mysql" driver = "rlm_sql_${database}" server = "localhost" #port = 3306 login = "userfreeradius" password = "pwdfreeradius" radius_db = "freeradius" acct_table1 = "radacct" acct_table2 = "radacct" postauth_table = "radpostauth" authcheck_table = "radcheck" authreply_table = "radreply" groupcheck_table = "radgroupcheck" groupreply_table = "radgroupreply" usergroup_table = "radusergroup" read_groups = yes deletestalesessions = yes sqltrace = no sqltracefile = ${logdir}/sqltrace.sql num_sql_socks = 150 connect_failure_retry_delay = 60 lifetime = 0 max_queries = 0 readclients = yes nas_table = "nas" $INCLUDE sql/${database}/dialup.conf }
– Éditer le fichier /etc/freeradius/users. C’est ce fichier qui indique comment on authentifie et on autorise les clients. C’est aussi dans ce fichier que vous indiquez les DNS qui seront reçus par les clients. (man page : http://freeradius.org/radiusd/man/users.html et pour la liste des attributs : http://www.freeradius.org/rfc/attributes.html)
user@mondomaine.fr Pool-Name := "pool1", # indique le pool IP à utiliser NAS-IP-Address == 192.X.X.X, # vérifie l'adresse IP du GGSN (NAS) User-Password := "test", # vérifie le mot de passe utilisateur MS-Primary-DNS-Server = @IP_DNS_PRIMAIRE, MS-Secondary-DNS-Server = @IP_DNS_SECONDAIRE, Fall-Through = yes # si les conditions ne sont pas remplies, il faut tester avec la suite
user@mondomaine.fr Pool-Name := "pool2", # indique le pool IP à utiliser NAS-IP-Address == 192.Y.Y.Y, # vérifie l'adresse IP du GGSN (NAS) User-Password := "test", # vérifie le mot de passe utilisateur MS-Primary-DNS-Server = @IP_DNS_PRIMAIRE, MS-Secondary-DNS-Server = @IP_DNS_SECONDAIRE,
– Éditer le fichier /etc/freeradius/sqlippool.conf :
sqlippool {
sql-instance-name = "sql"
ippool_table = "radippool"
## IP lease duration. (Indiquez ici la durée de vie des IP)
lease-duration = 86400 # 24 H
pool-key = "%{NAS-Port}"
$INCLUDE sql/mysql/ippool.conf
...
}
– Éditer le fichier /etc/freeradius/sites-available/default et modifier la section « accounting » tel que :
# Return an address to the IP Pool when we see a stop record. # main_pool sqlippool
Et dans la section « post-auth » :
# Get an address from the IP Pool. # main_pool sqlippool
Vérifiez qu’il existe bien un lien symbolique de /etc/freeradius/sites-enable/default vers /etc/freeradius/sites-available/default
– Éditer le fichier /etc/freeradius/clients.conf et indiquer l’adresse IP des 2 GGSN ainsi que le secret partagé :
client 192.xx.xx.xx { secret = mysecret shortname = GGSN1 nastype = other } client 192.yy.yy.yy { secret = mysecret shortname = GGSN2 nastype = other }
Création du Pool IP
Ajouter le pool d’IP dans la table radippool pour le GGSN1 :
mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool1', '192.168.0.1'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool1', '192.168.0.2'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool1', '192.168.0.3'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool1', '192.168.0.4'); ...
Puis pour le GGSN2 :
mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool2', '192.169.0.1'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool2', '192.169.0.2'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool2', '192.169.0.3'); mysql> INSERT INTO radippool (pool_name, framedipaddress) VALUES ('pool2', '192.169.0.4'); ...
Test
L’équipement se connecte le 08/06/2010 à 17h17 et on a dans la base de données :
id |
pool_name |
framedipaddress |
nasipaddress |
callingstationid |
expiry_time |
username |
pool_key |
|
1 |
pool1 |
192.168.0.1 |
192.xx.xx.xx |
33650xxxxxx |
2010-06-09 17:17:47 |
user@mondomaine.fr |
136042 |
Quand l’équipement se déconnectera, soit le GGSN envoie bien une requête « Accounting Stop » et le champ « expiry_time » passera à NULL, soit nos radius ne reçoivent rien et l’adresse IP pourra être à nouveau utilisée lorsque sa durée de vie aura expirée.