Portail captif IPtables

Bonjour,

Dans le cadre de mon travail de fin d’étude je dois réaliser un portail captif sur base d’un script IPtables. J’ai à ma disposition un environnement de test configuré comme ceci : hpics.li/e182708
Après de nombreuses recherches je suis tombé sur ces 3 tutoriels :

josselin-lecocq.fr/articles-portailcaptif
andybev.com/index.php/Using_ … ive_portal
pihomeserver.fr/2014/05/23/r … captif-22/

Je me suis donc basées sur leurs explications pour faire mon script et l’adapter à ma topologie.
Cependant j’ai un soucis dès que mon client veut surfer il n’est jamais redirigé sur ma page de login. Cependant celle-ci est accessible via son adresse IP. J’aimerais donc savoir si j’ai fait une erreur dans mon script ou bien si je doit partir sur autre chose ?

Merci d’avance pour vos réponses :slightly_smiling:

Mon script :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t mangle -N internet
iptables -t mangle -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j internet
iptables -t mangle -A internet -j MARK --set-mark 99
iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 -m tcp --dport 80 -j DNAT --to-destination 192.168.1.254

Que se passe-t-il exactement ?
Ces règles ont des redondances, mais elles devraient rediriger toutes les connexions HTTP arrivant par eth1 vers 192.168.1.254. Je les ai testées en local pour les connexions sortantes en remplaçant PREROUTING par OUTPUT et en enlevant les redondances, et ça fonctionne.
Note : dans cette situation la cible REDIRECT aurait le même effet que DNAT en plus simple.

As-tu vérifié avec iptables-save si toutes ces règles sont bien en place, et qu’il n’y en a pas d’autres qui pourraient interférer ?

As-tu bien testé avec des connexions HTTP et non HTTPS ? Ces règles n’interceptent pas les flux HTTPS, qui utilisent le port 443.

Bonjour,

Mon client n’est jamais redirigé vers la page héberge sur la machine Debian (192.168.1.254). Il peut ping l’IP et y accéder en y entrant manuellement l’IP. Mais je souhaiterais qu’il sois directement redirigé vers ma page de log-in.
J’ai vérifié mes tables avec la commande iptables-save voici le résultat :

> Generated by iptables-save v1.4.21 on Mon Feb 29 15:13:59 2016
> *mangle
> :PREROUTING ACCEPT [360:32869]
> :INPUT ACCEPT [360:32869]
> :FORWARD ACCEPT [0:0]
> :OUTPUT ACCEPT [28:2988]
> :POSTROUTING ACCEPT [28:2988]
> :internet - [0:0]
> -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j internet
> -A internet -j MARK --set-xmark 0x63/0xffffffff
> COMMIT
>  Completed on Mon Feb 29 15:13:59 2016
> Generated by iptables-save v1.4.21 on Mon Feb 29 15:13:59 2016
> *nat
> :PREROUTING ACCEPT [43:6209]
> :INPUT ACCEPT [44:6269]
> :OUTPUT ACCEPT [0:0]
> :POSTROUTING ACCEPT [0:0]
> -A PREROUTING -i eth1 -p tcp -m mark --mark 0x63 -m tcp --dport 80 -j DNAT --to-                                                  destination 192.168.1.254
> -A POSTROUTING -o eth0 -j MASQUERADE
> COMMIT

Pourriez vous me donner les règles que vous avez utilisée sans redondances ? Je suis assez novices en iptables et ne parviens pas à voir où elles sont.

Merci d’avance

Pour commencer, essaie cette règle toute simple :
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT

J’ai clear toutes mes tables avec le script de cette page: http://www.cyberciti.biz/tips/linux-iptables-how-to-flush-all-rules.html

J’ai ensuite essaye votre commande cependant mon client n’est toujours pas redirigé vers la page du portail et obtient cet erreur : http://hpics.li/f6db591

Apparemment un problème de résolution DNS. Il faut probablement laisser la règle MASQUERADE, ou installer un relais DNS sur la passerelle et le déclarer comme DNS dans la configuration DHCP.

As-tu bien compris tous les mécanismes qu’implique ce que tu veux faire ? DHCP, DNS, routage, NAT…

Je comprend bien toutes les notions dhcp,dns,… Mais ce sont les iptables que je ne maitrise pas parfaitement.
Si je récapitule bien ce que je dois faire c’est ajouter un dhcp (mes clients étaient en statiques jusqu’à présent) , un dns qui forward celui de google. Lorsque les deux sont installé partager via le dhcp mon adresse comme dns ?

Et pour les iptables j’utilise ceci ? :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 -m tcp --dport 80 -j REDIRECT

Tu n’as pas besoin de ton propre serveur DNS. Tu peux te contenter d’indiquer les adresses de DNS ouverts ou du FAI dans la configuration DHCP.

Dans un premier temps ne mets pas la correspondance mark dans la règle REDIRECT, pour vérifier que la redirection fonctionne. Ensuite tu pourras ajouter des conditions.

