Portail captif
Source de la documentation : https://projectzme.wordpress.com
Procédure validée sur Debian 13.
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 :
- enp1s0
- Carte connectée à Internet, en DHCP.
- enp2s0
- 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 install apache2 php conntrack sudo isc-dhcp-server nftables net-tools
Configurer les interfaces réseau comme suit en éditant le fichier /etc/network/interfaces :
auto lo iface lo inet loopback auto enp1s0 iface enp1s0 inet dhcp auto enp2s0 iface enp2s0 inet static address 10.0.0.254/24
Valider la configuration réseau :
systemctl restart networking
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; }
Définissez l'interface d'écoute du serveur DHCP en modifiant la ligne suivante dans /etc/default/isc-dhcp-server :
INTERFACESv4="enp2s0"
Redémarrer le serveur DHCP :
systemctl restart isc-dhcp-server
Activer le routage en ajoutant la ligne suivante dans le fichier /etc/sysctl.d/forward.conf :
net.ipv4.ip_forward=1
Appliquer ce changement :
sysctl --system
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, modifier le fichier /etc/nftables.conf :
#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority filter; policy drop; iifname lo accept ip protocol icmp accept udp dport 67 accept tcp dport 80 accept tcp dport 443 accept ct state { established, related } accept } chain forward { type filter hook forward priority filter; } chain output { type filter hook output priority filter; } chain prerouting { type nat hook prerouting priority dstnat; } chain postrouting { type nat hook postrouting priority srcnat; oifname enp1s0 meta mark 99 masquerade } } table ip filter { chain prerouting { type nat hook prerouting priority dstnat; iifname enp2s0 meta mark 0 tcp dport {80,443} dnat to 10.0.0.254 } } table inet mangle { chain prerouting { type nat hook prerouting priority mangle; } }
Activer et redémarrer nftables :
systemctl enable nftables.service systemctl restart nftables.service
Création du portail captif
Notre portail captif comportera deux 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.
Notre exemple présentera une page avec un simple lien afin d'accéder à Internet.
Voici le contenu de la page /var/www/html/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 /var/www/html/process.php.
<?php $ip = $_SERVER['REMOTE_ADDR']; exec("sudo /opt/captive-portal/add-rule ".$ip); sleep(1); header('Location: http://www.google.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"];
Nous allons créer les scripts permettant d'autoriser un utilisateur à outrepasser le portail captif et de révoquer cet accès.
mkdir /opt/captive-portal
Voici le script appelé par la page process.php pour autoriser un utilisateur. Pour cela, créer le fichier /opt/captive-portal/add-rule :
#!/bin/bash ip=$1 mac=$(arp -an $ip | sed -n 's/.*\([a-zA-Z0-9]\{2\}\(:[a-zA-Z0-9]\{2\}\)\{5\}\).*/\1/p') nft add rule inet mangle prerouting ether saddr $mac mark set 99 return conntrack -D --src $ip
Le script pour révoquer les accès est situé dans /opt/captive-portal/del-rule :
#!/bin/bash ip=$1 mac=$(arp -an $ip | sed -n 's/.*\([a-zA-Z0-9]\{2\}\(:[a-zA-Z0-9]\{2\}\)\{5\}\).*/\1/p') handle=$(nft -a list ruleset | grep $mac | sed -r 's/.*# handle ([^ ]+).*/\1/') nft delete rule inet mangle prerouting handle $handle conntrack -D --src $ip
Rendons ces scripts exécutables :
chmod +x /opt/captive-portal/add-rule chmod +x /opt/captive-portal/del-rule
Accorder les privilèges au serveur Web pour ajouter les règles nécessaires. Pour cela, exécuter la commande suivante :
visudo
et ajouter les lignes suivantes :
www-data ALL=NOPASSWD: /opt/captive-portal/add-rule [0-9]*.[0-9]*.[0-9]*.[0-9]*
Pour révoquer un client, exécuter la commande suivante en modifiant son adresse IP :
/opt/captive-portal/del-rule 10.0.0.10