Mes passions, le boulots, mes coups de gueule...




Raspberry Pi : Configurer IPtables

Catégories : Geek, Informatique, Raspberry Pi · par 14 Juil 2014

IPtables-01

Je me suis récemment rendu compte des dangers auxquels mon Raspberry Pi était exposé.

Bien qu’il soit placé derrière un router avec des fonctions de pare-feu activées, le Pi n’est pas à l’abri de nombreuses attaques. J’ai donc activé quelques protections dont la première est IPtables.


Voici d’autres articles de mon blog qui traitent du même sujet :


Normalement, IPtables est installé d’origine sur le RPi.
Si ce n’était pas le cas, il suffit de l’installer comme ceci :

$ sudo apt-get update && sudo apt-get upgrade && sudo apt-get install iptables

Une fois le pare-feu installé, on va vérifier qu’aucune règle n’a été configurée :

$ sudo iptables -L

On devrait obtenir ceci :

Chain INPUT (policy DROP)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Pour bloquer des ports et modifier les restrictions d’accès, il faut appeler iptables en ligne de commande avec les privilèges root. Mais dès que le RPi est redémarré, tous ce qui a été configuré est perdu et il faut tout recommencer.

Pour éviter ces inconvénients, on va créer un script comprenant toutes les commandes pour configurer le pare-feu et l’exécuter lors du démarrage du Pi.

On crée un fichier que l’on va nommer firewall et que l’on va placer dans le dossier /etc/init.d/ :

$ sudo nano /etc/init.d/firewall

On va y copier les lignes suivantes :

#!/bin/sh
### BEGIN INIT INFO
# Provides:          firewall rules
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

#Suppression des règles précédentes
iptables -F
iptables -X

########
# DROP #
########

# Définition du blocage général
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# Drop des scans XMAS et NULL
iptables -A INPUT -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

##########
# ACCEPT #
##########

# Conservations des connexions déjà établies
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Autorisation du loopback (127.0.0.1)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Autorisation des échanges avec le serveur DNS (53)
iptables -A OUTPUT -p udp -m udp --dport 53 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp -m udp --sport 53 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# NTP (123)
iptables -A INPUT -p udp --sport 123 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

# HTTP (80)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT

# HTTP (81 - PHPMyAdmin)
iptables -A INPUT -s 192.168.0.1/24 -p tcp --dport 81 -j ACCEPT
iptables -A OUTPUT -s 192.168.0.1/24 -p tcp --dport 81 -j ACCEPT

# HTTP (8200 - MiniDLNA)
iptables -A INPUT -s 192.168.0.1/24 -p tcp --dport 8200 -j ACCEPT
iptables -A OUTPUT -s 192.168.0.1/24 -p tcp --dport 8200 -j ACCEPT

# MiniDLNA (1900)
iptables -A INPUT -s 192.168.0.1/24 -p tcp -m tcp --dport 1900 -j ACCEPT
iptables -A INPUT -s 192.168.0.1/24 -p udp -m udp --dport 1900 -j ACCEPT
iptables -A OUTPUT -s 192.168.0.1/24 -p udp -m udp --dport 1900 -j ACCEPT

# HTTP (9091 - Transmission-Daemon WebInterface - Direct Access)
iptables -A INPUT -s 192.168.0.1/24 -p tcp --dport 9091 -j ACCEPT
iptables -A OUTPUT -s 192.168.0.1/24 -p tcp --dport 9091 -j ACCEPT

# SSH (22)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT

# VNC (5900:5910)
iptables -A INPUT -p tcp --dport 5900:5910 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 5900:5910 -j ACCEPT

# Transmission (51413)
iptables -A INPUT -p tcp -m tcp --dport 51413 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 51413 -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 51413 -j ACCEPT
iptables -A OUTPUT -p udp -m udp --dport 51413 -j ACCEPT

# Announces trackers (9200)
iptables -A OUTPUT -p tcp --dport 9200 -j ACCEPT

# Ports Torrents (49152:65535)
iptables -A INPUT -p tcp --dport 49152:65535 -j ACCEPT
iptables -A INPUT -p udp --dport 49152:65535 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 49152:65535 -j ACCEPT
iptables -A OUTPUT -p udp --dport 49152:65535 -j ACCEPT

