Защита ssh от брутфорса. Блокирование IP при подборе паролей
Если у вас есть сервер, на котором должна быть возможность подключения по ssh из интернета, значит всегда будут желающие подобрать пароль (brute force) для входа. Как бороться с такими «переборщиками»?
Лучше всего сделать авторизацию по ключу. Можно поменять порт (поможет, но не от всех желающих). А что делать, если нужно использовать стандартный порт и авторизацию по паролю?
В первую очередь запретить руту логиниться по паролю:
PermitRootLogin no
Далее, вы должны ограничить число пользователей у которых есть доступ к ssh.
AllowUsers user1 user2 user3
Эти настройки вы должны изменить или добавить в конфигурационном файле ssh /etc/ssh/sshd_config и перезапустить демон sshd.
Теперь в вашем /var/log/messages будет полно записей типа:
Oct 15 18:13:59 myserver sshd[7790]: Failed password for invalid user root from 212.83
.130.87 port 56520 ssh2
Можно избавиться и от этих назойливых попыток взлома. Достаточно установить и настроить одну из программ Fail2ban или DenyHosts. Они будут анализировать содержимое журнала /var/log/messages и особо ретивых брутфорсеров блокировать при помощи firewall.
Но мы лёгких путей не ищем! У меня на сервере нет python, необходимого для работы этих программ, да и блокировки при помощи файервола мне не нравятся.
Сделаем на perl простенький блокировщик с использованием /etc/hosts.deny. Он будет постоянно следить за сообщениями syslog, поступающими от sshd, анализировать их. Если с какого-то ip-адреса будет более 5 попыток входа «нелегальным» пользователем, этот ip будет добавлен в /etc/hosts.deny, а это значит демон tcpd заблокирует доступ с этого ip к sshd.
Для начала определимся где будет находиться наш блокировщик. Например в /root/bin/deny-hosts/.
mkdir /root/bin/deny-hosts
Создаём файл для списка заблокированных ip.
touch /etc/hosts.sshd.deny
В /etc/hosts.deny добавим такую строчку:
sshd : /etc/hosts.sshd.deny
Взаимодействие syslog и нашей программы организуем через именованные каналы (named pipe). Создаем канал:
mknod /root/bin/deny-hosts/auth.info p
chmod 600 /root/bin/deny-hosts/auth.info
И настроим syslog так чтобы сообщения от sshd попадали в этот канал. Добавим в /etc/syslog.conf такую строчку:
auth.info;mail.none |/root/bin/deny-hosts/auth.info
Теперь в /root/bin/deny-hosts/ создадим deny-hosts.pl такого содержания:
#!/usr/bin/perl
use Sys::Syslog;
$from = "admin\@myserver.com";
$to = "admin\@myserver.com";
%ban;
%banned;
openlog("deny-hosts", "ndelay,pid", "local0");
open (FIFO, "/root/bin/deny-hosts/auth.info");
syslog(LOG_INFO, "started");
while (1) {
while (<FIFO>) {
$str = $_;
if ($str=~/Failed password for invalid user .+ (.+) port/) {
if(!$ban{$1}) {
$ban{$1}=1;
} else {
$ban{$1}++;
}
foreach $key (keys %ban) {
if($ban{$key}>5 && $key) {
if (!$banned{$key}) {
open (BL, '>>/etc/hosts.sshd.deny');
print BL $key,"\n";
close(BL);
smtp_send($key);
syslog(LOG_INFO, "IP banned: $key");
}
delete($ban{$key});
$banned{$key} = 1;
}
}
}
}
smtp_send("syslog restarted");
sleep 5;
}
syslog(LOG_INFO, "exited");
close (FIFO);
closelog();
sub smtp_send {
my $body = $_[0];
my $time = time();
my ($sec,my $min,my $hour,my $mday,my $mon,my $year,my $wday,my $yday,my $isdst) = localtime($time);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d ", ($year+1900), ($mon+1), $mday, $hour, $min, $sec);
if (open (SENDMAIL, "|/usr/sbin/sendmail -t")) {
print SENDMAIL "From: $from\n";
print SENDMAIL "To: $to\n";
print SENDMAIL "Subject: IP banned $now\n\n";
print SENDMAIL "$body";
close (SENDMAIL);
}
}
Следует заменить в коде email-адреса с которого будут отправляться и на который будут приходить сообщения о заблокированных ip-адресах (в 5 и 6 строках кода).
Дайте права на запуск:
chmod 755 /root/bin/deny-hosts/deny-hosts.pl
Можно запускать скрипт вручную, а можно написать такой вот скрипт запуска/перезапуска:
#!/bin/sh
killall deny-hosts.pl
/root/bin/deny-hosts/deny-hosts.pl &
И запускать его автоматически при старте системы.
(#) Андрій:
Привіт. А можна якесь роз’яснення щодо «можно написать такой вот скрипт запуска/перезапуска»? де цей скрипт має знаходитись? як налаштувать його увімкнення\активність?
(#) Дмитрий:
Ви можете покласти його де вам зручно, а викликати як зазвичай, з /etc/rc.d/rc.local
Це якщо у вас стара сиcтема ще без systemd
Якщо в вашій системі вже використовується systemd то відповідні скрипти знайдете тут https://github.com/dshovchko/deny-hosts-pl (Але в такому разі я раджу встановити Fail2ban)