Segurança SSH · 14 min read · Jan 10, 2026
Prevenindo Ataques de Dicionário SSH Com DenyHosts
Prevenindo Ataques de Dicionário SSH Com DenyHosts
Versão 1.0
Autor: Falko Timme
Última edição: 02/07/2006
Neste HowTo, vou mostrar como instalar e configurar o DenyHosts. DenyHosts é uma ferramenta que observa tentativas de login no SSH e, se encontrar tentativas de login falhadas repetidamente do mesmo endereço IP, o DenyHosts bloqueia novas tentativas de login desse endereço IP colocando-o em /etc/hosts.deny. O DenyHosts pode ser executado pelo cron ou como um daemon. Neste tutorial, vou executar o DenyHosts como um daemon.
Do site do DenyHosts:
“DenyHosts é um script destinado a ser executado por administradores de sistema Linux para ajudar a frustrar ataques ao servidor ssh.
Se você já olhou para o seu log ssh (/var/log/secure no Redhat, /var/log/auth.log no Mandrake, etc…) pode ficar alarmado ao ver quantos hackers tentaram acessar seu servidor. Esperançosamente, nenhum deles teve sucesso (mas, novamente, como você saberia?). Não seria melhor prevenir automaticamente que esse atacante continuasse a entrar em seu sistema?
DenyHosts tenta abordar o acima…”
Este tutorial é baseado em um sistema Debian Sarge, no entanto, deve se aplicar a outras distribuições com quase nenhuma modificação.
Quero dizer primeiro que esta não é a única maneira de configurar um sistema assim. Existem muitas maneiras de alcançar esse objetivo, mas este é o caminho que eu sigo. Não dou nenhuma garantia de que isso funcionará para você!
1 Instalação
O DenyHosts é escrito em Python, portanto, devemos instalar o Python e também os arquivos de desenvolvimento do Python primeiro:
apt-get install python python2.3-dev python2.3
Em seguida, baixamos e instalamos o DenyHosts assim:
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
Isso instala o DenyHosts em /usr/share/denyhosts.
2 Configuração
Agora precisamos criar o arquivo de configuração do DenyHosts /usr/share/denyhosts/denyhosts.cfg. Podemos usar o arquivo de configuração de exemplo /usr/share/denyhosts/denyhosts.cfg-dist para isso:
cd /usr/share/denyhosts
cp denyhosts.cfg-dist denyhosts.cfg
Em seguida, devemos editar denyhosts.cfg com nosso editor favorito, como vi, por exemplo. O meu fica assim:
| ############ ESSAS CONFIGURAÇÕES SÃO OBRIGATÓRIAS ############ ######################################################################## # # SECURE_LOG: o arquivo de log que contém informações de log do sshd # se você não tiver certeza, grep "sshd:" /var/log/* # # O arquivo a ser processado pode ser substituído pelo argumento da linha de comando --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: o arquivo que contém informações de acesso restrito de hosts # # A maioria dos sistemas operacionais: HOSTS_DENY = /etc/hosts.deny # # Alguns BSD (FreeBSD) Unixes: #HOSTS_DENY = /etc/hosts.allow # # Outra possibilidade (veja também a próxima opção): #HOSTS_DENY = /etc/hosts.evil ####################################################################### ######################################################################## # PURGE_DENY: remove entradas do HOSTS_DENY que são mais antigas que este tempo # quando o DenyHosts é invocado com a flag --purge # # o formato é: i[dhwmy] # Onde 'i' é um inteiro (ex. 7) # 'm' = minutos # 'h' = horas # 'd' = dias # 'w' = semanas # 'y' = anos # # nunca purgar: PURGE_DENY = # # purgar entradas mais antigas que 1 semana #PURGE_DENY = 1w # # purgar entradas mais antigas que 5 dias #PURGE_DENY = 5d ####################################################################### ####################################################################### # BLOCK_SERVICE: o nome do serviço que deve ser bloqueado no HOSTS_DENY # # man 5 hosts_access para detalhes # # ex. sshd: 127.0.0.1 # bloqueará logins sshd de 127.0.0.1 # # Para bloquear todos os serviços para o host ofensivo: #BLOCK_SERVICE = ALL # Para bloquear apenas sshd: BLOCK_SERVICE = sshd # Para apenas registrar o host ofensivo e nada mais (se usar # um arquivo auxiliar para listar os hosts). Consulte: # http://denyhosts.sourceforge.net/faq.html#aux #BLOCK_SERVICE = # ####################################################################### ####################################################################### # # DENY_THRESHOLD_INVALID: bloqueia cada host após o número de tentativas de login falhadas # ter excedido este valor. Este valor se aplica a tentativas de login de usuário inválido # (ex. contas de usuário inexistentes) # DENY_THRESHOLD_INVALID = 5 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_VALID: bloqueia cada host após o número de falhas de # tentativas de login ter excedido este valor. Este valor se aplica a tentativas de login válidas # (ex. contas de usuário que existem em /etc/passwd) exceto # para o usuário "root" # DENY_THRESHOLD_VALID = 10 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_ROOT: bloqueia cada host após o número de falhas de # tentativas de login ter excedido este valor. Este valor se aplica a # tentativas de login do usuário "root" apenas. # DENY_THRESHOLD_ROOT = 5 # ####################################################################### ####################################################################### # # WORK_DIR: o caminho que o DenyHosts usará para gravar dados # (ele será criado se ainda não existir). # # Nota: é recomendado que você use um caminho absoluto # para este valor (ex. /home/foo/denyhosts/data) # WORK_DIR = /usr/share/denyhosts/data # ####################################################################### ####################################################################### # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=SIM|NÃO # Se definido como SIM, se uma tentativa de login suspeita resultar de um host permitido # então é considerada suspeita. Se for NÃO, então logins suspeitos # de hosts permitidos não serão relatados. Todos os logins suspeitos de # endereços IP que não estão em hosts permitidos sempre serão relatados. # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=SIM ###################################################################### ###################################################################### # # HOSTNAME_LOOKUP # # HOSTNAME_LOOKUP=SIM|NÃO # Se definido como SIM, para cada endereço IP que é relatado pelo Denyhosts, # o nome do host correspondente será pesquisado e relatado também # (se disponível). # HOSTNAME_LOOKUP=SIM # ###################################################################### ###################################################################### # # LOCK_FILE # # LOCK_FILE=/path/denyhosts # Se este arquivo existir quando o DenyHosts for executado, então o DenyHosts sairá # imediatamente. Caso contrário, este arquivo será criado ao ser invocado # e excluído ao sair. Isso garante que apenas uma instância esteja # em execução por vez. # # Redhat/Fedora: #LOCK_FILE = /var/lock/subsys/denyhosts # # Debian LOCK_FILE = /var/run/denyhosts.pid # # Vários #LOCK_FILE = /tmp/denyhosts.lock # ###################################################################### ############ ESSAS CONFIGURAÇÕES SÃO OBRIGATÓRIAS ############ ####################################################################### # # ADMIN_EMAIL: se você gostaria de receber e-mails sobre novos # hosts restritos e logins suspeitos, defina este endereço para # corresponder ao seu endereço de e-mail. Se você não quiser receber esses relatórios # deixe este campo em branco (ou execute com a opção --noemail) # ADMIN_EMAIL = # ####################################################################### ####################################################################### # SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts |
Certifique-se de definir SECURE_LOG e LOCK_FILE para os valores corretos para sua distribuição! Para Debian, estes são:
SECURE_LOG = /var/log/auth.log
LOCK_FILE = /var/run/denyhosts.pid
Como queremos executar o DenyHosts como um daemon, precisamos do script de controle do daemon /usr/share/denyhosts/daemon-control. Novamente, podemos usar o script de exemplo /usr/share/denyhosts/daemon-control-dist para criar o arquivo necessário:
cp daemon-control-dist daemon-control
Edite /usr/share/denyhosts/daemon-control e certifique-se de definir os valores corretos para DENYHOSTS_BIN, DENYHOSTS_LOCK e DENYHOSTS_CFG. Para Debian, estes são:
DENYHOSTS_BIN = “/usr/bin/denyhosts.py”
DENYHOSTS_LOCK = “/var/run/denyhosts.pid”
DENYHOSTS_CFG = “/usr/share/denyhosts/denyhosts.cfg”
Então meu /usr/share/denyhosts/daemon-control fica assim:
| #!/usr/bin/env python # denyhosts Ativa/desativa o daemon DenyHosts # # chkconfig: 2345 98 02 # descrição: Ativa/Desativa o # daemon DenyHosts para bloquear tentativas de ssh # ############################################### ############################################### #### Edite isso para se adequar à sua configuração #### ############################################### DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg" ############################################### #### Não edite abaixo #### ############################################### 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 "Para uma lista de 'args' válidos, consulte:" 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 "iniciando DenyHosts: ", cmd os.system(cmd) def stop(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGTERM) print "enviado SIGTERM para DenyHosts" else: print "DenyHosts não está em execução" def debug(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGUSR1) print "enviado SIGUSR1 para DenyHosts" else: print "DenyHosts não está em execução" def status(): pid = getpid() if pid == STATE_LOCK_EXISTS: print "%s existe, mas DenyHosts não está em execução" % DENYHOSTS_LOCK elif pid == STATE_NOT_RUNNING: print "Denyhosts não está em execução" else: print "DenyHosts está em execução com 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() |
Em seguida, precisamos tornar esse arquivo executável:
chown root daemon-control
chmod 700 daemon-control
Depois, criamos os links de inicialização do sistema para o DenyHosts para que ele seja iniciado automaticamente quando o sistema for inicializado:
cd /etc/init.d
ln -s /usr/share/denyhosts/daemon-control denyhosts
update-rc.d denyhosts defaults
Finalmente, iniciamos o DenyHosts:
/etc/init.d/denyhosts start
O DenyHosts registra em /var/log/denyhosts, se você estiver interessado nos logs. O daemon SSH registra em /var/log/auth.log no Debian. Você pode observar ambos os logs e tentar fazer login com um usuário inválido ou com um usuário válido e senha incorreta, etc. via SSH e ver o que acontece. Depois de ultrapassar o limite de tentativas de login incorretas, o endereço IP do qual você tentou se conectar deve ser listado em /etc/hosts.deny, assim:
| # /etc/hosts.deny: lista de hosts que não têm permissão para acessar o sistema. # Veja as páginas man hosts_access(5), hosts_options(5) # e /usr/doc/netbase/portmapper.txt.gz # # Exemplo: ALL: some.host.name, .some.domain # ALL EXCEPT in.fingerd: other.host.name, .other.domain # # Se você vai proteger o portmapper, use o nome "portmap" para o # nome do daemon. Lembre-se de que você só pode usar a palavra-chave "ALL" e endereços IP # (NÃO nomes de host ou de domínio) para o portmapper. Veja portmap(8) # e /usr/doc/portmap/portmapper.txt.gz para mais informações. # # O curinga PARANOID corresponde a qualquer host cujo nome não corresponda ao seu # endereço. # Você pode querer habilitar isso para garantir que qualquer programa que não # valide nomes de hosts pesquisados ainda deixe logs compreensíveis. Nas versões anteriores # do Debian, isso foi o padrão. # ALL: PARANOID sshd: 192.168.0.203 |
Isso significa que o sistema com o endereço IP 192.168.0.203 não pode mais se conectar usando SSH.
Você pode especificar se/quando os endereços IP são removidos novamente de /etc/hosts.deny - dê uma olhada na variável PURGE_DENY em /usr/share/denyhosts/denyhosts.cfg. Você deve iniciar o DenyHosts com a opção –purge para que a variável PURGE_DENY tenha efeito, assim:
/etc/init.d/denyhosts start –purge
No entanto, você também pode remover endereços IP manualmente de lá, e assim que eles forem removidos, esses endereços IP podem tentar fazer login novamente via SSH.
Links
- DenyHosts: http://denyhosts.sourceforge.net
Receba novas postagens na sua caixa de entrada
Sem spam. Cancele a assinatura a qualquer momento.