Iptables

De ArchwikiFR

Iptables est un puissant pare-feu (ou firewall) intégré au noyau Linux qui fait partie du projet Netfilter . Il peut être configuré directement, ou en utilisant l'un de ces nombreux frontends ou interfaces graphiques. Iptables fournit à la fois iptables pour les connexions IPv4 et ip6tables pour l'IPv6.

Présentation

Commençons donc sur de bonnes bases. Toujours dans l'esprit de Arch de savoir ce qu'il se passe dans sa machine, les requêtes réseaux en font partie plus que jamais ! Il est donc essentiel d'avoir un minimum de connaissances sur le schéma d'une connexion avant de se lancer dans la configuration de son pare-feu. Sans rentrer trop dans les détails non plus, nous verrons quand même le minimum nécessaire pour appréhender iptables.
Le but étant avant tout d'établir un pare-feu fonctionnel pour une utilisation "classique", tout en comprenant suffisamment le déroulement pour pouvoir modifier/adapter/créer la plupart des règles qui peuvent être utiles lors d'utilisations particulières.

Notions sur les réseaux

Pour faire simple : Un réseau est composé au minimum de 2 ordinateurs branchés ensemble. Les informations sur ce réseau vont transiter sous forme de "paquets" contenant des informations. Pour établir une communication, le premier ordinateur (A) va envoyer un paquet contenant une demande de connexion, à une autre machine (B). B va renvoyer une réponse à A ; et si elle est positive alors l'échange réel peut débuter.
Tout ça schématiquement, car il faut des adresses pour que les demandes et réponses arrivent là où elles doivent ! Il faut aussi que les 2 interlocuteurs utilisent les mêmes ports et protocoles. C'est ce qu'il se passe pour n'importe quelle connexion réseau, comme lorsqu'on consulte une page web (quand le serveur accepte la demande de connexion, on lui demande alors d'afficher une page, et il le fait !).
Ce qu'il nous faut bien voir ici, c'est que pour une connexion, "initiée" par A, A "envoie un paquet à l'extérieur" vers B, qui le "reçoit" et "renvoie" une réponse à A qui à son tour "reçoit la réponse".

Notions sur la sécurité

Ici c'est très simple, mais c'est aussi indispensable. Vu la multitude de possibilités qui existent et pour éviter de créer des brèches, par défaut, on interdit tout. Et ensuite, on autorise ce qui doit l'être… Ce que l'on peut voir ici, c'est qu'on adopte une "politique" à appliquer à l'ensemble des connexions (tout interdire), qu'on affine avec des règles particulières.

Et iptables dans tout ça ?!

Pour chaque paquet entrant, transitant ou sortant, iptables va l'analyser et le comparer aux règles qui lui sont indiquées. Si le paquet correspond à une règle, alors la règle est appliquée, s'il ne correspond à aucune règle, alors le paquet suit la politique par défaut.

La construction d'un paquet est normalisée (RFC 791), et contient dans un en-tête toutes les informations nécessaires pour son bon acheminement tout au long de son parcours. iptables s'appuie donc sur cet en-tête pour savoir quoi faire de ce nouveau paquet. En fonction de sa destination/provenance, le paquet entre dans une "table de routage". Il en existe plusieurs, qui ont chacune leur "juridiction" ! Il y a donc :

  • la table filter : elle contient la chaîne INPUT qui gère les paquets entrants (destiné aux sockets local), la chaîne OUTPUT qui gère les paquets sortants (générés localement) ; et la chaîne FORWARD qui gère les paquets qui vont passer par la machine mais sans lui être destinés. La table filter est la table par défaut, celle qui est utilisé si aucune autre n'est spécifié dans les options de la commande. C'est aussi celle-la que nous allons utiliser pour notre pare-feu.
  • la table nat : contient les chaînes PREROUTING, POSTROUTING et OUTPUT. Elle permet de modifier la route que le paquet est censé prendre. C'est celle qui est utilisé par exemple pour faire du SNAT/DNAT/PAT…
  • la table mangle : contient les chaînes PREROUTING, INPUT, FORWARD, OUTPUT et POSTROUTING. Elle permet de modifier un paquet traversant la machine, mais passant par un processus local.
  • la table raw : contient les chaînes PREROUTING et OUTPUT. Elle s'utilise en combinaison avec la cible NOTRACK.
  • enfin, la table security : contient les chaînes INPUT, FORWARD et OUTPUT. Elle est utilisé avec les cibles SECMARK et CONNSECMARK, en combinaison avec un module comme SELinux, afin d'effectuer un contrôle d'accès mandataire.

Chaque chaîne intervient à un moment précis dans le déroulement de la connexion, et c'est à chacune de ces chaînes que l'on attribue une politique par défaut ou une "cible" à suivre (je ne développerai pas ici sur les possibilités qu'offrent les cibles).

Important : Lorsque le paquet entre dans une table, il est comparé aux règle de cette table, dans l'ordre selon lequel les règles se présentent. C'est-à-dire que si un paquet est autorisé par une règle mais que ses critères correspondent à une règle située avant, alors le paquet suivra ce qui est indiqué par la première règle. Cela peut avoir de l'importance par exemple dans le cas d'un protocole que l'on souhaite utiliser seulement sur un réseau local tout en étant connecté à l'internet.

Installation

Pour installer iptables:

pacman -S iptables
Note : Si vous utilisez un noyau personnalisé, assurez-vous qu'il ait été compilé avec le support d'iptables.

Il faut ensuite rajouter le service:

systemctl start iptables

et pour le démarrer automatiquement:

systemctl enable iptables
Note : Le service iptables gère l'IPv4. Le paquet fournit en outre de quoi gérer l'IPv6 avec ip6tables.
Important : Le service lit et charge par défaut le fichier /etc/iptables/iptables.rules que vous devez configurer au moyen de la suite de ce document pour disposer d'un pare-feu (iptables fournit en outre un exemple de pare-feu simple dans /etc/iptables/simple_firewall.rules).

Commandes de base

Maintenant que tout ça est bien dégrossi, (et qu'il vous tarde de faire quelque chose) nous allons voir la construction d'une commande type, elle sera du style :

iptables -t <table dans laquelle écrire> -A <CHAINE CONCERNÉE> -les--options <options> -j <POLITIQUE À APPLIQUER> 

Détail de la ligne :

  • -t = on se place dans une table.
  • -A = on choisit une chaîne.
  • les options = elles sont très nombreuses (spécifier une interface/adresse/port de source/destination, rerouter/marquer un paquet, et bien d'autres...). En voici quelques-unes parmi les principales:
    • -s/-d <adresse IPv4> = indiquer une adresse ou un sous-réseau source/de destination, ex: qui vient de la machine 192.168.1.12 -s 192.168.1.12 ou en direction de toutes adresses d'un réseau -d 172.16.0.0/12, etc..
    • -i/-o <interface> = indiquer une interface réseau d'entrée/sortie, ex: qui sort par eth1 -o eth1 ou qui rentre par wlan0 -i wlan0, etc.
    • -p = indiquer un protocole de transport (-p tcp, -p udp, -p icmp,…).
  • -j (-g) = si le paquet correspond à tout ces critères, alors on applique ce qui suit à savoir accepter, rejeter, ignorer, faire passer, etc.

Ensuite, on peut s'intéresser à la sortie de :

iptables -L

Il s'agit de la liste de règle(s) appliquée(s) actuellement dans la table filter (table par défaut) puisqu'aucune option -t n'est spécifiée. Pour connaître les règles en vigueur dans les autres tables il suffit pour cela de rajouter dans la ligne le nom de la table voulue : (pour la table nat par exemple)

iptables -t nat -L

Nous pouvons, avant de commencer notre configuration, vider les tables actuelles, pour partir sur des bases propres. Pour cela :

iptables -t filter -F

Pour vider les règles personnelles :

iptables -t filter -X

Configuration pour un client simple

Voilà, nous allons donc enfin pouvoir passer à la confection de notre Pare-Feu ! Comme il interagit au niveau du noyau, et que ça touche à la sécurité, tout manipulation est à faire avec root et non pas simplement en sudo (certains changements pourraient s'appliquer, mais pas les sauvegardes).

Tout d'abord, on s'assure que toutes les tables sont vides avec l'option -L , et au besoin on les vide avec les options -F et -X vues plus haut.

À partir de là, dans le cas de notre firewall personnel, nous allons travailler uniquement dans la table filter, la table par défaut.

Nous commencerons donc, comme indiqué dans les notions de sécurité, par tout interdire :

iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP

Ainsi plus aucune connexion n'est autorisée, plus rien ne passe ! C'est très sécurisé mais pas très pratique pour surfer ! Nous allons alors ouvrir petit à petit les ports/connexions qui nous intéressent.

Tout d'abord, nous avons besoin d'autoriser les échanges avec les serveurs DNS :

iptables -t filter -A OUTPUT -p udp -m udp --dport 53 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT 
iptables -t filter -A INPUT -p udp -m udp --sport 53 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Explication de la première ligne : après le choix de la table (qui n'est pas nécessaire, vu qu'ici nous utilisons uniquement la table par défaut ; mais c'est mieux de prendre le réflexe de le préciser), un paquet passant par la chaîne OUTPUT, par protocole de transport udp (les 2 options -p et -m sont nécessaires) sur le port 53 (port très généralement utilisé par les DNS ), selon l'état de la connexion (NEW, demande de nouvelle connexion, RELATED, nouvelle demande mais en rapport avec une connexion déjà initiée et ESTABLISHED, en relation à une demande pour une connexion déjà initiée), sera accepté. N'importe quel autre cas subit la politique par défaut : DROP (refus sans réponse).

Sur le même principe, nous allons construire les autres règles avec les commandes suivantes :

  • pour accepter les ping depuis notre réseau local (le protocole icmp étant un peu à part, on ne précise pas de port) :
iptables -A OUTPUT -d 192.168.0.0/24 -p icmp -j ACCEPT
iptables -A INPUT -s 192.168.0.0/24 -p icmp -j ACCEPT
  • si nous avons par exemple besoin d'un accés ssh vers une de nos machines :
iptables -t filter -A OUTPUT -o eth0 -d 192.168.1.3 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -i eth0 -s 192.168.1.3 -p tcp -m tcp --sport 22 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  • pour les ports utiles à une navigation basique : (80 = http ; 443 = https ; 8000 = http, par exemple pour du streaming):
iptables -t filter -A OUTPUT -p tcp -m multiport --dports 80,443,8000 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT  
iptables -t filter -A INPUT -p tcp -m multiport --sports 80,443,8000 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Pour pouvoir utiliser l'option multiport, les protocoles doivent utiliser le même type de transport (udp, tcp).

  • si nous avons besoin d'un accès à un serveur tournant sur la machine elle-même :
iptables -t filter -A OUTPUT -o lo -j ACCEPT
iptables -t filter -A INPUT -i lo -j ACCEPT
Note : L'interface lo correspond à la boucle interne, soit l'adresse 127.0.0.1 . On peut, comme pour les autres règles, préciser un port particulier ou d'autres options .
Note : Dans le cas d'un portable par exemple, on peut aussi affiner ces règles en précisant l'interface câblée, et écrire une règle similaire pour l'interface sans fil qui accepte moins de protocoles (c'est alors que l'ordre de lecture des règles peut devenir important !).

Et ainsi de suite... Avec les règles qui sont données là, c'est normalement suffisant, inutile d'en rajouter de trop ! Sinon, il suffit de rajouter des règles du même ordre pour l'ensemble des ports/adresses/connexions que l'on souhaite pouvoir établir. Tout ceci bien entendu, pour "un client simple", qui n'a besoin que de connexions sortantes et de leurs réponses.

Important : Dans le cas de certaines applications (comme Slim ou lxdm...); il est nécessaire d'autoriser les connexions "en interne", avec l'interface lo, de la même manière que dans le cas d'un "serveur tournant sur la machine elle-même" (voir un peu plus haut) .

Il ne reste plus qu'à sauver ces règles (le fichier de configuration est /etc/conf.d/iptables et par défaut les règles sont donc sauvées dans /etc/iptables/iptables.rules):

iptables-save > /etc/iptables/iptables.rules

et à relancer le pare-feu pour la session en cours:

systemctl restart iptables

Voilà, notre machine est dotée d'un Firewall normalement assez efficace. Désormais, lorsque vous essayez de lancer un service/connexion et que vous obtenez un message d'erreur (ou aucune réponse!); pensez d'abord à vérifier les règles mises en place...

Pare-Feu... mais pas que !

Effectivement, nous avons vu jusqu'ici comment se protéger des connexions non désirées. Mais iptables permet également de faire du routage de paquets, soit par translation d'adresse, soit par redirection de ports, ou autre... les possibilités sont vraiment nombreuses. Et c'est là qu'on utilise les autres tables, la table nat notamment… La table mangle sera quant à elle appelée par exemple pour passer un paquet entrant à un processus local avant de le redistribuer.

Liens