Règles iptables anti brute force pour SSH

Nombreux sont les administrateurs se plaignant de la quantité d’attaques de type « brute force » (essai d’une multitude de mots de passe sur un compte donné) effectuées sur leurs serveurs SSH écoutant sur le port standard (22).

« iptables » Permet de mettre en place une protection sommaire contre ce type d’attaque du genre :

« Il est interdit d’effectuer plus de 4 connexions par minutes sur le port SSH. ».

Cette méthode n’a rien de nouveau mais reste efficace et peu contraignante. Ce post la rappelle rapidement.

Mise en place de l’anti brute force

Commençons par l’écriture d’une « chaîne nommée » (ensemble de règles appelées par un nom personnalisé) préfixant les logs des requêtes qui lui sont transmises et refusant la connexion :

# Regle log ssh drop :
iptables -N SSH_DROP
iptables -A SSH_DROP -m limit --limit 1/s -j LOG --log-prefix '[fw drop -> Attack ssh] : '
iptables -A SSH_DROP -j DROP

ou pour les utilisateurs d’ULOG :

# Regle log ssh drop :
iptables -N SSH_DROP
iptables -A SSH_DROP -j ULOG --ulog-nlgroup 1 --ulog-prefix '[fw drop -> Attack ssh] : '
iptables -A SSH_DROP -j DROP

Cette chaîne sera appliquée pour bloquer une machine.

Rappel : les règles « iptables » sont traitées, par défaut, dans l’ordre dans lesquelles elles sont définies.

L’anti brute-force proprement dit peut s’écrire ainsi :

1
2
3
4
# Regles anti-brute force :
iptables -A INPUT -d ${IP_EXT} -p tcp --dport ${PORT_SSH} -m recent --update --seconds 60 --hitcount 4 --name SSH -j SSH_DROP
iptables -A INPUT -d ${IP_EXT} -p tcp --dport ${PORT_SSH} -m recent --set --name SSH
iptables -A INPUT -d ${IP_EXT} -p tcp --dport ${PORT_SSH} -m state --state NEW -j ACCEPT

qui se lira :

  • ligne 2 : si le compteur « SSH » (–name) référence « 4 » tentatives (–hitcount) d’entrées sur « IP_EXT » sur le port « PORT_SSH » depuis moins de « 60 » secondes, appliquer « SSH_DROP ». Sous entendu : « sinon passe à la règle suivante ».
  • ligne 3 : Si une tentative de connexion est effectuée sur « PORT_SSH » d' »IP_EXT », incrémente le compteur « SSH ». Encore sous entendu : « sinon passe à la règle suivante ».
  • ligne 4 : accepte les connexion SSH à destination de « IP_EXT ».

En fonctionnement, cela donne :

  • De la première à la quatrième tentative :
    • règle 1 : le compteur SSH < ou = 4, passage à la règle suivante ;
    • règle 2 : incrémente SSH ;
    • règle 3 : autorise la connexion ;
  • Cinquième tentative :
    • règle 1 : compteur SSH > 4, applique SSH_DROP ;
    • chaîne SSH_DROP : log la connexion en la préfixant par « [fw drop -> Attack ssh] :  » puis DROP la connexion.

Résultat

Si nous tentons 5 connexions successives en moins d’une minute, la machine nous fait patienter et consigne l’attaque dans les logs :

18:48:56 fhh@mafalda ~ $ ssh srv
fhh@srv's password: ^c
18:49:01 fhh@mafalda ~ $ ssh srv
fhh@srv's password: ^c
18:49:02 fhh@mafalda ~ $ ssh srv
fhh@srv's password: ^c
18:49:04 fhh@mafalda ~ $ ssh srv
fhh@srv's password: ^c
18:49:05 fhh@mafalda ~ $ ssh srv
--- plus de prompt ---^c

et dans les logs :

Dec  8 18:49:24 srv [fw drop -> Attack ssh] :  IN=br0 OUT= MAC=XXXXXXX  SRC=XXXXXXXX DST=XXXXXXXXXX LEN=60 TOS=00 PREC=0x00 TTL=64 ID=16030 DF PROTO=TCP SPT=57334 DPT=22 SEQ=2340649455 ACK=0 WINDOW=14600 SYN URGP=0

Notes complémentaires

Cette « protection » part des principes (souvent vérifiés) que :

  • les programmes attaquant effectue une tentative d’authentification par connexion ;
  • qu’un programme ne pouvant tester plus de 4/12 mots de passe par minutes délaissera le serveur ciblé.