# ICMP (Ping)
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

# Parer les attaques de type Déni de Service
iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT

# Parer les scans de ports
iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ci-dessus le SSH est ouvert depuis n’importe quelle adresse sur le net, ce qui va nous permettre de nous connecter depuis n’importe où dans le monde.
Si vous modifiez cette règle, vous risquez de perdre l’accès à votre RPi en SSH.

On va maintenant rendre le script exécutable :

$ sudo chmod +x /etc/init.d/firewall

Puis, l’exécuter manuellement :

$ sudo /etc/init.d/firewall

Pour l’exécuter à chaque démarrage, on va l’inclure dans la liste des scripts qui s’exécutent au boot :

$ sudo update-rc.d firewall defaults

Voilà, une partie des ports sont bloqués, mais ceux qui sont restés ouverts (principalement pour les torrents) courent un risque.
Pour compléter la sécurité, on va installer Fail2Ban. Mais ça, c’est une autre histoire… 😉


Edit – 16 juillet 2014 :

J’ai remarqué que les logs de Fail2Ban comportaient régulièrement des attaques depuis des adresses IP situées dans les mêmes tranches.

2014-07-16 17:27:29,371 fail2ban.actions: WARNING [ssh] Ban 116.10.191.223
2014-07-16 17:27:29,549 fail2ban.actions: WARNING [ssh] Ban 116.10.191.212
2014-07-16 17:27:29,709 fail2ban.actions: WARNING [ssh] Ban 120.33.29.226
2014-07-16 17:27:29,889 fail2ban.actions: WARNING [ssh] Ban 61.174.51.224
2014-07-16 17:27:30,079 fail2ban.actions: WARNING [ssh] Ban 109.75.160.67
2014-07-16 17:27:30,238 fail2ban.actions: WARNING [ssh] Ban 202.137.9.53
2014-07-16 17:27:30,422 fail2ban.actions: WARNING [ssh] Ban 61.174.51.214
2014-07-16 17:27:30,587 fail2ban.actions: WARNING [ssh] Ban 116.10.191.163
2014-07-16 17:27:30,759 fail2ban.actions: WARNING [ssh] Ban 61.174.51.215
2014-07-16 17:27:30,948 fail2ban.actions: WARNING [ssh] Ban 116.10.191.234
2014-07-16 17:27:31,126 fail2ban.actions: WARNING [ssh] Ban 116.10.191.179
2014-07-16 17:27:31,305 fail2ban.actions: WARNING [ssh] Ban 116.10.191.231
2014-07-16 17:27:31,491 fail2ban.actions: WARNING [ssh] Ban 61.174.50.235

NB.: Toutes les heures sont identiques car j’ai reloadé Fail2Ban après avoir modifié les règles. Il a alors re-banni toutes les attaques trouvées dans la période décrite dans le findtime = 86400 (1 jour).

J’ai alors décidé d’ajouter quelques lignes dans la partie DROP d’IPtables, dans le fichier /etc/init.d/firewall :

# Bloquer certaines IP connues pour les attaques
# De 116.10.191.1 => 116.10.191.254
iptables -A INPUT -s 116.10.191.0/24 -j DROP
# De 61.174.50.1 => 61.174.51.254
iptables -A INPUT -s 61.174.50.0/23 -j DROP

Un calculateur de masque IPv4 pourra vous être utile :
http://cric.grenoble.cnrs.fr/Administrateurs/Outils/CalculMasque/

(28) comments

Baudoux
8 ans ago · Répondre

Bonjour,
Merci pour ce tuto : fantastique !
Eventuellement pourriez-vous m’aider (je suis loin d’être un spécialiste).
Voilà – j’aimerais modifier l’adresse 192.168.0.1 en 192.168.1.1. J’ai fait les modifs dans le script mais lorsque je veux intégrer la nouvelle version par ‘sudo update-rc.d firewall defaults’, j’ai une série de warnings et mon iptables (‘sudo iptables -L’) est remise à zéro (vide).
Cordialement
FBx

    fanjoe
    8 ans ago · Répondre

    Bonjour,

    La commande « sudo update-rc.d firewall defaults » permet de lancer la script firewall lors de chaque démarrage.
    Elle ne doit être exécutée qu’une fois.
    Si vous voulez changer les règles du firewall, modifiez simplement le script avec la commande : « sudo nano /etc/init.d/firewall ».
    C’est ce script modifié qui sera appelé au boot…
    Pour éviter de redemarrer le RPi, vous pouvez exécuter le script en vous plaçant dans le dossier « /etc/init.d/ » et en tapant la commande : « ./firewall ».

    Didier.

