Exit la box opérateur partie 2
Table of contents
Avant d'aller plus loin dans la technique...
Résumé de l'épisode précédent
Dans la première partie nous avons vu comment choisir une distribution, et un exemple personnel de routeur maison avec plusieurs interfaces réseaux.
Nous nous sommes concentré sur l'infrastructure attendue (avec ou sans DMZ, quel type d'interface est nécessaire...) et comment activer le mode routeur. Linux est magique en ce sens, car en une seule commande on active le système d'exploitation pour que celui ci puisse router des paquets.
D'ailleurs un petit rappel du modèle OSI, toujours intéressant de creuser un peu sur ce que fait concrètement un routeur, allons donc plus en profondeur:
L'image ci dessus me parait assez parlante, on y voit les couches du modèle (qui est je le rappelle un modèle théorique), les normes/technologies utilisées par couche et le matériel qui concrètement exploite celles ci. On retiendra simplement:
-
La première couche, Physique, est le support utilisé pour transporter l'information. Dans mon cas, une fibre optique jusqu'à mon tranceiver puis ensuite du câble Ethernet.
-
La seconde couche, Liaison de donnée est celle qui va gérer les segments sur un réseau local. Sur cette couche on y retrouve les adresses Mac, intégrées aux cartes réseau par les constructeurs.
-- Celles ci sont sensées être fixes, mais un des premiers trucs cool qu'on apprends en sécurité informatique est de faire du mac spoofing, pour les curieux je vous ramène à l'article Wikipédia dédié.
-- A noter que deux éléments actifs peuvent dialoguer via adresse mac sur un même réseau de Niveau 2. Pas besoin d'IP donc.
- La troisième et dernière qui nous intéresse est la couche Réseau, c'est elle qui gère les sacro-saintes adresses IP. Utilisées même en local car aisées à retenir (sur 32 bits pour la V4 et 128 pour la V6) elles sont aujourd'hui présentes partout.
-- Pour revenir sur l'activation du mode routeur sous Linux, ça va être le fait de permettre à l'OS de gérer sur une interface en entrée un paquet IP, de le décapsuler, (on monte donc dans la pile de protocole) puis de l'encapsuler sur l'autre interface. Pour les curieux c'est par ici
-- Un routeur gère beaucoup d'autres aspects, la notion de route, le NAT/PAT, l'interconnexion de protocoles routés. Dans notre cas on restera simplement sur le fait que ça soit l'élément entre notre opérateur, et nos réseaux locaux (si DMZ)
T'es mignon avec ta cape de prof de techno mais c'est quoi la suite?
Dans ce second article on va s'affairer à sécuriser tout d'abord son routeur avec un pare-feu, puis ensuite installer des outils pour gérer les services nécessaires à une utilisation classique d'un réseau local.
En effet une fois qu'on a du matériel qui transfère correctement les requêtes, tout n'est pas joué.
Il faut tout d'abord que les clients (ordinateurs, tablettes et tous les autres trucs installés dans la maison) puissent faire une résolution DNS. C'est crucial, sinon votre navigateur n'arrivera pas à résoudre une IP par un nom de domaine et l'inverse. D'autre part il faut que ces mêmes clients puissent obtenir une adresse IP locale via le DHCP lors de la première connexion, pour que nous n'ayons pas à paramétrer manuellement les 50 périphériques de la famille.
-
Pour le DNS nous installerons un outil qui en plus de faire office de serveur bloque également les publicités: piHole. Une fois correctement paramétré, cet outil est absolument génial.
-
Pour le DHCP nous installerons l'outil isc-dhcp-server (disponible sur les dépôts Debian), qui permet assez simplement de gérer les périphériques connectés à l'interface de votre choix.
En avant le déploiement...du firewall
Installation du pare-feu
Iptables est le pare-feu utilisé par de nombreuses distributions. Il est robuste et une fois qu'on a compris comment le paramétrer il permet une grande souplesse dans la gestion des flux. Son petit frère nftables semble intéressant, cependant je n'ai jamais passé le pas de déployer celui ci, nous resterons donc sur du old school.
Rien de plus simple pour l'installation:
root@router-debian:~# apt install iptables
Et là...bah il se passe rien. Normal car de base tout est ouvert:
root@router-debian:~# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
De la même manière pour le NAT (je développe la partie NAT/PAT plus bas dans l'article):
root@router-debian:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
On voit effectivement que les chaines INPUT/FORWARD/OUTPUT sont en ACCEPT, et qu'il n'y a pas de règles plus spécifiques de définies.
Je vous invite à lire cet article qui résume bien les grands axes, avec le petit schéma qui va bien:
Les règles en entrée du routeur (INPUT), celles qui sont transmises d'un réseau à l'autre (donc d'une interface à l'autre, FORWARD) et celles en sorties du routeur (OUTPUT) sont autorisées.
Ceinture et bretelles
Avant de commencer à jouer avec les règles - et donc de risque de se planter - on va créer un super script qui permettra de remettre à zéro le pare-feu en cas de problème.
touch ~/iptables_clear.sh
puis ajoutez:
#!/bin/bash
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
Enfin on active le script qu'il puisse être exécutable:
chmod +x ~/iptables_clear.sh
On a notre script qui nous permettra une RAZ en cas de pépin, à condition bien sûr d'avoir accès au routeur en direct. En ssh c'est une autre histoire... A noter également qu'un reboot de la machine à ce stade repasse les règles iptables par défaut.
Le script Iptables
Note pour les barbus et autre aficionados de la sécurité: ma modeste contribution n'est certainement pas parfaite et je l'assume pleinement. Comme pour le premier article je suis preneur des critiques, commentaires et autres conseils qui permettront à chacun d'augmenter son niveau de sécurité ou du moins d'éviter des erreurs classiques... mais allez y de manière constructive :)
Les règles classiques
Passons maintenant à notre script qui va gérer l'ensemble de nos règles. Allons y par étapes:
#!/bin/bash
#Flush
sudo iptables -F
sudo iptables -t nat -F
#Loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
#Règles générales
iptables -P FORWARD DROP
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
#LOG
#iptables -A OUTPUT -d 109.0.66.20 -j LOG --log-prefix "iptables_DNS::"
#Connexions en cours
iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
#ICMP
iptables -A INPUT -i eno1 -p icmp -j DROP
iptables -A INPUT -p icmp -j ACCEPT
- Flush: les deux premières lignes font une remise à zéro des règles dont celles du NAT
- Loopback: on autorise tout sur la boucle locale, nécessaire pour le bon fonctionnement de l'OS
- Règles générales: on bloque en entrée et transition, par contre j'ai fait le choix d'autoriser en sortie.
- avantage: règles simplifiées (sinon ça peut monter très vite)
-
inconvénient: sécurité limitée (on ne contrôle pas les flux sortants)
-
LOG: peut être utile pour avoir des informations complémentaires dans /var/log (ici par exemple les logs à destination de l'ip 109.X.X.X.)
- Connexions en cours: permet d'autoriser une connexion lorsque celle ci est en état Established (exemple la connexion ssh pour gérer le routeur à distance)
Le dernier exemple ICMP est donné pour comprendre comment iptables fonctionne. A savoir qu'il va prendre la première règle qui répond à la demande. Ne mettez pas les règles les plus permissives en premier, au risque que celles d'après ne servent à rien!
Exempe ici nous avons:
- iptables -A INPUT -i eno1 -p icmp -j DROP: je bloque les requêtes ICMP en entrée de l'interface eno1 (WAN). Les pings depuis internet sont bloqués.
- iptables -A INPUT -p icmp -j ACCEPT: les requêtes ICMP en entrées sont autorisées.
Ca pourrait paraître contradictoire, on bloque puis on autorise. Mais la subtilité est que dans le premier cas l'interface est indiquée, dans le second non. Du coup iptables va vérifier: si l'interface en question est bien eno1 il s'arrête à la première. Dans le cas inverse il continue et donc traite la seconde règle qui autorise le traffic ICMP implicitement vers les autres interfaces.
Les règles spécifiques à votre réseau
Quelques exemples qui aideront à mettre en place un périmètre de sécurité sur l'ensemble des interfaces de votre routeur local:
#LAN
iptables -A INPUT -i enx9cebe8355797 -s 192.168.1.0/24 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -d 192.168.2.0/24 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -o eno1 -j ACCEPT
Sur mon interface LAN:
- J'autorise en entrée sur l'interface indiquée les flux provenant du réseau 192.168.1.0/24
- J'autorise le transfère des requêtes depuis le réseau 192.168.1.0/24 vers le réseau 192.168.2.0/24 (ma DMZ)
- J'autorise le transfère des requêtes depuis le réseau 192.168.1.0/24 vers l'interface eno1 en sortie (le WAN)
#DMZ
iptables -A INPUT -i enx000ec6ccbb04 -s 192.168.2.2 -j ACCEPT
iptables -A FORWARD -s 192.168.2.0/24 -d 192.168.1.0/24 -j ACCEPT #LAN
iptables -A FORWARD -s 192.168.2.2 -d 217.X.X.X -p udp --dport 123 -j ACCEPT #NTP
iptables -A FORWARD -s 192.168.2.2 -d 185.X.X.X/29 -j ACCEPT #VPN
iptables -A FORWARD -s 192.168.2.2 -d 208.67.222.222 -p udp --dport 53 -j ACCEPT #DNS
Sur mon interface DMZ:
- J'autorise en entrée sur l'interface indiquée les flux provenant de l'ip 192.168.2.2
- J'autorise les flux provenant du réseau 192.168.2.0/24 vers les ips du LAN
- J'autorise le transfère de requêtes depuis l'ip 192.168.2.2 vers le 217.X.X.X sur le port UDP 123 (NTP)
- J'autorise le transfère de requêtes depuis l'ip 192.168.2.2 vers 185.X.X.X/29 pour monter le VPN
- J'autorise le transfère de requêtes depuis l'ip 192.168.2.2 vers le 208.67.222.222 (opendns) sur le port 53 en UDP
Ici on voit que c'est beaucoup plus restrictif, je permet à une seule ip de faire du NTP/DNS à destination d'un hôte et de monter un VPN sur une plage d'ip restreinte. L'idée est d'avoir un kill switch, si mon tunnel VPN tombe, le matériel derrière n'a pas d'autres accès internet. Je préserve mon anonymat, à bon entendeur...
#WAN
iptables -A INPUT -i eno1 -p tcp --dport 51820 -j ACCEPT
Sur mon interface WAN:
- J'autorise le port 51820 en entrée (wireguard)
Je n'ai en redirection de port qu'une seule entrée, vers mon serveur VPN wireguard qui fera l'objet d'un prochain article...
Activation du pare-feu au redémarrage
Les règles indiquées ci dessus ne sont pas exhaustives, chaque réseau à ses spécificités. Toujours le choix difficile de placer le curseur entre une gestion aisée et pas trop chronophage de son réseau et une sécurité acceptable.
Enfin pour finir, les règles iptables ne sont pas persistantes, du coup si vous ne voulez pas activer manuellement le script à chaque redémarrage alors il va falloir exécuter les commandes suivantes:
apt install iptables-persistent
Désormais les règles seront sauvegardées dans /etc/iptables/rules.vx. Simplement via la commande suivante:
iptables-save > /etc/iptables/rules.v4
OU
ip6tables-save > /etc/iptables/rules.v6
Mise en place du NAT
Faire une belle matrice de flux ne suffira pas à avoir une installation fonctionnelle. Pour cela il va falloir mettre en place de la translation d'adresse pour que le routeur sache quels périphériques causent d'une interface à l'autre.
C'est presque à appréhender comme une seconde fonctionnalité d'iptable, d'ailleurs je vous invite à lire et comprendre à quoi sert le NAT pour avoir une configuration correcte.
Un excellent article que j'ai découvert récemment, qui vous expliquera absolument tout ce que vous n'avez jamais voulu savoir sur le NAT, PAT et autre DNAT: https://www.it-connect.fr/le-nat-et-le-pat-pour-les-debutants/
Bon je spoil, on fait du PAT en sortie et du DNAT si vous avez besoin de rediriger des ports depuis internet vers un élément actif de votre réseau.
Je l'ai indiqué précédemment Iptables gère très bien ça, on va parler de PREROUTING et POSTROUTING. Comme d'habitude on retrouve pléthore de bonnes informations sur le web, voici ce que j'ai trouvé qui me parait compréhensible:
Chaine PREROUTING et cible DNAT
Dans la chaine PREROUTING (avant routage) on ne peut modifier que l’adresse de destination (et les numéros de ports au cas où ils seraient déja utilisés), d’ou l’utilisation de la cible DNAT (NAT de destination).
Chaine POSTROUTING et cible SNAT
Dans la chaine POSTROUTING (après routage) on ne peut modifier que l’adresse source, d’ou l’utilisation de la cible SNAT (NAT source).
Cible MASQUERADE
Cette cible permet de déterminer l’adresse IP de sortie pour chaque paquet, ce qui est moins performant car il va vérifier l’interface de sortie pour chaque connexion. MASQUERADE est utilisée dans le cas d’une adresse IP publique dynamique, dans le cas d’IP fixe nous préfèrerons utiliser la cible SNAT en spécifiant l’adresse IP de sortie.
Revenons à notre script qui va donc s'étoffer avec ce genre de commandes:
# NAT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 5001 -j DNAT --to-destination 192.168.2.2:5001
- J'applique le SNAT depuis mon réseau 192.168.1.0/24
- J'applique le SNAT depuis mon réseau 192.168.2.0/24
- J'applique le DNAT depuis internet, port 5001 (Synology pour les curieux) à destination de mon ip située dans ma DMZ (bravo si vous avez suivi)
- Cette dernière règle est minimaliste car dans mon cas je n'applique le DNAT que via mon interface VPN. Pensez à être plus restrictif dans un cas plus classique, à savoir du DNAT sur la patte WAN
Les services locaux
Une fois le pare-feu en place, place aux deux services locaux nécessaires pour que les périphériques clients soient autonomes.
Déployons un serveur de nom de domaine DNS
En premier lieu il est nécessaire que la résolution de nom se fasse, pour cela on va utiliser un outil, Pihole, à la base conçu pour s'installer sur un raspberry mais qui se greffe sans difficulté à une distribution x86/64.
L'avantage de Pihole, un bloqueur de publicités hyper efficace. Depuis que je l'utilise, j'ai à minima 20% de mon trafic interne qui est bloqué et j'ai eu des pointes à 35%!
Concrètement ça indique que lorsqu'on utilise un service (youtube par exemple) ou encore un périphérique embarqué (une box tv Xiaomi dans mon cas) de nombreuses requêtes non sollicitées sont envoyées. Pihole en tant que serveur DNS devra normalement les résoudre, mais ne fera finalement que les bloquer. Simple mais efficace.
Pour l'installation leur site est très bien fait je vous laisse le soin de le découvrir: https://pi-hole.net/
L'installation est très simple, deux conseils néanmoins:
- blindez vos listes 'Adlists' qui vont contenir les urls à bloquer quitte à avoir des doublons, pour ma part j'en ai 67. Comme vu ci dessus mon Pihole bloque actuellement quasi 5 millions d'url! En creusant sur internet vous trouverez des sites qui recensent ces listes à intégrer à l'outil, à la demande je peux aussi regarder de mon coté si un export est possible...
- L'import s'effectue depuis l'interface graphique sous 'Group Management' puis 'Adlists'
- Nécessite ensuite de recharger les listes, via le menu 'Tools' puis 'Update Gravity'
- partez immédiatement sur du DNSCrypt (ou DOH). Comme souvent inutile de refaire la roue, un article très bien détaillé se trouve ici: https://www.malekal.com/configurer-pihole-avec-dnscrypt-ou-dns-over-https-doh/
Au bout de quelques jours/semaines vous pourrez vous faire peur à voir que certains périphériques passent leur temps à requêter des url qui n'ont rien à voir avec votre navigation quotidienne. Pour ma part mention spéciale à ma box Xiaomi et à l'iPhone de madame.
Tout ça étant bloqué dans votre réseau, la bande passante de votre connexion vous dira merci, et un peu vie privée aussi. A l'inverse à ma grande surprise je n'ai pas eu trop à ajouter de sites en listes blanches pour forcer les faux positifs, c'est assez bluffant.
Déployons un serveur DHCP
Enfin dernière étape, il faut que les clients qui s'authentifient pour la première fois sur le réseau puissent avoir une adresse ip de délivrée (dans mon cas uniquement sur la patte LAN). Deux solutions s'offrent à nous:
- Je suis une faignasse et j'assume: Pihole précédemment vu offre la possibilité d'activer le serveur DHCP sur l'interface de son choix. Je ne l'ai pas testé mais ça semble vraiment pas bien compliqué, tout se passe dans 'Settings', puis onglet 'DHCP'.
- Les mains dans le camboui et la sueur de la ligne de commande c'est mon truc: alors allons y via l'outil isc-dhcp-server.
Tout d'abord on installe l'outil et ses dépendances:
apt install isc-dhcp-server
Puis on paramètre l'interface en écoute:
nano /etc/default/isc-dhcp-server
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="enx9cebe8355797"
INTERFACESv6=""
Comme indiqué en commentaire si vous souhaitez mettre plusieurs interfaces, il suffit simplement de mettre à la suite d'un espace.
Le reste à faire se situe dans le fichier /etc/dhcp/dhcpd.conf:
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.150 192.168.1.200;
option domain-name-servers 192.168.1.1;
option domain-name "domain.local";
option subnet-mask 255.255.255.0;
option routers 192.168.1.1;
option broadcast-address 192.168.1.255;
option netbios-node-type 1;
default-lease-time 28800;
max-lease-time 28800;
En gros j'indique mon réseau et son masque, l'adresse de début du range ip, le serveur DNS, le nom de mon domaine...
J'ai choisi enfin toujours dans ce même fichier de mettre des ips associées à mes périphériques. Ca assure que le service dhcp associe toujours la même adresse ip à un client dédié. L'utilité dans mon cas c'est d'avoir dans pihole qu'on a vu précédemment un retour cohérent des requêtes effectuées par ces clients. Si l'ip change régulièrement, difficile d'avoir une traçabilité de qui fait quoi comme requêtes...
host xiaomi_box {
hardware ethernet aa:bb:cc:dd:ee:ff;
fixed-address 192.168.1.22;
}
L'exemple ci dessus indique que l'adresse MAC qui se présentera comme aa:bb:cc:dd:ee:ff se verra affecter l'ip 192.168.1.22
Un redémarrage de service isc-dhcp-server et normalement vos clients pourront désormais se connecter. Une commande utile pour le vérifier:
root@router-debian:~# dhcp-lease-list
To get manufacturer names please download http://standards.ieee.org/regauth/oui/oui.txt to /usr/local/etc/oui.txt
Reading leases from /var/lib/dhcp/dhcpd.leases
MAC IP hostname valid until manufacturer
===============================================================================================
4e:15:dc:cc:ab:18 192.168.1.176 -NA- 2022-06-06 23:18:59 -NA-
c0:25:ee:11:ff:d6 192.168.1.179 DESKTOP-PRLXX 2022-06-06 17:25:52 -NA-
root@router-debian:~#
Et pour finir...
Félicitation si vous êtes parvenu au bout de l'article! On a donc désormais un routeur qui est globalement sécurisé, qui délivre des adresses ip aux clients connectés sur le réseau local et qui traite les requêtes DNS en bloquant une partie de ces dernières. On est pas mal là non?
Ceci dit on pourrait aller plus loin en installant des outils pour voir les requêtes passer à niveau réseau, et réfléchir à comment ouvrir notre infrastructure locale vers l'extérieur de manière sécurisée. Vous me voyez venir ça sera l'objet d'un troisième article...