SSH безопасность · 14 min read · Jan 10, 2026
Предотвращение атак словарем SSH с помощью DenyHosts
Предотвращение атак словарем SSH с помощью DenyHosts
Version 1.0
Author: Falko Timme
Last edited: 02/07/2006
В этом руководстве я покажу, как установить и настроить DenyHosts. DenyHosts — это инструмент, который отслеживает попытки входа в SSH, и если он обнаруживает неудачные попытки входа снова и снова с одного и того же IP-адреса, DenyHosts блокирует дальнейшие попытки входа с этого IP-адреса, добавляя его в /etc/hosts.deny. DenyHosts может работать по расписанию cron или как демон. В этом учебнике я буду запускать DenyHosts как демон.
С сайта DenyHosts:
“DenyHosts — это скрипт, предназначенный для запуска системными администраторами Linux, чтобы помочь предотвратить атаки на ssh-сервер.
Если вы когда-либо смотрели свой ssh-журнал (/var/log/secure на Redhat, /var/log/auth.log на Mandrake и т. д.), вы могли бы быть встревожены тем, сколько хакеров пытались получить доступ к вашему серверу. Надеюсь, ни один из них не был успешен (но как вы можете это знать?). Разве не было бы лучше автоматически предотвратить дальнейший доступ этого злоумышленника к вашей системе?
DenyHosts пытается решить вышеизложенное…”
Это руководство основано на системе Debian Sarge, однако оно должно применяться и к другим дистрибутивам с почти без изменений.
Я хочу сказать сначала, что это не единственный способ настройки такой системы. Существует множество способов достижения этой цели, но это тот путь, который я выбираю. Я не даю никаких гарантий, что это сработает для вас!
1 Установка
DenyHosts написан на Python, поэтому сначала мы должны установить Python и также файлы разработки Python:
apt-get install python python2.3-dev python2.3
Затем мы загружаем и устанавливаем DenyHosts следующим образом:
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
Это устанавливает DenyHosts в /usr/share/denyhosts.
2 Настройка
Теперь нам нужно создать файл конфигурации DenyHosts /usr/share/denyhosts/denyhosts.cfg. Мы можем использовать файл образца конфигурации /usr/share/denyhosts/denyhosts.cfg-dist для этого:
cd /usr/share/denyhosts
cp denyhosts.cfg-dist denyhosts.cfg
Затем мы должны отредактировать denyhosts.cfg с помощью нашего любимого редактора, например, vi. Мой выглядит так:
| ############ THESE SETTINGS ARE REQUIRED ############ ######################################################################## # # SECURE_LOG: the log file that contains sshd logging info # if you are not sure, grep "sshd:" /var/log/* # # The file to process can be overridden with the --file command line # argument # # Redhat or Fedora Core: #SECURE_LOG = /var/log/secure # # Mandrake, FreeBSD or OpenBSD: SECURE_LOG = /var/log/auth.log # # SuSE: #SECURE_LOG = /var/log/messages # ######################################################################## ######################################################################## # HOSTS_DENY: the file which contains restricted host access information # # Most operating systems: HOSTS_DENY = /etc/hosts.deny # # Some BSD (FreeBSD) Unixes: #HOSTS_DENY = /etc/hosts.allow # # Another possibility (also see the next option): #HOSTS_DENY = /etc/hosts.evil ####################################################################### ######################################################################## # PURGE_DENY: removed HOSTS_DENY entries that are older than this time # when DenyHosts is invoked with the --purge flag # # format is: i[dhwmy] # Where 'i' is an integer (eg. 7) # 'm' = minutes # 'h' = hours # 'd' = days # 'w' = weeks # 'y' = years # # never purge: PURGE_DENY = # # purge entries older than 1 week #PURGE_DENY = 1w # # purge entries older than 5 days #PURGE_DENY = 5d ####################################################################### ####################################################################### # BLOCK_SERVICE: the service name that should be blocked in HOSTS_DENY # # man 5 hosts_access for details # # eg. sshd: 127.0.0.1 # will block sshd logins from 127.0.0.1 # # To block all services for the offending host: #BLOCK_SERVICE = ALL # To block only sshd: BLOCK_SERVICE = sshd # To only record the offending host and nothing else (if using # an auxilary file to list the hosts). Refer to: # http://denyhosts.sourceforge.net/faq.html#aux #BLOCK_SERVICE = # ####################################################################### ####################################################################### # # DENY_THRESHOLD_INVALID: block each host after the number of failed login # attempts has exceeded this value. This value applies to invalid # user login attempts (eg. non-existent user accounts) # DENY_THRESHOLD_INVALID = 5 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_VALID: block each host after the number of failed # login attempts has exceeded this value. This value applies to valid # user login attempts (eg. user accounts that exist in /etc/passwd) except # for the "root" user # DENY_THRESHOLD_VALID = 10 # ####################################################################### ####################################################################### # # DENY_THRESHOLD_ROOT: block each host after the number of failed # login attempts has exceeded this value. This value applies to # "root" user login attempts only. # DENY_THRESHOLD_ROOT = 5 # ####################################################################### ####################################################################### # # WORK_DIR: the path that DenyHosts will use for writing data to # (it will be created if it does not already exist). # # Note: it is recommended that you use an absolute pathname # for this value (eg. /home/foo/denyhosts/data) # WORK_DIR = /usr/share/denyhosts/data # ####################################################################### ####################################################################### # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS # # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES|NO # If set to YES, if a suspicious login attempt results from an allowed-host # then it is considered suspicious. If this is NO, then suspicious logins # from allowed-hosts will not be reported. All suspicious logins from # ip addresses that are not in allowed-hosts will always be reported. # SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES ###################################################################### ###################################################################### # # HOSTNAME_LOOKUP # # HOSTNAME_LOOKUP=YES|NO # If set to YES, for each IP address that is reported by Denyhosts, # the corresponding hostname will be looked up and reported as well # (if available). # HOSTNAME_LOOKUP=YES # ###################################################################### ###################################################################### # # LOCK_FILE # # LOCK_FILE=/path/denyhosts # If this file exists when DenyHosts is run, then DenyHosts will exit # immediately. Otherwise, this file will be created upon invocation # and deleted upon exit. This ensures that only one instance is # running at a time. # # Redhat/Fedora: #LOCK_FILE = /var/lock/subsys/denyhosts # # Debian LOCK_FILE = /var/run/denyhosts.pid # # Misc #LOCK_FILE = /tmp/denyhosts.lock # ###################################################################### ############ THESE SETTINGS ARE OPTIONAL ############ ####################################################################### # # ADMIN_EMAIL: if you would like to receive emails regarding newly # restricted hosts and suspicious logins, set this address to # match your email address. If you do not want to receive these reports # leave this field blank (or run with the --noemail option) # ADMIN_EMAIL = # ####################################################################### ####################################################################### # SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts |
Убедитесь, что вы установили SECURE_LOG и LOCK_FILE на правильные значения для вашего дистрибутива! Для Debian это:
SECURE_LOG = /var/log/auth.log
LOCK_FILE = /var/run/denyhosts.pid
Поскольку мы хотим запустить DenyHosts как демон, нам нужен скрипт управления демоном /usr/share/denyhosts/daemon-control. Снова мы можем использовать образец скрипта /usr/share/denyhosts/daemon-control-dist для создания необходимого файла:
cp daemon-control-dist daemon-control
Отредактируйте /usr/share/denyhosts/daemon-control и убедитесь, что вы установили правильные значения для DENYHOSTS_BIN, DENYHOSTS_LOCK и DENYHOSTS_CFG. Для Debian это:
DENYHOSTS_BIN = “/usr/bin/denyhosts.py”
DENYHOSTS_LOCK = “/var/run/denyhosts.pid”
DENYHOSTS_CFG = “/usr/share/denyhosts/denyhosts.cfg”
Итак, мой /usr/share/denyhosts/daemon-control файл выглядит так:
| #!/usr/bin/env python # denyhosts Bring up/down the DenyHosts daemon # # chkconfig: 2345 98 02 # description: Activates/Deactivates the # DenyHosts daemon to block ssh attempts # ############################################### ############################################### #### Edit these to suit your configuration #### ############################################### DENYHOSTS_BIN = "/usr/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid" DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg" ############################################### #### Do not edit below #### ############################################### 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 "For a list of valid 'args' refer to:" 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 "starting DenyHosts: ", cmd os.system(cmd) def stop(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGTERM) print "sent DenyHosts SIGTERM" else: print "DenyHosts is not running" def debug(): pid = getpid() if pid >= 0: os.kill(pid, signal.SIGUSR1) print "sent DenyHosts SIGUSR1" else: print "DenyHosts is not running" def status(): pid = getpid() if pid == STATE_LOCK_EXISTS: print "%s exists but DenyHosts is not running" % DENYHOSTS_LOCK elif pid == STATE_NOT_RUNNING: print "Denyhosts is not running" else: print "DenyHosts is running with 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() |
Затем мы должны сделать этот файл исполняемым:
chown root daemon-control
chmod 700 daemon-control
После этого мы создаем ссылки на загрузку системы для DenyHosts, чтобы он автоматически запускался при загрузке системы:
cd /etc/init.d
ln -s /usr/share/denyhosts/daemon-control denyhosts
update-rc.d denyhosts defaults
Наконец, мы запускаем DenyHosts:
/etc/init.d/denyhosts start
DenyHosts ведет журнал в /var/log/denyhosts, если вас интересуют журналы. SSH-демон ведет журнал в /var/log/auth.log на Debian. Вы можете просмотреть оба журнала и попробовать войти с недействительным пользователем или с действительным пользователем и неправильным паролем и т. д. через SSH и посмотреть, что произойдет. После того как вы превысите порог неправильных попыток входа, IP-адрес, с которого вы пытались подключиться, должен быть внесен в /etc/hosts.deny, как это:
| # /etc/hosts.deny: list of hosts that are _not_ allowed to access the system. # See the manual pages hosts_access(5), hosts_options(5) # and /usr/doc/netbase/portmapper.txt.gz # # Example: ALL: some.host.name, .some.domain # ALL EXCEPT in.fingerd: other.host.name, .other.domain # # If you're going to protect the portmapper use the name "portmap" for the # daemon name. Remember that you can only use the keyword "ALL" and IP # addresses (NOT host or domain names) for the portmapper. See portmap(8) # and /usr/doc/portmap/portmapper.txt.gz for further information. # # The PARANOID wildcard matches any host whose name does not match its # address. # You may wish to enable this to ensure any programs that don't # validate looked up hostnames still leave understandable logs. In past # versions of Debian this has been the default. # ALL: PARANOID sshd: 192.168.0.203 |
Это означает, что система с IP-адресом 192.168.0.203 больше не может подключаться с помощью SSH.
Вы можете указать, если/когда IP-адреса будут удалены снова из /etc/hosts.deny - посмотрите на переменную PURGE_DENY в /usr/share/denyhosts/denyhosts.cfg. Вы должны запустить DenyHosts с опцией –purge, чтобы сделать переменную PURGE_DENY эффективной, вот так:
/etc/init.d/denyhosts start –purge
Тем не менее, вы также можете вручную удалить IP-адреса оттуда, и как только они будут удалены, эти IP-адреса смогут снова попытаться войти через SSH.
Ссылки
- DenyHosts: http://denyhosts.sourceforge.net
Get new posts in your inbox
No spam. Unsubscribe anytime.