Youri
7 ans ago · Répondre

Bonjour,
Petite précision (qui évitera peut être à certains de chercher pendant un moment), le HTTPS semble bloquer avec ces règles (si je ne dis pas de bêtises). Il faut l’autoriser avec les lignes :
iptables -A INPUT -p tcp –dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp –dport 443 -j ACCEPT

    fanjoe
    7 ans ago · Répondre

    Merci,

    C’est modifié !

    Didier.

Bluescreen
7 ans ago · Répondre

Histoire d’être pointilleux, les lignes pour 443 que tu as rajouté ne fonctionnent pas si on « copie/colle » le pavé.
Le « – » a été transformé et fait foirer la ligne. ^^

    fanjoe
    7 ans ago · Répondre

    Merci pour la remontée. 😉
    C’est corrigé.

PP
7 ans ago · Répondre

Bonjour j’ai réalisé le script au démarrage, il fonctionne très bien quand je le lance manuellement mais lors du démarrage le fichier Blacklist.txt est vide, donc je pense qu’il ne fonctionne pas? Auriez-vous une solution?

Merci

    fanjoe
    7 ans ago · Répondre

    Bonjour,
    Comme le script s’exécute au démarrage, il est possible que la connexion internet ne soit pas encore initialisée.
    D’où le retour d’un fichier vide.
    Peut-être ajouter un WAIT ?
    Didier.

pp
7 ans ago · Répondre

Merci de votre réponse mais j’ai réussi en rajoutant le lien du script dans rc.local.

PP
7 ans ago · Répondre

Bonjour, j’ai donc installé iptables sur mon Raspberry mais le problème c’est qu’il met 2 voir 3 heures pour mettre à jour, avec la Blacklist, j’ai pris la blacklist avec toutes les IP’s? Est-ce normal?

PP
6 ans ago · Répondre

Bonjour, pouvez-vous me donner la manip pour avoir Geoip sur Raspberry, il me met ce message d’erreur: iptables: No chain/target/match by that name?

Merci

    fanjoe
    6 ans ago · Répondre

    Bonjour,

    Oui, c’est normal.
    La méthode n’est pas très adaptée aux très grandes listes d’IP à bannir.
    Voyez un autre article qui répondra mieux à votre cas : https://www.fanjoe.be/?p=3233
    Didier.

pp
6 ans ago · Répondre

merci beaucoup. Par contre, il me marque: ipset v6.30: The set with the given name does not exist
je dois m’en inquiéter?

    fanjoe
    6 ans ago · Répondre

    Une recherche Google ?

pp
6 ans ago · Répondre

Déjà fait, il n’ y a pas grand chose! Du moins rien qui fonctionne pour moi!

Michel Mostaert
6 ans ago · Répondre

Bonjour,

Je monte actuellement un raspberry Pi pour faire de la domestique entre autres. Je suis informaticien dans une grosse entreprise et j’y ai appris pas mal de choses, que je souhaite appliquer avec le Pi également: sécurité, backups monitoring etc. Mais je ne suis pas un féru du monde Linux, c’est pourquoi cela me prend un peu de temps.
J’ai analysé le fichier fourni ci-dessus, de règles IPtables et j’ai été surpris de voir trois règles « DROP » intégral en premier lieu… J’imagine que le principe d’IPtables est de filtrer les paquets TCP/IP sur base des règles qui lui sont fournies, et dès qu’un paquet correspond à une règle d’appliquer la règle de filtrage en question et le paquet est traité c’est terminé au suivant… Du coup, si on fait un DROP complet sur l’entrée, la sortie et le forward en commençant, pour moi tous les paquets seront filtrés par ces règles « DROP » et ne se verront appliquer aucune des règles suivantes…
J’ai montré ces règles à des collègues spécialisés en Linux qui partagent mon avis… Du coup j’imagine que quelque chose doit nous échapper mais quoi ? Merci d’avance d’éclairer nos lanternes.
Cordialement,

    fanjoe
    6 ans ago · Répondre

    Bonjour,

    Le paramettre -P définit la « politique par défaut » de la chaine INPUT, FORWARD et OUTPUT.
    En bref, on verrouille tout et ouvre un par un en attachant des règles avec le paramettre -A.

    Je ne suis pas spécialiste d’IPtables. Je partage juste ma configuration largement inspirée de ce que j’ai glané un peu partout sur le web.

    Un exemple de la doc Ubuntu : https://doc.ubuntu-fr.org/iptables

    Didier.

