Le port SSH doit probablement être parmi les plus testés par les scripts kiddies. Même si le mieux reste de restreindre l'accès par IP et de n'autoriser l'authentification que par clé, ce n'est des fois pas possible. Dans ce cas, on se retrouve avec une avalanche de tentative de connexion et le auth.log qui explose en taille. Ça devient lourd (dans les 2 sens du terme :-) ).
Afin de bannir une IP au bout d'un trop grand nombre de connexions par unité de temps, il existe différents outils qui analysent les logs et ajoutent des règles dynamiquement comme fail2ban, mais je préfère agir directement au niveau pare-feu quand c'est possible. Avec iptables sous Linux, il existe le module limit. Avec Packet Filter, voici comment procéder :
Créer une table, qui contiendra les IP bannies :
table <badguys> persist
on drope donc tous ce qui provient des IP présentes dans la table :
block in quick on $wan_if from <badguys>
et enfin la règle intéressante :
pass in on $wan_if proto tcp to self port ssh flags S/SA keep state (max-src-conn 3, max-src-conn-rate 5/30, overload <badguys> flush global)
La règle permet de limiter l'établissement d'une connexion sur le port SSH à 3 connexion simultanée (
max-src-conn 3
) et avec une limite de 5 connexion par tranche de 30 secondes (max-src-conn-rate 5/30
). Si une IP dépasse cette limite, elle est ajoutée à la table badguys (overload <badguys>
) et tous les états que l'IP aurait déjà pu avoir sont supprimés (flush global
).
Ensuite, on peut faire expirer les IP présentes dans la table avec un simple cron :
33 3 * * * /sbin/pfctl -t badguys -T expire 86400 2>&1 |grep -v "0/0 addresses expired."