J’ai suivi vos instruction et cela a fonctionne avec ces règles :grinning: :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT

Cependant ces deux règles ne fonctionnent que avec les requêtes Https.
Que suggérez vous d’ajouter pour qu’elles soientt également redirigées ?

Tu veux dire que la redirection ne fonctionne qu’avec HTTP (port 80) ? La règle MASQUERADE traite indifféremment toutes les connexions qui n’ont pas été redirigées vers le portail.
Pour rediriger les connexions HTTPS, il faut faire de même avec le port 443, et bien sûr il faut que ton portail réponde en HTTPS. Mais les navigateurs vont signaler une erreur car le site qui répond n’est pas le site demandé. Selon le navigateur et son paramétrage, il sera possible de passer outre pour afficher la page, ou pas.

D’autre part, je soupçonne que tu n’avais pas utilisé le marquage des paquets juste pour le plaisir de compliquer les choses, et que tu voulais à terme pouvoir jouer sur le marquage pour ne pas intercepter toutes les connexions HTTP (une fois le client authentifié par exemple). Me trompé-je ?

Quand je dit que la redirection ne fonctionne qu’avec HTTP ce que je veux dire c’est que seul les sites en http son redirigée vers ma page de login, Les sites en https fonctionnent normalement.
Je vais donc essayer d’écouter également le port 443.

En effet j’essaie d’utiliser de marquage afin de pouvoir bloquer certain sites par la suite. Mais je suis entrain de me dire que cela serait p-e plus intéressant de le faire en passant via un proxy. Qu’en pensez vous ?

Je ne vois pas en quoi le marquage est utile pour filtrer les sites.

Un proxy transparent ne fonctionne qu’avec les communications HTTP en clair. L’interception d’une communication HTTPS par un proxy transparent provoquera une erreur ou au mieux un avertissement du navigateur lors de la vérification de l’identité du serveur. Les protocoles autres que HTTP ne sont pas pris en compte.

Effectivement je me rend compte que cela ne fonctionne pas, je suis directement renvoyé vers une erreur comme celle-ci : http://www.hostingpics.net/viewer.php?id=373087Capture.png
Existe t’il alors un quelconque moyen de rediriger les requêtes https vers ma page de login ?

Je ne connais pas cette erreur. Habituellement on a un message disant que le nom du certificat transmis ne correspond pas au site demandé ou son authenticité ne peut être vérifiée (quand il s’agit d’un certificat autosigné).

Est-ce en redirigeant les connexions HTTPS vers un proxy ou vers le serveur du portail captif ?

vers le portail captif via cette règle :

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 -j DNAT --to 127.0.0.1:80

Forcément ça ne peut pas marcher. On ne peut pas juste rediriger le port 443 vers le port 80 et s’attendre à ce que ça marche. Le client envoie du HTTPS sur le port 443 alors que le portail s’attend à recevoir du HTTP sur le port 80.

Il faut que le portail captif écoute aussi en HTTPS, sur le port 443, et faire une redirection sans changer le port.

Accessoirement, la redirection de paquets extérieurs vers une adresse de loopback comme 127.0.0.1 n’est pas censée fonctionner non plus, je me demande comment le client a pu recevoir une réponse. Utilise plutôt REDIRECT.

Effectivement ça semble logique, mais êtes vous certains que celà va marcher ? Parce que j’ai lu à plusieurs endroits que faire une redirection https n’était pas possible car ssl vérifiait l’intégrité du contenu . Par conséquent l’utilisateur recevait une erreur et la redirection ne fonctionnerait pas.

Juste deux précisions, si cela peut être utile.
Un proxy transparent n’écoute que sur un seul port.
S’il n’est pas transparent, alors il pourra gérer les requêtes https. Mais, il pourrait être apparenté à un man-in-the-middle.

Je l’ai déjà mentionné dans cette discussion. Erreur ou avertissement, cela dépend du navigateur.

Merci pour toutes vos réponse j’ai réussi à réaliser ce que je voulais :slight_smile: J’ai cependant encore quelques questions afin d’améliorer mon système. J’utilise actuellement les lignes suivantes :

iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE
iptables -t mangle -N internet
iptables -t mangle -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j internet
iptables -t mangle -A internet -j MARK --set-mark 99
iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 -m tcp --dport 80 -j REDIRECT --to-ports 80
iptables -t nat -A PREROUTING -i eth1 -p tcp -m mark --mark 99 --dport 443 -j REDIRECT --to ports 443
echo “1” > /proc/sys/net/ipv4/ip_forward

Mes clients qui souhaitent surfer sont donc bien redirigé vers ma page de login. Lorsque ceux-ci se logguent, je débloque leur accès au net via cette commande :

sudo iptables -t mangle -I internet 1 -m mac --mac-source USER-MAC-ADDRESS-HERE -j RETURN

Je souhaiterai pouvoir bloquer/ouvrir des ports et laisser certains sites accessible pour les client non loggué càd ceux dont leur paquet sont marqué 99. Serait-ce réalisable ? Si oui quelles commandes dois-je ajouter ?