Michel Mostaert
6 ans ago · Répondre

Bonjour,

@fanjoe merci beaucoup pour le retour… Comme vous le voyez je suis loin d’être un spécialiste d’IPtables ou de Linux moi-même, mais j’apprends progressivement…

Bien à vous,

Michel Mostaert
6 ans ago · Répondre

Bonjour,

J’ai commencé à personnaliser le fichier de règles fourni ici… Une bonne base, indiscutablement. J’ai retiré le range VNC (un seul port suffit j’imagine), le HTTP et le HTTPS en entrée (pas de serveur web pour l’instant). Pouvez-vous encore me dire à quoi sert le port 9200 ouvert dans votre fichier ? Je n’ai trouvé que du « WAP » comme infos sur ce port, je ne vois pas bien ce que viendrait faire une vieille technologie de navigateur sur GSM dans un PC…

Merci d’avance,

Cordialement;

Michel

Michel Mostaert
6 ans ago · Répondre

Bonjour Didier,

Super merci beaucoup pour le retour et compliments pour la disponibilité… Les gens qui partagent leurs connaissances, j’apprécie bcp.
Cordialement,
Michel

maxime
6 ans ago · Répondre

Bonjour,

Je dis peut être une bêtise mais si on redirige uniquement un port ssh de notre box vers celui de notre raspberry. Il n’est alors pas vraiment nécessaire de mettre en place toutes les règles sur les ports nn ?
Fail2Ban est quant à lui très utile pour sécurisé le port ssh.
Mais je ne comprend pas l’intérêt de protéger tous les autres ports qui ne sont accessible que chez nous en local.

Cordialement,
Maxime.

lecorremaxime
6 ans ago · Répondre

Bonjour Didier,

Je suis nouveau dans le domaine mais j’ai du mal a comprendre cette crainte au niveau de la sécurité. Par exemple si on redirige un port ssh de notre box vers notre raspberry (ex : 22), à ce moment le sécuriser ce port devient intéressant. Mais pourquoi aller sécuriser tous les autres ports ? La raspberry est sur notre réseau local, il n’y a que en local que nous pouvons accéder à ces ports.

Cordialement.

    fanjoe
    6 ans ago · Répondre

    Bonjour,

    Effectivement, sur un réseau local, le risque est faible, mais en entreprise, l’attaque peut être menée en interne.

    Pour divers raisons, il peut être nécessaire de placer le serveur en DMZ. Ce n’est peut-être pas la meilleure idée, mais c’est possible.

    Aussi, avec l’arrivée des objets connectés (domotique, caméras IP, …) on n’est pas à l’abris d’une faille dans le firmware de ceux-ci qui ouvrirait une brèche sur le réseau local.

    En matière de sécurité, à mon sens, mieux vaut être parano et prévoir le pire.

    Didier.

      lecorremaxime
      6 ans ago ·

      Merci beaucoup pour cette réponse très rapide.
      Je vais donc me diriger vers la solution parano ^^

      Cordialement,
      Maxime.

Olivier M
5 ans ago · Répondre

Bonjour

Pour les règles avec OUTPUT sur un port particulier, ne faut il pas plutôt écrire –sport plutôt que –dport ??
Car en appliquant uniquement la règle SSH de votre tuto j’étais bloqué et impossible de me connecter à mon serveur.
Cela s’est débloqué en corrigeant en –sport

Très bon tuto cela m’a fait grandement progresser dans la compréhension d’iptables.

ThierryR
5 ans ago · Répondre

Formidable. C’est une belle base pour sécuriser son raspi. De plus partager ses connaissances est bien dans l’esprit linux. Félicitations.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.