Ma méthode pour gérer les règles IpTables

Date: 10/06/2013 | Catégories: Open-source,Planet-libre,Systeme | Tags: ,,

iptables"Ooopsss..."

Cette phrase a été prononcée au moins une fois par toute personne ayant administré les règles de Firewall d'un serveur. Les conséquences vont du simple blocage d'une application critique (dont on s’aperçoit de l'indisponibilité au prochain "check" sur son serveur de monitoring) à la perte de connexion pure et simple vers la machine (même pour corriger sa boulette).

Pour éviter de se retrouver dans cette situation et ainsi éviter les rires et moqueries des collègues, voici quelques pistes que j'utilise pour administrer mes règles IpTables sur mes serveurs Debian.

1. Regrouper la sécurité dans un script de démarrage

Il y a plusieurs écoles pour gérer les règles de Firewall. Celle proposée par le wiki officiel de Debian repose sur l'utilisation exclusive des commandes iptables-save et iptables-restore qui permettent respectivement de sauvegarder et de restaurer une configuration IpTables existante.

Pour ma part, je préfère inclure ces commandes dans un script de plus haut niveau que je positionne dans le répertoire /etc/init.d et qui sera donc lancé au démarrage du serveur. Ce fichier firewall.sh est disponible sur mon GitHub DebianPostInstall ou via Gist.

En voici une version à ce jour:

Par défait le script met en place les règles suivantes:

  • autorise les connexions SSH entrantes (pour administrer son serveur à distance)
  • autorise les connexions HTTP, HTTPs et DNS sortante (pour l'installation et mise à jour du système et des logiciels)
  • interdiction et log des autres flux, entrant et sortant
  • et en cadeau bonux (ce qui on plus de 35 ans peuvent comprendre) sécurise un peu plus le kernel Linux

L'utilisation de ce script est standard, ainsi pour appliquer les règles de Firewall:

Pour supprimer les règles de Firewall (attention votre serveur sera ainsi exposé aux attaques extérieures puisqu'aucunes restriction d'accès ne sera appliquée):

Attention: Il est également possible d'utiliser cette commande avec l'option stop (sudo service firewall.sh stop), mais il faut être conscient que toutes les connexions, entrantes et sortantes seront alors interdites (même votre SSH !!!). Cette commandes est donc à éviter bannir si l'on utilise une connexion à distance pour administrer son serveur...

2. Modifier les règles

On entre ici dans le vif du sujet de ce billet: Comment procéder quand on doit modifier les règles de sécurité ?

La première chose à faire est d'être sûr d'avoir les connaissances nécessaires avant de toucher à quoi que ce soit. Cela peut sembler évident, mais faire des copier/coller de règles trouver sur le net et que l'on ne maîtrisent pas est, sans aucun doute, le meilleur moyen de tout faire planter. Pour modifier les tables IpTables, il faut donc avoir un verni de connaissance général sur le protocole TCP/IP (notamment les notions d'adresses et de port sources/destinations). On trouve pour cela quelques très bon cours en ligne comme celui de chez Developpez.com ou bien la bible de Tanenbaum: Réseaux 5em édition aux éditions Pearson. Bien évidemment, il faut également connaitre les rudiments de la commande IpTables en lisant la documentation officielle (disponible en Français) et notamment la section sur le filtrage de paquets.

On peut passer aux choses sérieuses en identifiant les règles courantes grâce à la commande:

On obtiendra alors une sortie dépendante des règles actives (exemple pour un de mes serveurs):

Une fois que vous avez identifié la règle IpTables à ajouter dans votre configuration,  il est maintenant temps de passer à l'action.

Ne jamais, jamais, modifier directement la table avec une commande IpTables sur un serveur en production...

Plusieurs solutions sont possibles, personnellement, j'utilise la méthodologie suivantes:

  1. je commence par copier le script firewall.sh dans un autre répertoire (par exemple dans /tmp/firewall.sh)
  2. j'ajoute la règle IpTables dans la copie du script (/tmp/firewall.sh)
  3. je teste les nouvelles règles en utilisant l'option "test" du script ainsi modifié qui va sauvegarder les règles actuelles, appliquer les nouvelles, attendre 30 secondes puis ré-appliquer les règles actuelles (donc au pire au fait une boulette de 30 secondes...)
  4. si tout se passe comme attendu pendant les 30 secondes, alors je copie le fichier /tmp/firewall.sh sous /etc/init.d
  5. et j'applique les règles en production le moment voulu

Les lignes de commandes correspondantes sont:

Ainsi, en cas de problème dans les règles, le serveur ne sera indisponible que pendant 30 secondes. Dans le cas "pas de bol" ou le serveur crache durant ces 30 secondes alors les anciennes règles seront rechargées au redémarrage.

Pas de script ?

Si vous ne souhaitez pas mettre en place un tel script de démarrage des règles de Firewall, il est quand même possible (même si je ne le conseille pas pour avoir une vue d'ensemble des règles à appliquer) de reproduire la méthodologie d'écrite dans le chapitre précédant.

Ainsi, il est tout à fait possible d'utiliser une commande du type:

Conclusion

Comment gérez-vous vos règles de Firewall sur vos serveurs GNU/Linux ? Des astuces à partager avec nous dans les commentaires ?

  • stombi

    Pour moi c’est exclusivement avec iptables-save, iptables-restore et le paquet iptables-persistent pour tout soit lancé au boot.

  • Nicolas KAROLAK

    Merci pour le partage !

    Pour le moment j’utilise UFW, il simplifie grandement la chose et semble bien faire son boulot. Pourquoi as-tu fait le choix d’IPTables ? Performance et/ou sécurité supérieure ? Gestion plus fine des règles ? Habitude ? Geekitude ?

    • Habitude… J’étais un utilisateur de Pf avant (sur BSD).
      Je vais me noter de regarder UFW car tu n’es pas le premier à m’en parler.

      • Loïc BLOT

        Utiliser PF sur OpenBSD c’est l’adopter.

        Le souci des outils
        comme UFW c’est qu’ils font des ensembles de règles pensées de la même
        manière. Si on prend l’exemple de PF, écrire des règles à la iptables ou
        ACL CISCO n’est pas du tout pertinent, a cause des optimisations de PF
        avec ses tables, la notion de stateful intégrée…

  • paulez

    J’utilise Shorewall, un frontend à Iptables.

    • Nassim

      +1 pour Shorewall, règles très lisibles grâce à une gestion par zones, sécurité d’utilisation grâce à des fonctionnalités comme le safe-restart.

  • j’utilise ufw. Il est suffisamment simple et performant. De plus, il s’intègre bien avec Fail2ban.
    Pour des applications complexes, je préfère shorewall.

  • Aymeric

    Personnellement, j’utilisais pas mal firewall builder pour une interface type checkpoint et firewall eyes (mais qui nécessite de traiter les logs ailleurs que dans le syslog) pour se donner des yeux et des mains 🙂

  • thierry_jaouen

    J’utilise « ferm »: une légère surcouche a IpTables , qui active les règles de manières atomique. L’essayer, c’est l’adopter: http://ferm.foo-projects.org/download/2.1/ferm.html

  • Thomas Prevot

    Pour ma part, j utilise firewall buildeŕ , qui permet de gerer une ferme de parefeux avec des règles communes ds une seule interface. fonction cluster de parefeux, compatible linux,bsd, cisco asa/pix, acl procurve.. Bref très pratique pour maintenir une cohérence ds un ensemble de parefeux.

    Je vais qd même jeter un oeil aux autres. Merci pour le partage

  • polohb

    Merci pour ces info, j’utilise a peu près la même manière (script dans init.d)
    Merci aussi pour « l’option test » du script qui devrait être assez pratique lors d’une prochaine modif 😀

    ps : fin de partie 1, on n’écrit pas contient mais plutôt conscient.

  • Majoux

    Merci pour ce script de toute beauté.

    [mode flemmard]Si tu pouvais mettre à jour pour éviter le :
    « WARNING: The state match is obsolete. Use conntrack instead. »

    ça serait cool [/mode flemmard]

  • Raphaël SurcouF

    Nico, par rapport à l’application de nouvelles règles pour tester, depuis iptables 1.4.1.1, il existe maintenant une nouvelle commande en plus de iptables-save et iptables-restore : iptables-apply.

    Cette dernière permet justement d’appliquer de nouvelles règles à partir d’un fichier et demande confirmation après les avoir appliqués. Faute de réponse dans un délai déterminé, les anciennes règles sont remises en route :

    $ man iptables-apply
    « NAME
    iptables-apply – a safer way to update iptables remotely

    SYNOPSIS
    iptables-apply [-hV] [-t timeout] ruleset-file

    DESCRIPTION
    iptables-apply will try to apply a new ruleset (as output by iptables-save/read by iptables-restore) to iptables, then prompt the user whether the changes are okay. If the new ruleset cut the existing connection, the user will not be able to answer affirmatively. In this case, the script rolls back to the previous ruleset after the timeout expired. The timeout can be set with -t. »

  • geronimo

    salut une question sur iptables. En lançant le script à priori tout fonctionne bien cependant en faisant un iptables -L -v je vois des paquets en DROP (en INPUT et OUTPUT)

    comment puis je en savoir plus? un fichier log existe?

    PS: j’ai trouvé ici:
    http://www.thegeekstuff.com/2012/08/iptables-log-packets/

  • j’utilise une méthode a peut prêt identique, dès l’installation d’un dédié :).

  • kendyan

    Hello, merci pour pour ce script. Par contre il ne fonctionne pas avec NGINX . J’ai des logs de ce type :

    kernel: IN= OUT=eth0 SRC=XX.XX.XX.XX DST=XX.XX.XX.XX LEN=211 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP SPT=49352 DPT=6157 LEN=191

    Lorsque je mets l’ip dans le navigateur, cela mouline et puis rien.
    Si je fais un clear, tout fonctionne.

    Une idée ?

    Edit : J’ai trouvé la solution sur un autre de tes scripts :

    echo « Notes: If you use IpTables add the following rules »
    echo « iptables -A INPUT -i lo -s localhost -d localhost -j ACCEPT »
    echo « iptables -A OUTPUT -o lo -s localhost -d localhost -j ACCEPT »
    echo « iptables -A OUTPUT -m state –state RELATED,ESTABLISHED -j ACCEPT »
    echo « iptables -A INPUT -p tcp –dport http -j ACCEPT »

  • Pingback: Les commandes GNU/Linux qui vous feront gagner du temps()

  • Esmedo

    Bonjour,

    Merci pour le script. Je viens de le tester sur debian7 et j’ai un soucis pour faire le test apache- it works, je ne peux pas atteindre le serveur en http. Je sais que tu dis que ce n’est pas bien mais j’ai fait un iptables -A INPUT -p tcp -m tcp –dport 80 -j ACCEPT et c’est bon.

    Pourtant le port 80 fait bien partit de ton script. Je débute dans la config de serveur, tu saurais me dire quel est le problème ?

    Merci,
    David

  • dcampillo

    Question de débutant: pourquoi la commande stop bloque tout le traffic entrant et sortant, au lieu de faire un « Clear » ? De mon point de vue, si je souhaite « stopper » le firewall, c’est que je souhaite arrêter le firewall et donc laissé passer tout le traffic entrant et sortant ?

    Je pensais modifier ton script et faire en sorte qu’un « stop » fasse un « clean », mais est-ce qu’il y a vraiment une raison d’avoir le « stop » ?

  • dcampillo

    Une question avec CIFS:

    J’ai utilisé vore script j’ai ouvert les port que j’avais besoin…c’est vraiment la classe pour les débutants. Par contre, je n’ai pas ouvert ni authorisé le port 445 pour CIFS/SMB, mais mes partages réseau sont quand même montés.

    Il y a quelques chose que je ne capte pas ?

  • Pingback: exemple de script iptables()

  • maz

    Sauf erreur de ma part la partie test n’est pas correcte :

    w_test () {
    fw_save (<– tu sauvegarde la config actuelle)

    sleep 30 && echo "Restore previous Firewall rules…" && fw_restore & (<– tu dors 30 secondes puis tu restaures la config qui n'avait pas changé entre temps)

    fw_stop (<– là tu arrêtes tout le trafiic)

    fw_start (<– là tu redémarres avec les nouvelles règles)

    Pour moi, si je ne me trompe pas, c'est juste un start différé de 30 secondes avec une sauvegarde potentiellement inaccessible si on a fait une bourde dans la config. J'écrirais plutôt :

    w_test () {
    fw_save (<– tu sauvegarde la config actuelle)

    fw_stop (<– là tu arrêtes tout le trafiic)
    fw_start (<– là tu redémarres avec les nouvelles règles)
    sleep 30 && echo "Restore previous Firewall rules…" && fw_restore & (<– tu dors 30 secondes puis tu restaures la config qui n'avait pas changé entre temps)

    Autre question que je me pose : que se passe-t-il si je lance cette commande sur un serveur distant via ssh sans précéder ma commande de nohup ? Car au moment du fw_stop, je suis déconnecté et si le serveur ne poursuit pas l'exécution du script (ce qui me paraît logique), ben je n'y ai plus accès… Me tompe-je ?