Сегодня я приведу практические рекомендации как обезопасить установленный блог на VPS хостинге. Имея VPS хостинг — Вам выделяются ресурсы (HDD,CPU,RAM) и ваша задача не только поставить систему Ubuntu (LTS релизы) и развернуть CMS-систему WordPress, но и защитить вашу vps‘ку. Что я подразумеваю под защитой:
- прекратить подбор логина и пароля в административную часть wordpress
- прекратить подбор пароля до сервера удаленного администрирования (SSH)
Ранее на своем блоге я описал как защитить выставленную систему от несанкционированного подключения с помощью фаервола (ufw) и технологии port knocking, но вот если Вы не хотите использовать port knocking (технология простукивания системы), то можно защититься посредством утилиты fail2ban о которой в практическом применении и пойдет речь. Что может данная утилита — а она просто анализирует логи формируемых сервисов на Вашем сервере посредством составленных фильтров и если количество повторяющихся записей отказа или ошибок повторяется за определенное время то происходит блокировка в виде запрета доступа.
Итак моя система моего блога: Ubuntu Trusty, блог развернут по заметке.
Устанавливаю утилиту fail2ban в систему:
ekzorchik@srv-host:~$ sudo apt-get install fail2ban -y
Конфигурационные файлы утилиты fail2ban располагаются в каталоге /etc/fail2ban, также его содержимое Важно с точки зрения накладываемого функционала на содержимое, а именно:
- каталог → action.d – содержит правила (/etc/fail2ban/action.d/) реагирования исходя из файла jail.conf и фильтров из каталога /etc/fail2ban/filter.d/
- каталог –> filter.d – содержит фильтры
- каталог → jail.conf – файл объединяющий все правила воедино
Но обычно приложение fail2ban используется для защиты выставляемых во всемирную сеть сервисов, к примеру: Asterisk, Mail, FileServer, а вот для CMS систем?
Когда кто-либо пытается зайти в административную часть и не только по переходу ссылке “Войти” указывая неправильный логин или же пароль, а может и все вместе, то в журналах формируются следующие записи:
- http://10.7.8.122/wp-login.php
если Login: указывается к примеру ekzorchik, а пароль: подбираемый, то на данной странице выводится подсказка, то да пользователь есть, но вот пароль не соответствует правильному:
ОШИБКА: Введённый вами пароль пользователя ekzorchik неверен. Забыли пароль? (http://10.7.8.122/wp-login.php?action=lostpassword)
ekzorchik@srv-host:~$ tail -f /var/log/apache2/wordpress-access.log
10.7.8.135 – – [16/Feb/2016:09:04:44 +0300] “POST /wp-login.php HTTP/1.1” 200 2166 “http://10.7.8.122/wp-login.php” “Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0”
10.7.8.135 – – [16/Feb/2016:09:04:44 +0300] “GET /wp-includes/css/buttons.min.css?ver=4.4.2 HTTP/1.1” 200 1697 “http://10.7.8.122/wp-login.php” “Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0”
10.7.8.135 – – [16/Feb/2016:09:04:44 +0300] “GET /wp-includes/css/dashicons.min.css?ver=4.4.2 HTTP/1.1” 200 28890 “http://10.7.8.122/wp-login.php” “Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0”
10.7.8.135 – – [16/Feb/2016:09:04:44 +0300] “GET /wp-admin/css/login.min.css?ver=4.4.2 HTTP/1.1” 200 6235 “http://10.7.8.122/wp-login.php” “Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0”
- если не правильно указываем даже логин и пароль, то еще одна подсказка, то такого логина не существует:
ОШИБКА: Неверное имя пользователя. Забыли пароль? (http://10.7.8.122/wp-login.php?action=lostpassword)
Что примечательно так это события в лог файлах, любое действие авторизации и безуспешно авторизации сопровождается ответным кодом 200 – что якобы успешно по правилам работы в Web-пространстве. Бред какой-то.
Но так дело не пойдет, буду разбирать как прикрутить fail2ban к используемой CMS системе WordPress для этого создаю фильтр:
ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/filter.d/wordpress-authen.conf
[Definition]
failregex = <HOST> - - .* "POST.*(wp-login\.php|xmlrpc\.php).* 200
ignoreregex =
На заметку: режим POST – это передача параметров путем ввода в соответствующие поля, а режим GET – это получение параметров.
Не забываем сохранить внесенные изменения в новый фильтр. Данная строка означает, что осуществляется поиск строки со статусом кода 200 и запросе/вводе URL адреса или переходу к файлам: wp-login.php & xmlrpc.php.
На заметку: по правилам хорошего тома в конфигурационном файле jail.conf должно быть только то что используется и прокомментировано, все остальное должно быть удалено.
ekzorchik@srv-host:~$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.old
А теперь создаю правило реагирования:
ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/action.d/ufw-wordpress.conf
[Definition]
actionstart =
actionstop =
actioncheck =
# этим мы блокируем нарушителя для всего хостинга, если нужно только для 80 порта, то to any port 80
actionban = ufw insert 1 deny from <ip> to any
actionunban = ufw delete deny from <ip> to any
А теперь создаю правило блокировки для сервиса:
ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/jail.conf
[wordpress-authen]
enabled = true
# правила реагирования: /etc/fail2ban/action.d/ufw-wordpress.conf
action = ufw-wordpress
port = http
filter = wordpress-authen
logpath = /var/log/apache2/wordpress-access.log
# если в течение одного часа было 5 неудачных попыток, то блокируем его на одни сутки
# если по статистики количество блокируемых будет измеряться сотнями, то можно увеличить период на неделю.
# в течение часа
findtime = 3600
# пять неудачный попыток
maxretry = 5
# блокировка на 24 часа
bantime = 86400
Не забываем сохранить внесенные изменения.
На заметку: описание параметров из конфигурационного файла jail.conf
- ignoreip — IP–адреса, которые не должны быть заблокированы. Можно задать список IP-адресов разделённых пробелами, маску подсети, или имя DNS–сервера, т. е. Ваш рабочий статический, домашний с которых только Вы можете зайти, а все остальные ни-ни.
- bantime — время бана в секундах, по истечении которого IP–адрес удаляется из списка заблокированных. findtime = 3600 (## если в течении 1 часа:)
- maxretry — количество подозрительных совпадений, после которых применяется правило. В контексте
[ssh]
— это число неудавшихся попыток логина, после которых происходит блокировка. - enabled — значение
true
указывает что данный jail активен,false
выключает действие изолятора. - port — указывает на каком порту или портах запущен целевой сервис. Стандартный порт SSH–сервера — 22, или его буквенное наименование —
ssh, Web-сервера — 80 (http)
- filter — имя фильтра с регулярными выражениями, по которым идёт поиск «подозрительных совпадений» в журналах сервиса. Фильтру
wordpress-authen
соответствует файл /etc/fail2ban/filter.d/wordpress-authen.conf - logpath — путь к файлу журнала, который программа Fail2ban будет обрабатывать с помощью заданного ранее фильтра. Вся история удачных и неудачных входов в wordpress /var/log/apache2/wordpress-access.log
Чтобы настройки сервиса активировались нужно перезапустить службу fail2ban:
ekzorchik@srv-host:~$ sudo service fail2ban restart
* Restarting authentication failure monitor fail2ban
Проверяем, как отработает блокировка:
ekzorchik@srv-host:~$ sudo tail -f /var/log/apache2/wordpress-access.log
вводим в окне авторизации неправильные логин и пароль в количестве пяти раз, а тем временем в журнале fail2ban появляются нижеследующие строки
2016-02-16 10:16:38,527 fail2ban.jail : INFO Jail ‘wordpress-authen’ started
2016-02-16 10:20:59,344 fail2ban.actions: WARNING [wordpress-authen] Ban 10.7.8.135
вот и мой IP адрес (10.7.8.135) с которого я пишу и попутно тестирую/работаю заблокирован.
по прошествии некого времени мой IP был разблокирован
2016-02-16 10:30:59,591 fail2ban.actions: WARNING [wordpress-authen] Unban 10.7.8.135
и уже обратившись через браузер http://10.7.8.122 — я получаю сообщение от «Попытка соединения не удалась» – и это здорово.
Чтобы посмотреть статистику по отработанному фильтру:
ekzorchik@srv-host:~$ sudo fail2ban-client status wordpress-authen
Status for the jail: wordpress-authen
|- filter
| |- File list: /var/log/apache2/wordpress-access.log
| |- Currently failed: 0
| `- Total failed: 5
`- action
|- Currently banned: 1
| `- IP list: 10.7.8.135
`- Total banned: 1
Как видно, мой IP адрес заблокирован, чтобы разблокировать определенный IP адрес нужно набрать следующую команду:
ekzorchik@srv-host:~$ sudo fail2ban-client set wordpress-authen unbanip 10.7.8.135
10.7.8.135
Отлично теперь можно авторизовать через Web-интерфейс.
А заблокировать снова внеся его в BAN лист в ручную можно такой командой:
ekzorchik@srv-host:~$ sudo fail2ban-client set wordpress-authen banip 10.7.8.135
10.7.8.135
Итак что обозначают введенные команды:
- wordpress-authen — название настроенного фильтра в конфигурационном файле jail.conf
- banip — заблокировать указанный адрес
- unbanip — разблокировать указанный адрес
На заметку:
на будущее смотрите хелп по команде fail2ban-client там все подробно описано (я же справился)
Хочу заменить, что данный способ успешно работает и препятствует доступ к моему блогу нежелательных, вот к примеру, однажды зайдя на свой VPS ресурс и сделав отчет как работает защита wordpress – увидел вот такую картину:
<secret_user>@<secret_host>:~$ sudo fail2ban-client status wordpress-authen
Status for the jail: wordpress-authen
|- filter
| |- File list: /var/log/apache2/wordpress-access.log
| |- Currently failed: 0
| `- Total failed: 72
`- action
|- Currently banned: 5
| `- IP list: 23.125.42.243 184.183.155.178 173.8.27.45 54.186.75.170 69.15.51.33
`- Total banned: 5
Видно, что попытки несанционированного доступа уже пресекаются. И это хорошо.
Так это я рассмотрел действия чтобы не дать зайти в панель администрирования wordpress, но ведь я на него же имею доступ по ssh, защищаю систему по заметке.
ekzorchik@srv-host:~$ sudo ufw allow to any port 381
Rule added
ekzorchik@srv-host:~$ sudo ufw allow to any port 80
Skipping adding existing rule
ekzorchik@srv-host:~$ sudo ufw status numbered
Status: active
To Action From
— —— —-
[ 1] 80 ALLOW IN Anywhere
[ 2] 381 ALLOW IN Anywhere
Теперь перехожу к настройке правила которое будет блокировать несанкционированные попытки зайти на мой блог по порту 381 на котором работает OpenSSH сервис. По умолчанию когда утилита fail2ban установлена, защита ssh активируется по умолчанию:
ekzorchik@srv-host:~$ ps aux | grep sshd
root 742 0.0 0.1 61380 5312 ? Ss 07:58 0:00 /usr/sbin/sshd -D
ekzorchik@srv-host:~$ sudo service ssh status
ssh start/running, process 742
фильтры уже настроены: /etc/fail2ban/filter.d/sshd.conf
Когда кто-то пытается подключиться к службе по стандартному порту, то в логах появляются следующие строки:
Mar 7 09:12:39 srv-host sshd[2718]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.7.8.135
Mar 7 09:12:40 srv-host sshd[2718]: Failed password for invalid user ad from 10.7.8.135 port 56800 ssh2
На заметку: По умолчанию fail2ban работает совместно с брандмауэром iptables, но я же использую ufw, а потому ниже будут приведены действия по замене работы.
А потому нужно настроить блокировку от таких вот часто повторяющихся строк в файлах логов:
ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/jail.conf
#banaction = iptables-multiport
#action_
#action_mw
#action_mwl
#action
[ufw-ssh]
enabled = true
# /etc/fail2ban/action.d/ufw-ssh.conf
action = ufw-ssh
port = 381
filter = sshd
logpath = /var/log/auth.log
# количество подозрительных совпадений
maxretry = 5
# в течении 5 минут - три совпадения
findtime = 300
# блокировка на 24 часа
bantime = 86400
Создаю правила реагирования на нарушителей:
ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/action.d/ufw-ssh.conf
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = ufw insert 1 deny from <IP> to any app OpenSSH
actionunban = ufw delete deny from <IP> to any app OpenSSH
Не забываем по окончании правки конфигурационных файлов сохранить внесенные изменения. А теперь перезапускаем службу failban для активации изменений:
ekzorchik@srv-host:~$ sudo service fail2ban restart
Проверяем текущий статус правила:
ekzorchik@srv-host:~$ sudo fail2ban-client status ssh
Status for the jail: ssh
|- filter
| |- File list: /var/log/auth.log
| |- Currently failed: 0
| `- Total failed: 0
`- action
|- Currently banned: 0
| `- IP list:
`- Total banned: 0
C другой машины пробую подключаться с использованием неизвестных мне логинов и паролей к системе:
aollo@srv-glpi:~$ ssh -l admin 10.7.8.122 -p 381
admin@10.7.8.122’s password:
Permission denied, please try again.
admin@10.7.8.122’s password:
^C
aollo@srv-glpi:~$ ssh -l n 10.7.8.122 -p 381
ssh: connect to host 10.7.8.122 port 381: Connection refused
, а на 22 порт нельзя будет подключиться потому как он закрыт и открывается только когда по нему постучат, хотя на него также желательно настроить fail2ban на всякий случай (ну может быть).
, вот теперь я заблокировал на срок указанный в конфигурационном файле jail.conf нарушителя.
Проверяю:
ekzorchik@srv-host:~$ sudo fail2ban-client status ssh
Status for the jail: ssh
|- filter
| |- File list: /var/log/auth.log
| |- Currently failed: 0
| `- Total failed: 9
`- action
|- Currently banned: 1
| `- IP list: 10.7.8.154
`- Total banned: 1
По сути выставление порта 381 — это просто медовый сервис по отводу личностей от Вашего хостинга. Рекомендую время блокировки IP указать выраженное, как неделя. На этом я хочу подытожить все то, что рассмотрел что нужно сделать чтобы обезопасить вашу VPS от посягательств. В дальнейшем я буду рассматривать защиту различных сервисов посредством связки: ufw + fail2ban для меня так понятней чем писать правила посредством iptabes. Как говориться каждому свое. На этом у меня все и до новых заметок, с уважением автор блога — ekzorchik.