0

[Série Sécurisation] Firewall avec iptables

Pour poursuivre dans mes bonnes résolutions 2012 visant la sécurisation de mon PC, j'ai pensé qu'un firewall efficace était une étape indispensable. En effet, puisque je route tout mon trafic dans un tunnel VPN possédant une IP publique, les ports de mon PC sont grand ouverts sur le net.

J'ai beaucoup cherché un Firewall applicatif qui m'aurait permis d'autoriser les applications au cas par cas mais malheureusement il n'y a pas de solution digne de ce nom sous Linux. J'ai donc opté pour du bas niveau : de bonnes vieilles règles iptables !

Le script

Avec iptables, on établit des règles pour l'INPUT d'une part et l'OUTPUT d'autre part :

  • INPUT désigne les connexions entrantes. Cela désigne donc les connexions que votre machine n'a pas initiées elle-même mais aussi les retours de paquets UDP. Je lui ai assigné la politique par défaut DROP c'est-à-dire ne rien laisser passer sauf mes exceptions.
  • OUTPUT désigne les connexions sortantes. Cela désigne donc les connexions initiées par votre machine mais aussi les retours de paquets UDP. Je lui ai assigné la politique par défaut ACCEPT c'est-à-dire tout laisser passer sauf mes exceptions.
  • /etc/fw.sh
    #!/bin/sh

    # Flush previous rules for clean firewall
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -F INPUT
    iptables -F OUTPUT

    # Don't fuck with already established or related connections (even UDP will pass if it was locally initiated)
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

    # MY RULES BEGIN

        # Input with default policy drop : exception = ACCEPT
        iptables -A INPUT -p tcp -s 192.168.0.0/16 --dport 22 -j ACCEPT # SSH from LAN
        iptables -A INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT  # Avahi/ZeroConf
        iptables -A INPUT -p tcp --dport 6881:6999 -j ACCEPT            # Bittorrent
        iptables -A INPUT -p tcp --dport 50210 -j ACCEPT                # Tomahawk
       
        # Output with default policy accept : exception = DROP
        iptables -A OUTPUT -p udp ! -d 192.168.0.0/16 --sport 17500 -j DROP    # Block Dropbox broadcasts except on LAN
       
        # Microsoft filesharing shit (Samba/CIFS) only accepted on 192.168.0.0/16.
        iptables -A INPUT -p udp -d 192.168.0.0/16 --sport 137 -j ACCEPT
        iptables -A INPUT -p udp -d 192.168.0.0/16 --sport 138 -j ACCEPT
        iptables -A OUTPUT -p udp ! -d 192.168.0.0/16 --sport 137 -j DROP
        iptables -A OUTPUT -p udp ! -d 192.168.0.0/16 --sport 138 -j DROP
        iptables -A OUTPUT -p tcp ! -d 192.168.0.0/16 --sport 139 -j DROP
        iptables -A OUTPUT -p tcp ! -d 192.168.0.0/16 --sport 445 -j DROP

    # MY RULES END

    # Allow all ICMP
    iptables -A INPUT -p icmp -j ACCEPT
    iptables -A OUTPUT -p icmp -j ACCEPT

    # Trusted interfaces
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT

    # Set default rule (policy)
    iptables -P INPUT DROP
    iptables -P OUTPUT ACCEPT

    echo "Firewall up!"

    Dans ce script vous pourrez clairement distinguer la zone à adapter selon vos besoins (partie "MY RULES"). Les règles sont assez explicites et ne nécessitent pas d'autres précisions si ce n'est la consultation de la manpage d'iptables.

    Surveiller les règles

    Une petite commande vous permettra de surveiller où passe/est bloqué votre trafic :

    # iptables -Z && watch iptables -L -v

    Cela affichera une règle par ligne, avec la première colonne spécifiant le nombre de paquets concernés par la règle.

    Persistance au reboot

    Après avoir exécuté le script et testé que tout fonctionne bien, le plus simple sous Gentoo est d'exploiter l'init script dédié à iptables :

    # /etc/init.d/iptables start
    # /etc/fw.sh
    # /etc/init.d/iptables save
    # rc-update add iptables

    Ainsi vos règles seront réétablies au reboot de votre machine. N'oubliez pas de refaire un /etc/init.d/iptables save à chaque fois que vous modifiez vos règles de firewall.

    Mode paranoïaque : OUTPUT en DROP

    Personnellement je trouve que sur une machine personnelle, bloquer la sortie est un peu poussé et souvent chiant. Mais pour des applications plus importantes comme un serveur il vous faudra sans doute envisager de changer la politique de l'OUTPUT et autoriser les ports au cas par cas.

    Mais comme je le disais, je trouve ça chiant sur une machine personnelle et je ne le documenterai pas.

    Je suis ouvert aux suggestions

    J'ai écrit ces règles de firewall hier et les teste donc depuis moins de 24 heures. Si vous pensez à une règle que j'aurais oubliée, merci de me le faire savoir en commentaire 😉