Sicurezza SSH · 14 min read · Jan 10, 2026
Prevenire gli attacchi di dizionario SSH con DenyHosts
Prevenire gli attacchi di dizionario SSH con DenyHosts
Versione 1.0
Autore: Falko Timme
Ultima modifica: 02/07/2006
In questo HowTo mostrerò come installare e configurare DenyHosts. DenyHosts è uno strumento che osserva i tentativi di accesso a SSH e, se trova tentativi di accesso falliti ripetutamente dallo stesso indirizzo IP, DenyHosts blocca ulteriori tentativi di accesso da quell’indirizzo IP inserendolo in /etc/hosts.deny. DenyHosts può essere eseguito da cron o come demone. In questo tutorial eseguirò DenyHosts come demone.
Dal sito web di DenyHosts:
“DenyHosts è uno script destinato ad essere eseguito dagli amministratori di sistema Linux per aiutare a contrastare gli attacchi ai server ssh.
Se hai mai guardato il tuo log ssh (/var/log/secure su Redhat, /var/log/auth.log su Mandrake, ecc…) potresti essere allarmato nel vedere quanti hacker hanno tentato di accedere al tuo server. Speriamo che nessuno di loro abbia avuto successo (ma d’altra parte, come potresti saperlo?). Non sarebbe meglio prevenire automaticamente che quell’attaccante continui a entrare nel tuo sistema?
DenyHosts cerca di affrontare quanto sopra… “
Questo tutorial è basato su un sistema Debian Sarge, tuttavia, dovrebbe applicarsi ad altre distribuzioni con quasi nessuna modifica.
Voglio dire prima che questo non è l’unico modo per impostare un sistema del genere. Ci sono molti modi per raggiungere questo obiettivo, ma questo è il modo che scelgo. Non fornisco alcuna garanzia che questo funzionerà per te!
1 Installazione
DenyHosts è scritto in Python, quindi dobbiamo prima installare Python e anche i file di sviluppo di Python:
apt-get install python python2.3-dev python2.3
Poi scarichiamo e installiamo DenyHosts in questo modo:
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
Questo installa DenyHosts in /usr/share/denyhosts.
2 Configurazione
Ora dobbiamo creare il file di configurazione di DenyHosts /usr/share/denyhosts/denyhosts.cfg. Possiamo usare il file di configurazione di esempio /usr/share/denyhosts/denyhosts.cfg-dist per questo:
cd /usr/share/denyhosts
cp denyhosts.cfg-dist denyhosts.cfg
Poi dobbiamo modificare denyhosts.cfg con il nostro editor preferito come vi, per esempio. Il mio appare così:
| ############ QUESTE IMPOSTAZIONI SONO OBBLIGATORIE ############ ######################################################################## # # SECURE_LOG: il file di log che contiene le informazioni di logging di sshd # se non sei sicuro, grep "sshd:" /var/log/* # # Il file da elaborare può essere sovrascritto con l'argomento della riga di comando --file # # Redhat o Fedora Core: #SECURE_LOG = /var/log/secure # # Mandrake, FreeBSD o OpenBSD: SECURE_LOG = /var/log/auth.log # # SuSE: #SECURE_LOG = /var/log/messages # ######################################################################## ######################################################################## # HOSTS_DENY: il file che contiene le informazioni di accesso degli host ristretti # # La maggior parte dei sistemi operativi: HOSTS_DENY = /etc/hosts.deny # # Alcuni BSD (FreeBSD) Unixes: #HOSTS_DENY = /etc/hosts.allow # # Un'altra possibilità (vedi anche l'opzione successiva): #HOSTS_DENY = /etc/hosts.evil ####################################################################### ######################################################################## # PURGE_DENY: rimuove le voci HOSTS_DENY che sono più vecchie di questo tempo # quando DenyHosts viene invocato con il flag --purge # # il formato è: i[dhwmy] # Dove 'i' è un intero (es. 7) # 'm' = minuti # 'h' = ore # 'd' = giorni # 'w' = settimane # 'y' = anni # # mai purgare: PURGE_DENY = # # purgare voci più vecchie di 1 settimana #PURGE_DENY = 1w # # purgare voci più vecchie di 5 giorni #PURGE_DENY = 5d ####################################################################### ####################################################################### # BLOCK_SERVICE: il nome del servizio che dovrebbe essere bloccato in HOSTS_DENY # # man 5 hosts_access per dettagli # # es. sshd: 127.0.0.1 # bloccherà gli accessi sshd da 127.0.0.1 # # Per bloccare tutti i servizi per l'host colpevole: #BLOCK_SERVICE = ALL # Per bloccare solo sshd: BLOCK_SERVICE = sshd # Per registrare solo l'host colpevole e nient'altro (se si utilizza # un file ausiliario per elencare gli host). Riferirsi a: # http://denyhosts.sourceforge.net/faq.html#aux #BLOCK_SERVICE = # ####################################################################### ####################################################################### # # DENY_THRESHOLD_INVALID: blocca ogni host dopo che il numero di tentativi di accesso falliti # ha superato questo valore. Questo valore si applica ai tentativi di accesso # utente non validi (es. account utente inesistenti) # DENY_THRESHOLD_INVALID = 5 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_VALID: blocca ogni host dopo che il numero di # tentativi di accesso falliti ha superato questo valore. Questo valore si applica a # tentativi di accesso utente validi (es. account utente che esistono in /etc/passwd) tranne # per l'utente "root" # DENY_THRESHOLD_VALID = 10 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_ROOT: blocca ogni host dopo che il numero di tentativi di accesso falliti # ha superato questo valore. Questo valore si applica a # tentativi di accesso dell'utente "root" solo. # DENY_THRESHOLD_ROOT = 5 # ####################################################################### ####################################################################### # # WORK_DIR: il percorso che DenyHosts utilizzerà per scrivere i dati # (verrà creato se non esiste già). # # Nota: si consiglia di utilizzare un percorso assoluto # per questo valore (es. /home/foo/denyhosts/data) # WORK_DIR = /usr/share/denyhosts/data # ####################################################################### ####################################################################### # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES|NO # Se impostato su YES, se un tentativo di accesso sospetto proviene da un host consentito # allora è considerato sospetto. Se questo è NO, allora i logins sospetti # da host consentiti non verranno segnalati. Tutti i logins sospetti da # indirizzi IP che non sono negli host consentiti verranno sempre segnalati. # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES ###################################################################### ###################################################################### # # HOSTNAME_LOOKUP # # HOSTNAME_LOOKUP=YES|NO # Se impostato su YES, per ogni indirizzo IP segnalato da Denyhosts, # il corrispondente nome host verrà cercato e segnalato anche # (se disponibile). # HOSTNAME_LOOKUP=YES # ###################################################################### ###################################################################### # # LOCK_FILE # # LOCK_FILE=/path/denyhosts # Se questo file esiste quando DenyHosts viene eseguito, allora DenyHosts uscirà # immediatamente. Altrimenti, questo file verrà creato all'invocazione # e cancellato all'uscita. Questo garantisce che solo un'istanza sia # in esecuzione alla volta. # # Redhat/Fedora: #LOCK_FILE = /var/lock/subsys/denyhosts # # Debian LOCK_FILE = /var/run/denyhosts.pid # # Varie #LOCK_FILE = /tmp/denyhosts.lock # ###################################################################### ############ QUESTE IMPOSTAZIONI SONO OPZIONALI ############ ####################################################################### # # ADMIN_EMAIL: se desideri ricevere email riguardo ai nuovi # host ristretti e accessi sospetti, imposta questo indirizzo per # corrispondere al tuo indirizzo email. Se non desideri ricevere questi rapporti # lascia questo campo vuoto (o esegui con l'opzione --noemail) # ADMIN_EMAIL = # ####################################################################### ####################################################################### # SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts |
Assicurati di impostare SECURE_LOG e LOCK_FILE sui valori corretti per la tua distribuzione! Per Debian, questi sono:
SECURE_LOG = /var/log/auth.log
LOCK_FILE = /var/run/denyhosts.pid
Poiché vogliamo eseguire DenyHosts come demone, abbiamo bisogno dello script di controllo del demone /usr/share/denyhosts/daemon-control. Ancora una volta, possiamo usare lo script di esempio /usr/share/denyhosts/daemon-control-dist per creare il file necessario:
cp daemon-control-dist daemon-control
Modifica /usr/share/denyhosts/daemon-control e assicurati di impostare i valori corretti per DENYHOSTS_BIN, DENYHOSTS_LOCK e DENYHOSTS_CFG. Per Debian, questi sono:
DENYHOSTS_BIN = “/usr/bin/denyhosts.py”
DENYHOSTS_LOCK = “/var/run/denyhosts.pid”
DENYHOSTS_CFG = “/usr/share/denyhosts/denyhosts.cfg”
Quindi il mio /usr/share/denyhosts/daemon-control appare così:
| #!/usr/bin/env python # denyhosts Avvia/ferma il demone DenyHosts # # chkconfig: 2345 98 02 # descrizione: Attiva/Disattiva il # demone DenyHosts per bloccare i tentativi ssh # ############################################### ############################################### #### Modifica questi per adattarli alla tua configurazione #### ############################################### DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg" ############################################### #### Non modificare sotto #### ############################################### import os, sys, signal, time STATE_NOT_RUNNING = -1 STATE_LOCK_EXISTS = -2 def usage(): print "Uso: %s {start [args...] | stop | restart [args...] | status | debug | condrestart [args...] }" % sys.argv[0] print print "Per un elenco di 'args' validi fare riferimento a:" 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 "avviando DenyHosts: ", cmd os.system(cmd) def stop(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGTERM) print "inviato DenyHosts SIGTERM" else: print "DenyHosts non è in esecuzione" def debug(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGUSR1) print "inviato DenyHosts SIGUSR1" else: print "DenyHosts non è in esecuzione" def status(): pid = getpid() if pid == STATE_LOCK_EXISTS: print "%s esiste ma DenyHosts non è in esecuzione" % DENYHOSTS_LOCK elif pid == STATE_NOT_RUNNING: print "Denyhosts non è in esecuzione" else: print "DenyHosts è in esecuzione con 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() |
Successivamente, dobbiamo rendere quel file eseguibile:
chown root daemon-control
chmod 700 daemon-control
Dopo, creiamo i collegamenti di avvio del sistema per DenyHosts in modo che venga avviato automaticamente all’avvio del sistema:
cd /etc/init.d
ln -s /usr/share/denyhosts/daemon-control denyhosts
update-rc.d denyhosts defaults
Infine, avviamo DenyHosts:
/etc/init.d/denyhosts start
DenyHosts registra in /var/log/denyhosts, se sei interessato ai log. Il demone SSH registra in /var/log/auth.log su Debian. Puoi guardare entrambi i log e provare a effettuare il login con un utente non valido o con un utente valido e una password errata, ecc. tramite SSH e vedere cosa succede. Dopo aver superato la soglia dei tentativi di accesso errati, l’indirizzo IP da cui hai provato a connetterti dovrebbe essere elencato in /etc/hosts.deny, in questo modo:
| # /etc/hosts.deny: elenco degli host che NON sono autorizzati ad accedere al sistema. # Vedi le pagine manuali hosts_access(5), hosts_options(5) # e /usr/doc/netbase/portmapper.txt.gz # # Esempio: ALL: some.host.name, .some.domain # TUTTI ECCETTO in.fingerd: other.host.name, .other.domain # # Se intendi proteggere il portmapper usa il nome "portmap" per il # nome del demone. Ricorda che puoi usare solo la parola chiave "ALL" e gli indirizzi IP # (NON nomi host o nomi di dominio) per il portmapper. Vedi portmap(8) # e /usr/doc/portmap/portmapper.txt.gz per ulteriori informazioni. # # Il carattere jolly PARANOID corrisponde a qualsiasi host il cui nome non corrisponde al suo # indirizzo. # Potresti voler abilitare questo per garantire che eventuali programmi che non # convalidano i nomi host cercati lascino comunque log comprensibili. Nelle versioni passate # di Debian questo è stato il predefinito. # TUTTI: PARANOID sshd: 192.168.0.203 |
Ciò significa che il sistema con l’indirizzo IP 192.168.0.203 non può più connettersi utilizzando SSH.
Puoi specificare se/quando gli indirizzi IP vengono rimossi nuovamente da /etc/hosts.deny - dai un’occhiata alla variabile PURGE_DENY in /usr/share/denyhosts/denyhosts.cfg. Devi avviare DenyHosts con l’opzione –purge per rendere efficace la variabile PURGE_DENY, in questo modo:
/etc/init.d/denyhosts start –purge
Tuttavia, puoi anche rimuovere manualmente gli indirizzi IP da lì, e non appena sono stati rimossi, questi indirizzi IP possono provare a effettuare il login nuovamente tramite SSH.
Link
- DenyHosts: http://denyhosts.sourceforge.net
Ricevi i nuovi post nella tua casella di posta.
Nessuno spam. Disiscriviti in qualsiasi momento.