Sécurité SSH · 15 min read · Jan 10, 2026
Prévenir les attaques par dictionnaire SSH avec DenyHosts
Prévenir les attaques par dictionnaire SSH avec DenyHosts
Version 1.0
Auteur : Falko Timme
Dernière modification : 02/07/2006
Dans ce HowTo, je vais montrer comment installer et configurer DenyHosts. DenyHosts est un outil qui observe les tentatives de connexion à SSH, et s’il trouve des tentatives de connexion échouées encore et encore depuis la même adresse IP, DenyHosts bloque d’autres tentatives de connexion depuis cette adresse IP en l’ajoutant à /etc/hosts.deny. DenyHosts peut être exécuté par cron ou en tant que démon. Dans ce tutoriel, je vais exécuter DenyHosts en tant que démon.
Depuis le site web de DenyHosts :
“DenyHosts est un script destiné à être exécuté par les administrateurs système Linux pour aider à contrer les attaques sur les serveurs ssh.
Si vous avez déjà regardé votre journal ssh (/var/log/secure sur Redhat, /var/log/auth.log sur Mandrake, etc…), vous pourriez être alarmé de voir combien de hackers ont tenté d’accéder à votre serveur. Espérons qu’aucun d’eux n’a réussi (mais alors, comment le sauriez-vous ?). Ne serait-il pas mieux d’empêcher automatiquement cet attaquant de continuer à entrer dans votre système ?
DenyHosts tente de répondre à cela… “
Ce tutoriel est basé sur un système Debian Sarge, cependant, il devrait s’appliquer à d’autres distributions avec presque aucune modification.
Je veux d’abord dire que ce n’est pas la seule façon de mettre en place un tel système. Il existe de nombreuses façons d’atteindre cet objectif, mais c’est la méthode que je choisis. Je ne donne aucune garantie que cela fonctionnera pour vous !
1 Installation
DenyHosts est écrit en Python, nous devons donc d’abord installer Python et également les fichiers de développement Python :
apt-get install python python2.3-dev python2.3
Ensuite, nous téléchargeons et installons DenyHosts comme ceci :
cd /tmp
wget http://mesh.dl.sourceforge.net/sourceforge/denyhosts/DenyHosts-2.0.tar.gz
tar xvfz DenyHosts-2.0.tar.gz
cd DenyHosts-2.0
python setup.py install
Cela installe DenyHosts dans /usr/share/denyhosts.
2 Configuration
Maintenant, nous devons créer le fichier de configuration de DenyHosts /usr/share/denyhosts/denyhosts.cfg. Nous pouvons utiliser le fichier de configuration d’exemple /usr/share/denyhosts/denyhosts.cfg-dist pour cela :
cd /usr/share/denyhosts
cp denyhosts.cfg-dist denyhosts.cfg
Ensuite, nous devons éditer denyhosts.cfg avec notre éditeur préféré comme vi, par exemple. Le mien ressemble à ceci :
| ############ CES PARAMÈTRES SONT REQUIS ############ ######################################################################## # # SECURE_LOG : le fichier journal qui contient les informations de journalisation sshd # si vous n'êtes pas sûr, grep "sshd:" /var/log/* # # Le fichier à traiter peut être remplacé par l'argument de ligne de commande --file # # Redhat ou Fedora Core : #SECURE_LOG = /var/log/secure # # Mandrake, FreeBSD ou OpenBSD : SECURE_LOG = /var/log/auth.log # # SuSE : #SECURE_LOG = /var/log/messages # ######################################################################## ######################################################################## # HOSTS_DENY : le fichier qui contient les informations d'accès des hôtes restreints # # La plupart des systèmes d'exploitation : HOSTS_DENY = /etc/hosts.deny # # Certains BSD (FreeBSD) Unixes : #HOSTS_DENY = /etc/hosts.allow # # Une autre possibilité (voir aussi l'option suivante) : #HOSTS_DENY = /etc/hosts.evil ####################################################################### ######################################################################## # PURGE_DENY : supprime les entrées HOSTS_DENY qui sont plus anciennes que ce temps # lorsque DenyHosts est invoqué avec le drapeau --purge # # le format est : i[dhwmy] # Où 'i' est un entier (ex. 7) # 'm' = minutes # 'h' = heures # 'd' = jours # 'w' = semaines # 'y' = années # # jamais purger : PURGE_DENY = # # purger les entrées plus anciennes qu'une semaine #PURGE_DENY = 1w # # purger les entrées plus anciennes que 5 jours #PURGE_DENY = 5d ####################################################################### ####################################################################### # BLOCK_SERVICE : le nom du service qui doit être bloqué dans HOSTS_DENY # # man 5 hosts_access pour plus de détails # # ex. sshd : 127.0.0.1 # bloquera les connexions sshd depuis 127.0.0.1 # # Pour bloquer tous les services pour l'hôte en faute : #BLOCK_SERVICE = ALL # Pour bloquer uniquement sshd : BLOCK_SERVICE = sshd # Pour ne seulement enregistrer l'hôte en faute et rien d'autre (si vous utilisez # un fichier auxiliaire pour lister les hôtes). Référez-vous à : # http://denyhosts.sourceforge.net/faq.html#aux #BLOCK_SERVICE = # ####################################################################### ####################################################################### # # DENY_THRESHOLD_INVALID : bloque chaque hôte après que le nombre de tentatives de connexion échouées # a dépassé cette valeur. Cette valeur s'applique aux tentatives de connexion d'utilisateur invalides # (ex. comptes d'utilisateur inexistants) # DENY_THRESHOLD_INVALID = 5 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_VALID : bloque chaque hôte après que le nombre de tentatives de connexion échouées # a dépassé cette valeur. Cette valeur s'applique aux tentatives de connexion d'utilisateur valides # (ex. comptes d'utilisateur qui existent dans /etc/passwd) sauf # pour l'utilisateur "root" # DENY_THRESHOLD_VALID = 10 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_ROOT : bloque chaque hôte après que le nombre de tentatives de connexion échouées # a dépassé cette valeur. Cette valeur s'applique uniquement aux # tentatives de connexion de l'utilisateur "root". # DENY_THRESHOLD_ROOT = 5 # ####################################################################### ####################################################################### # # WORK_DIR : le chemin que DenyHosts utilisera pour écrire des données # (il sera créé s'il n'existe pas déjà). # # Remarque : il est recommandé d'utiliser un chemin absolu # pour cette valeur (ex. /home/foo/denyhosts/data) # WORK_DIR = /usr/share/denyhosts/data # ####################################################################### ####################################################################### # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=OUI|NON # Si défini sur OUI, si une tentative de connexion suspecte provient d'un hôte autorisé # alors elle est considérée comme suspecte. Si c'est NON, alors les connexions suspectes # provenant d'hôtes autorisés ne seront pas signalées. Toutes les connexions suspectes provenant # d'adresses IP qui ne sont pas dans les hôtes autorisés seront toujours signalées. # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=OUI ###################################################################### ###################################################################### # # HOSTNAME_LOOKUP # # HOSTNAME_LOOKUP=OUI|NON # Si défini sur OUI, pour chaque adresse IP signalée par Denyhosts, # le nom d'hôte correspondant sera recherché et signalé également # (si disponible). # HOSTNAME_LOOKUP=OUI # ###################################################################### ###################################################################### # # LOCK_FILE # # LOCK_FILE=/path/denyhosts # Si ce fichier existe lorsque DenyHosts est exécuté, alors DenyHosts sortira # immédiatement. Sinon, ce fichier sera créé lors de l'invocation # et supprimé à la sortie. Cela garantit qu'une seule instance est # en cours d'exécution à la fois. # # Redhat/Fedora : #LOCK_FILE = /var/lock/subsys/denyhosts # # Debian LOCK_FILE = /var/run/denyhosts.pid # # Divers #LOCK_FILE = /tmp/denyhosts.lock # ###################################################################### ############ CES PARAMÈTRES SONT OPTIONNELS ############ ####################################################################### # # ADMIN_EMAIL : si vous souhaitez recevoir des e-mails concernant les nouveaux # hôtes restreints et les connexions suspectes, définissez cette adresse pour # correspondre à votre adresse e-mail. Si vous ne souhaitez pas recevoir ces rapports, # laissez ce champ vide (ou exécutez avec l'option --noemail) # ADMIN_EMAIL = # ####################################################################### ####################################################################### # SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts |
Assurez-vous de définir SECURE_LOG et LOCK_FILE sur les valeurs correctes pour votre distribution ! Pour Debian, celles-ci sont :
SECURE_LOG = /var/log/auth.log
LOCK_FILE = /var/run/denyhosts.pid
Comme nous voulons exécuter DenyHosts en tant que démon, nous avons besoin du script de contrôle du démon /usr/share/denyhosts/daemon-control. Encore une fois, nous pouvons utiliser le script d’exemple /usr/share/denyhosts/daemon-control-dist pour créer le fichier nécessaire :
cp daemon-control-dist daemon-control
Éditez /usr/share/denyhosts/daemon-control et assurez-vous de définir les valeurs correctes pour DENYHOSTS_BIN, DENYHOSTS_LOCK et DENYHOSTS_CFG. Pour Debian, celles-ci sont :
DENYHOSTS_BIN = “/usr/bin/denyhosts.py”
DENYHOSTS_LOCK = “/var/run/denyhosts.pid”
DENYHOSTS_CFG = “/usr/share/denyhosts/denyhosts.cfg”
Ainsi, mon /usr/share/denyhosts/daemon-control ressemble à ceci :
| #!/usr/bin/env python # denyhosts Démarrer/arrêter le démon DenyHosts # # chkconfig: 2345 98 02 # description: Active/Désactive le # démon DenyHosts pour bloquer les tentatives ssh # ############################################### ############################################### #### Modifiez ceci pour convenir à votre configuration #### ############################################### DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg" ############################################### #### Ne pas modifier ci-dessous #### ############################################### import os, sys, signal, time STATE_NOT_RUNNING = -1 STATE_LOCK_EXISTS = -2 def usage(): print "Usage: %s {start [args...] | stop | restart [args...] | status | debug | condrestart [args...] }" % sys.argv[0] print print "Pour une liste des 'args' valides, référez-vous à:" print "$ denyhosts.py --help" print sys.exit(0) def getpid(): try: fp = open(DENYHOSTS_LOCK, "r") pid = int(fp.readline().rstrip()) fp.close() except Exception, e: return STATE_NOT_RUNNING if os.access(os.path.join("/proc", str(pid)), os.F_OK): return pid else: return STATE_LOCK_EXISTS def start(*args): cmd = "%s --daemon " % DENYHOSTS_BIN if args: cmd += ' '.join(args) print "démarrage de DenyHosts : ", cmd os.system(cmd) def stop(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGTERM) print "envoi de SIGTERM à DenyHosts" else: print "DenyHosts n'est pas en cours d'exécution" def debug(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGUSR1) print "envoi de SIGUSR1 à DenyHosts" else: print "DenyHosts n'est pas en cours d'exécution" def status(): pid = getpid() if pid == STATE_LOCK_EXISTS: print "%s existe mais DenyHosts n'est pas en cours d'exécution" % DENYHOSTS_LOCK elif pid == STATE_NOT_RUNNING: print "Denyhosts n'est pas en cours d'exécution" else: print "DenyHosts est en cours d'exécution avec pid = %d" % pid def condrestart(*args): pid = getpid() if pid >= 0: restart(*args) def restart(*args): stop() time.sleep(1) start(*args) if __name__ == '__main__': cases = {'start': start, 'stop': stop, 'debug': debug, 'status': status, 'condrestart': condrestart, 'restart': restart} try: args = sys.argv[2:] except: args = [] try: option = sys.argv[1] if option in ('start', 'restart', 'condrestart'): if '--config' not in args and '-c' not in args: args.append("--config=%s" % DENYHOSTS_CFG) cmd = cases[option] apply(cmd, args) except: usage() |
Ensuite, nous devons rendre ce fichier exécutable :
chown root daemon-control
chmod 700 daemon-control
Ensuite, nous créons les liens de démarrage du système pour DenyHosts afin qu’il soit démarré automatiquement lorsque le système est démarré :
cd /etc/init.d
ln -s /usr/share/denyhosts/daemon-control denyhosts
update-rc.d denyhosts defaults
Enfin, nous démarrons DenyHosts :
/etc/init.d/denyhosts start
DenyHosts journalise dans /var/log/denyhosts, si vous êtes intéressé par les journaux. Le démon SSH journalise dans /var/log/auth.log sur Debian. Vous pouvez surveiller les deux journaux et essayer de vous connecter avec un utilisateur invalide ou avec un utilisateur valide et un mot de passe incorrect, etc. via SSH et voir ce qui se passe. Après avoir franchi le seuil des tentatives de connexion incorrectes, l’adresse IP depuis laquelle vous avez essayé de vous connecter devrait être répertoriée dans /etc/hosts.deny, comme ceci :
| # /etc/hosts.deny : liste des hôtes qui ne sont _pas_ autorisés à accéder au système. # Voir les pages de manuel hosts_access(5), hosts_options(5) # et /usr/doc/netbase/portmapper.txt.gz # # Exemple : ALL : some.host.name, .some.domain # ALL EXCEPT in.fingerd : other.host.name, .other.domain # # Si vous allez protéger le portmapper, utilisez le nom "portmap" pour le # nom du démon. N'oubliez pas que vous ne pouvez utiliser que le mot-clé "ALL" et les adresses IP # (PAS les noms d'hôtes ou de domaine) pour le portmapper. Voir portmap(8) # et /usr/doc/portmap/portmapper.txt.gz pour plus d'informations. # # Le caractère générique PARANOID correspond à tout hôte dont le nom ne correspond pas à son # adresse. # Vous souhaiterez peut-être activer cela pour garantir que tous les programmes qui ne # valident pas les noms d'hôtes recherchés laissent toujours des journaux compréhensibles. Dans les versions passées # de Debian, cela a été le défaut. # ALL : PARANOID sshd : 192.168.0.203 |
Cela signifie que le système avec l’adresse IP 192.168.0.203 ne peut plus se connecter via SSH.
Vous pouvez spécifier si/quand les adresses IP sont à nouveau supprimées de /etc/hosts.deny - jetez un œil à la variable PURGE_DENY dans /usr/share/denyhosts/denyhosts.cfg. Vous devez démarrer DenyHosts avec l’option –purge pour rendre la variable PURGE_DENY effective, comme ceci :
/etc/init.d/denyhosts start –purge
Cependant, vous pouvez également supprimer manuellement des adresses IP de là, et dès qu’elles ont été supprimées, ces adresses IP peuvent essayer de se connecter à nouveau via SSH.
Liens
- DenyHosts : http://denyhosts.sourceforge.net
Recevez de nouveaux articles dans votre boîte de réception.
Aucun spam. Désabonnez-vous à tout moment.