[ Articles -> Conception d'un portail captif simple (niveau 3 du modèle OSI) ]
Cet article a pour objectif de décrire la conception d'un portail captif simple, en environnement GNU/Linux, opérant au niveau 3 du modèle OSI.
De bonnes connaissances en réseau sont nécessaires pour la compréhension de cet article.
Le portail captif est une technique mise en oeuvre sur une passerelle d'accès permettant de bloquer toute commutation externe et de forcer le client à se connecter sur une page Web, en redirigeant toutes les requêtes HTTP vers le serveur cible.
Cette technique a principalement pour objectif l'authentification du client sur le réseau. C'est une alternative légère et plus simple à utiliser pour les clients néophytes que l'authentification 802.1x (radius), c'est pourquoi elle est couramment utilisée sur les réseaux Wi-Fi ouverts.
Pour la suite de l'article, nous prendrons en considération le réseau 10.100.1.0/24, ayant pour passerelle (route par défaut des clients) 10.100.1.1.
Notre passerelle a pour interface "interne" eth1 (10.100.1.1) et pour interface "externe" eth0.
Il existe 2 types de portails qui agissent respectivement aux niveaux 2 (liaison) et 3 (réseau) du modèle OSI. Le plus courant est le portail captif de niveau 3, c'est donc sur celui-ci que nous nous attarderons.
Nous ferons abstraction du routage (éventuellement du NAT en postrouting), qui n'est pas le propos de l'article, et qui est considéré comme acquis et déjà en place.
La passerelle tourne sous un OS à base de Debian (Linux). Les paquets suivants doivent être installés :
Les règles configurées avec IPtables doivent permettre trois choses :
Pour la suite, on définit quatre variables Bash :
1 INT_IF=eth1 2 EXT_IF=eth0 3 IP_CAPTIVE_PORTAL=10.100.1.1 4 IPTABLES=/sbin/iptables
Très simple :
1 ### Deny FORWARD by default 2 $IPTABLES -A FORWARD -i $INT_IF -o $EXT_IF -j DROP
Le fait de forcer le serveur DNS est utile pour la suite (déclaration d'un domaine local), et permet d'éviter les tunnels IP over DNS (d'autant que de toute façon la commutation est bloquée).
Là encore, la configuration iptables est très simple :
1 ### Redirects HTTP requests from unloggued users to the logon web page - DNS forcing 2 3 $IPTABLES -t nat -I PREROUTING -i $INT_IF -p tcp --dport 80 -j DNAT --to-destination $IP_CAPTIVE_PORTAL 4 $IPTABLES -t nat -I PREROUTING -i $INT_IF -p udp --dport 53 -j DNAT --to-destination $IP_CAPTIVE_PORTAL
Il peut être intéressant, quand on est FAI, d'autoriser les clients non authentifiés à se connecter au site web du-dit FAI, afin d'enregistrer des abonnements.
En supposant que l'IP du serveur hébergant le site web du FAI soit 212.27.48.10, on entre les commandes suivantes :
1 # Allow free forwarding for 212.27.48.10 2 3 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 212.27.48.10 -j ACCEPT 4 $IPTABLES -I FORWARD -i $INT_IF -d 212.27.48.10 -j ACCEPT
On peut aussi autoriser le trafic à destination de PayPal, utile en cas de paiement en ligne pour l'abonnement :
1 # Allow free forwarding for PayPal 2 3 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 66.211.169.0/24 -j ACCEPT 4 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 64.4.241.0/24 -j ACCEPT 5 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 72.246.0.0/15 -j ACCEPT 6 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 216.113.160.0/19 -j ACCEPT 7 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 66.235.128.0/19 -j ACCEPT 8 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 66.135.192.0/19 -j ACCEPT 9 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 66.151.153.9 -j ACCEPT 10 $IPTABLES -t nat -I PREROUTING -i $INT_IF -d 173.0.80.0/20 -j ACCEPT 11 12 $IPTABLES -I FORWARD -i $INT_IF -d 66.211.169.0/24 -j ACCEPT 13 $IPTABLES -I FORWARD -i $INT_IF -d 64.4.241.0/24 -j ACCEPT 14 $IPTABLES -I FORWARD -i $INT_IF -d 72.246.0.0/15 -j ACCEPT 15 $IPTABLES -I FORWARD -i $INT_IF -d 216.113.160.0/19 -j ACCEPT 16 $IPTABLES -I FORWARD -i $INT_IF -d 66.235.128.0/19 -j ACCEPT 17 $IPTABLES -I FORWARD -i $INT_IF -d 66.135.192.0/19 -j ACCEPT 18 $IPTABLES -I FORWARD -i $INT_IF -d 66.151.153.9 -j ACCEPT 19 $IPTABLES -I FORWARD -i $INT_IF -d 173.0.80.0/20 -j ACCEPT
Bloquer et rediriger le trafic est une chose, mais lorsque le client est authentifié, il faut pouvoir l'autoriser à bypasser le portail captif.
Libre à vous d'utiliser le langage de programmation de votre choix pour l'interface client, il vous faudra après authentification rajouter deux règles iptables pour l'adresse MAC spécifique.
Par exemple, pour autoriser l'adresse MAC 5E:FF:56:A2:AF:15 à se connecter, on exécute les commandes suivantes :
1 /sbin/iptables -t nat -I PREROUTING -m mac --mac-source 5E:FF:56:A2:AF:15 -j ACCEPT 2 /sbin/iptables -I FORWARD -m mac --mac-source 5E:FF:56:A2:AF:15 -j ACCEPT
Le but du portail est bien sûr de pouvoir authentifier de façon automatique des utilisateurs.
Pour ce faire, le programme executé sur le serveur doit posséder des droits suffisants pour faire appel à iptables (root). En prenant l'exemple d'un script PHP, appelé par Apache (serveur web), apache doit posséder des droits suffisants.
Pour ce faire, on utilise sudo, en rajoutant la ligne suivante dans le sudoers (avec la commande visudo) :
1 # visudo 2 www-data ALL = NOPASSWD: /sbin/iptables
En PHP, l'implémentation d'une fonction permettant d'autoriser une adresse MAC à se connecter peut donner le code suivant :
1 <?php 2 3 function enableMac($mac='inconnue') 4 { 5 if($mac == 'inconnue') 6 { 7 $mac = shell_exec('/usr/sbin/arp -na '.$_SERVER['REMOTE_ADDR']); 8 preg_match('/..:..:..:..:..:../',$mac , $matches); 9 @$mac = $matches[0]; 10 } 11 12 $r1 = shell_exec("sudo /sbin/iptables -t nat -I PREROUTING -m mac --mac-source $mac -j ACCEPT"); 13 $r2 = shell_exec("sudo /sbin/iptables -I FORWARD -m mac --mac-source $mac -j ACCEPT"); 14 15 return $r1.$r2; 16 } 17 18 ?>
Ainsi s'achève la conception de notre portail captif de niveau 3.
À titre d'exemple d'amélioration, il est possible prévoir une redirection du client sur un domaine dédié à l'authentification (ex : auth.mon-fai.fr), avec un bon paramétrage DNS. Il est aussi possible (et conseillé) de proposer une version HTTPS (SSL / TLS) du portail captif, afin de garantir la sécurité de l'authentification sur réseau ouvert.
J'espère avoir correctement traité ce sujet, et je tiens à remercier l'association Quantic Télécom pour les sources et codes présentés ici.