Côté utilisateur, rappelons qu’iptables contrôle les connexions et non les tentatives d’identification. En général, trois tentatives d’authentification sont possible par connexion via le client SSH. Un utilisateur devrait donc effectuer 12 tentatives de mot de passe infructueuse en moins d’une minute pour ce faire bannir (comportement suffisamment suspect pour justifier de le faire attendre quelques secondes).

Si vous effectuez des sauvegardes via rsync par exemple ou ses dérivés (rsnapshots, etc) utilisant une authentification par couple de clés (publique/privée) pensez a ajouter une règle pour la machine de sauvegarde sous peine de la voir considérée comme attaquante par votre firewall…

Si les attaques persistent, complétez votre stratégie de sécurité par d’autres outils du type fail2ban, etc.

Références

9 réflexions au sujet de « Règles iptables anti brute force pour SSH »

  1. Bonjour,
    La commande suivante me renvoi une erreur :
    # iptables -A INPUT -d ${IP_EXT} -p tcp –dport ${PORT_SSH} -m recent –update –seconds 60 –hitcount 4 –name SSH -j SSH_DROP

    Bad argument `tcp’
    Try `iptables -h’ or ‘iptables –help’ for more information.

    Une idée du problème ?
    Pour info, je suis sur Debian 6.

    Merci

  2. afaik Cela facilite le (D)DoS car matraquer le port interdit à qui que ce soit d’établir une session SSH.

    Mieux vaut peut-être limiter le nombre max de tentatives d’accès durant un laps de temps donné par IP source, peut-être ainsi:

    iptables -A INPUT -i eth+ -p tcp –dport MonPortSSH -m state –state NEW -m recent –set –name SSH –rsource
    iptables -A INPUT -m recent –update –seconds 15 –hitcount 10 –rttl –name SSH –rsource -j DROP
    iptables -A INPUT -i eth+ -p tcp -m tcp –dport MonPortssh -j ACCEPT

    Ce n’est pas parfait mais plus solide et le DDOS n’est plus directement facilité par la limitation.

    1. Salut Nat,

      En fait non, pas de déni de service en matraquant le port ssh avec ces règles.

      Comme tu peux le lire dans le man d’iptables (http://linux.die.net/man/8/iptables) « set » enregistre par défaut les ips sources :

      [!] --set
      This will add the source address of the packet to the list. If the source address is already in the list, this will update the existing entry. This will always return success (or failure if ! is passed in).

      et si tu lit le descriptif de « rsource » tu y trouvera « This is the default« .

      En bref les règles proposées dans l’article et celles que tu propose sont à peu de choses près identique…

      1. > si tu lit le descriptif de “rsource” tu y trouvera “This is the default“.

        Ah bien vu. J’ignore si cela a changé ou si j’avais mal lu. Merci!

  3. A peu prés la même chose, mais avec « ferm » .
    En bonus, une liste d’IP (ou de subnet) autorisés. Je precise l’interface exposé a Internet, et non pas que son IP.

    Par exemple, dans un fichier « ferm.conf »


    # ------------------------------------
    # Regles iptables avec Ferm
    # ------------------------------------

    @def $WAN_IF = eth1;

    # ---------------------

    chain ( INPUT OUTPUT FORWARD ) policy DROP;

    # ---------------------
    # Local
    # ---------------------

    chain INPUT if lo ACCEPT;
    chain OUTPUT of lo ACCEPT;

    # ---------------------
    # Pre-Limit
    # ---------------------
    # But: interdire le brut-force sur ssh

    # Liste des IPs qui echappent a la pre-limit

    @def $PRE_LIMIT_AUTHORIZED = (
    82.67.215.202 # au hasard...
    212.27.48.10
    207.46.197.32/24
    );

    table filter chain PRE_LIMIT_DROP {
    mod limit limit 5/s LOG log-prefix 'FW=pre_limit_drop ' log-level info;
    DROP;
    }

    table filter chain PRE_LIMIT {
    saddr $PRE_LIMIT_AUTHORIZED RETURN;
    mod state state NEW mod recent set rsource name "pre_limit" NOP;
    mod state state NEW mod recent update seconds 120 hitcount 4 rsource name "pre_limit" jump PRE_LIMIT_DROP;
    }

    # ---------------------
    # WAN
    # ---------------------

    chain INPUT if $WAN_IF proto tcp dport ssh {
    jump PRE_LIMIT;
    ACCEPT;
    }

    # ---------------------
    # EOF

    Appliquer par:

    ferm -i ferm.conf

    C’est sympa ferm 🙂

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *