Portail captif
Source de la documentation : https://projectzme.wordpress.com
Procédure validée sur Debian 8.
Présentation du projet
La technique de portail captif (captive portal) consiste à forcer les clients HTTP d'un réseau de consultation à afficher une page web spéciale (le plus souvent dans un but d'authentification) avant d'accéder à Internet normalement.
Source : Wikipedia
Nous allons installer ce portail captif sur un ordinateur équipé de deux cartes réseaux :
- eth0
- Carte connectée à Internet, en DHCP.
- eth1
- Carte connectée au réseau à soumettre au portail captif. Adresse : 10.0.0.254/24. Un serveur DHCP.
Installation des paquets et configuration réseau
Nous allons installer les paquets nécessaires :
apt-get install apache2 php5 conntrack sudo isc-dhcp-server
Configurer les interfaces réseau comme suit en éditant le fichier /etc/network/interfaces :
auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp auto eth1 iface eth1 inet static address 10.0.0.254 network 10.0.0.0 netmask 255.255.255.0 post-up bash /etc/iptables.rules.sh
Valider la configuration réseau :
service networking restart
Configurer le serveur DHCP. Pour cela, éditez le fichier /etc/dhcp/dhcpd.conf et ajouter ce qui suit :
subnet 10.0.0.0 netmask 255.255.255.0 { range 10.0.0.10 10.0.0.200; option routers 10.0.0.254; option domain-name-servers 87.98.175.85; # DNS OpenNIC ns10.fr option subnet-mask 255.255.255.0; option broadcast-address 10.0.0.255; }
Redémarrer le serveur DHCP :
service isc-dhcp-server restart
Activer le routage en décommentant la ligne suivante dans le fichier /etc/sysctl.conf :
net.ipv4.ip_forward=1
Redirection du trafic vers le portail captif
Nous allons activer le NAT, identifier le trafic des clients et le rediriger vers le portail captif. Pour cela, créer le fichier /etc/iptables.rules.sh :
iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE iptables -t mangle -N internet iptables -t mangle -A internet -j MARK --set-mark 99 iptables -t mangle -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j internet iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 -m tcp --dport 80 -j DNAT --to-destination 10.0.0.254 iptables -t mangle -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j internet iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 -m tcp --dport 443 -j DNAT --to-destination 10.0.0.254
Nous avons fait en sorte que le script soit exécuté après la configuration de l'interface eth1 lors de l'édition du fichier /etc/network/interfaces.
Création du portail captif
Notre portail captif comportera trois pages :
- index.php
- La page sur laquelle sera redirigée les utilisateurs non connectés (y mettre les CGU de votre service ou un formulaire d'authentification).
- process.php
- La page traitant les demandes d'authentification.
- kick.php
- Cette page permet de révoquer l'authentification d'un utilisateur et l'oblige à s'authentifier de nouveau.
Notre exemple présentera une page avec un simple lien afin d'accéder à Internet.
Voici le contenu de la page index.php :
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="author" content="Antoine Pernot"> <title>Portail captif</title> </head> <body> <h1>Portail captif</h1> <p>Cliquez <a href="http://10.0.0.254/process.php">ici</a> pour accéder à Internet. </p> </body> </html>
Voici le contenu de la page process.php.
<?php $ip = $_SERVER['REMOTE_ADDR']; $arp = "/usr/sbin/arp"; $mac = shell_exec("sudo $arp -an " . $ip); preg_match('/..:..:..:..:..:../',$mac , $matches); $mac = @$matches[0]; exec("sudo iptables -I internet 1 -t mangle -m mac --mac-source $mac -j RETURN"); exec("sudo rmtrack " . $ip); sleep(1); header('Location: http://www.example.com'); exit; ?>
Remplacez http://www.example.com
par la page à afficher dès qu'un client est authentifié. Vous pouvez notamment placer dans le formulaire d'authentification un champ caché contenant l'URL demandée afin de rediriger le client vers la page qu'il a souhaité :
$schema = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://"; $url = $schema.$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
Voici le contenu de la page kick.php :
<?php $ip = $_GET['ip']; // Entrer ici l'adresse IP du client à révoquer. $arp = "/usr/sbin/arp"; $mac = shell_exec("sudo $arp -an " . $ip); preg_match('/..:..:..:..:..:../',$mac , $matches); $mac = @$matches[0]; if( $mac === NULL) { echo "Erreur: Impossible de retrouver l'adresse MAC."; exit; } while( $chain = shell_exec("sudo iptables -t mangle -L | grep ".strtoupper($mac) ) !== NULL ) { exec("sudo iptables -D internet -t mangle -m mac --mac-source ".strtoupper($mac)." -j RETURN"); } exec("sudo rmtrack " . $ip); echo "Utilisateur révoqué"; ?>
Nous allons créer le script permettant à un client d'outrepasser le portail captif. Pour cela, éditer le fichier /usr/bin/rmtrack :
/usr/sbin/conntrack -L | grep $1 | grep ESTAB | grep 'dport=80' | awk "{ system(\"conntrack -D --orig-src $1 --orig-dst \" substr(\$6,5) \" -p tcp --orig-port-src \" substr(\$7,7) \" --orig-port-dst 80\"); }"
Changer les droits sur le script :
chmod 755 /usr/bin/rmtrack
Accorder les privilèges au serveur Web pour effectuer ces opérations. Pour cela, exécuter la commande suivante :
visudo
et ajouter les lignes suivantes :
www-data ALL=NOPASSWD: /usr/sbin/arp www-data ALL=NOPASSWD: /sbin/iptables www-data ALL=NOPASSWD: /usr/bin/rmtrack [0-9]*.[0-9]*.[0-9]*.[0-9]*
Redémarrer et tester.