Защита на Ubuntu 16.04 хостинг сървър с Fail2ban и ipset
Fail2ban – блокиране при грешна парола
Fail2Ban е програма за предотвратяване на нежелани прониквания от Интернет в Линукс сървъри, написана е на езика за програмиране Python. Тя работи като прочита логовете на SSH, FTP, HTTP и други хостинг услуги на Линукс сървъри. При определен брои неосъществени оторизирания Fail2ban ще блокира само тази услуга за определено време само за атакуващия IP адрес. Fail2Ban използва iptables профили да блокира опитите на груба сила (Brute Force) като следи логовете на Линукс услугите в /var/log/$service.log
Инсталиране
sudo apt-get install fail2ban
Копиране на примерен конфигурационен файл
cd /etc/fail2ban
sudo cp jail.conf jail.local
Редактиране на конфигурациония файл
sudo nano jail.local
Моят конфигурационен файл
[DEFAULT]
mta = mail
destemail = mymail@server.net
sendername = Fail2Ban_your@server.net
action = %(action_mwl)s
[pureftpd]
enabled = true
port = ftp
filter = pureftpd
logpath = /var/log/syslog
bantime = 3600
findtime = 600
maxretry = 3
[dovecot-pop3imap]
enabled = true
filter = dovecot-pop3imap
action = iptables-multiport[name=dovecot-pop3imap, port="pop3,pop3s,imap,imaps", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 3
[postfix]
enabled = true
port = smtp,ssmtp,submission
filter = postfix
logpath = /var/log/mail.log
[postfix-sasl]
enabled = true
port = smtp
filter = postfix-sasl
logpath = /var/log/mail.log
bantime = 3600
findtime = 600
maxretry = 3
[dropbear]
enabled = true
port = ssh
filter = dropbear
logpath = /var/log/auth.log
maxretry = 3
[ssh-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 3
[apache]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 3
[apache-multiport]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 3
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/error.log
maxretry = 3
[apache-overflows]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/error.log
maxretry = 2
[roundcube-auth]
enabled = true
filter = roundcube-auth
port = http,https
logpath = /var/log/roundcube/errors
Както е видно от конфигурациония файл на тази машина има postfix майл сървър който ми изпраща на мейла всеки един блокиран неуспешен опит на услугите които следи със следната конфигурация:
mta = mail
destemail = mymail@server.net
sendername = Fail2Ban_your@server.net
action = %(action_mwl)s
Аз в моя мейл клиент получавам това:
Нека разгледаме един модул на услуга от този конфигурационен файл:
[postfix-sasl] – Това е оторизиращия механизъм на мейл сървъра
enabled = true – false няма да се изпълни, true ще се изпълни
port = smtp – Порта който използва
filter = postfix-sasl – iptables профила който ще използва
logpath = /var/log/mail.log – от къде взима историята за неуспешна ауторизация
bantime = 3600 – времето в секунди в което ще блокира услугата
findtime = 600 – времето в секунди в което ще брой неуспешните опити
maxretry = 3 – броя на опитите за ауторизация
След като опишем услугите които ползваме трябва да рестартираме fail2ban за да влязат промените в сила:
sudo service fail2ban restart
За да придобием повече информация какво прави fail2ban освен от мейла ако е настроен можем да разгледаме логовете му.
sudo tail -f /var/log/fail2ban.log
2016-12-31 06:45:08,756 fail2ban.actions: WARNING [postfix-sasl] Unban 65.83.46.99
2016-12-31 06:45:18,872 fail2ban.actions: WARNING [postfix-sasl] Ban 65.83.46.99
Unban и Ban всъщност означава – разблокиран и блокиран, за определен период от време, findtime = 600 ако не се оторизира 3 пъти maxretry = 3 ще бъде блокиран за bantime = 3600 секунди време.
ipset – хиляди правила в няколко реда
ipset също е модул в ядрото на Линукс което на практика е разширение в iptables. За да обясня как работи ipset трябва да се върна в началото и да обясня как работи iptables. Нека си представим (само за тест), че услугата SSH искам да я спра за всички и само определен брой мрежи и адреси да имат достъп до нея:
iptables -A INPUT -p tcp --dport 22 -s 93.155.130.0/23 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 93.155.162.44 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 93.155.169.55 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
Първите три реда които завършват с ACCEPT разрешават пакети идващи от -s IP само на този порт -p tcp –dport 22 във веригата пристигащи INPUT добави правилото да е последно -A. Реда който завършва с DROP забранява на всички порт 22 (SSH) без горните три естествено. Логиката надявам се е ясна, разбира се с тези четири реда не научихме iptables – това е само една трошичка от нея. Fail2ban върши прекрасна работа но аз искам да си направя собствена верига с която да блокирам IP адреси и мрежи от публична листа като Spamhaus например.
Spamhaus държи списък с „лошите“ мрежи http://www.spamhaus.org/drop/drop.lasso които аз искам да блокирам. Но тук аз срещам два проблема. Първият е, че в списъка има 827 мрежи което са си 827 правила в iptables. След като знаем как работи iptables знаем, че за всеки пакет се взима решение след като той премине през всички правила което на практика излиза, че всички пакети идващи към нашият сървър трябва да минат през тези правила. След Spamhaus аз искам да ползвам blacklist и на OpenBL където има 13191 IP адреса които са заразени или пращат спам.
Всъщност искам да блокирам и Китай, и Северна Кореа, защото те нямат работа в моя сървър, но така станаха над 20000 правила, ако всички пакети минават през тези правила едва ли моят сървър ще работи коректно (за да пиша това съм пробвал, не работи коректно !!!) Спасението е ipset който прави така, че в iptables 10000 правила може да изглеждат като 1. Тоест Spamhaus ще е едно правило, OpenBL 2, China 3 и с Кореа ще станат 4 правила но ще блокират някъде около 20000 мрежи в Интернет.
Инсталиране на ipset:
sudo apt-get install ipset
Вторият проблем е как да извлеча 20000 мрежи да ги вкарам в ipset правила в комбинация с iptables и те да се обновяват периочно, например на 24 часа. Решението не може да бъде нищо друго освен прост скрипт на bash. В основата си кода трябва да извлече листата от Интернет в текстов файл, да я подреди в команди и да ги изпълни. Ето пример:
Създаване на ipset скрипта
Не всички дистрибуции имат модул на ipset в ядрото, в Ubuntu server 14.04/16.04 LTS той е в наличност но не е зареден. Ще го видите с командата lsmod едва когато изпълните за първи път ipset.
sudo nano firewall.sh
#!/bin/bash
#
# Based ipset script block Spamhaus, OpenBL, China and Korea
#
# Require Ubuntu server 14.04/16.04 LTS and ipset
# sudo apt-get install ipset
# lsmod | grep ip_set
# ip_set_hash_ip 32768 1
# ip_set_hash_net 32768 3
# ip_set 45056 3 ip_set_hash_net,ip_set_hash_ip,xt_set
# nfnetlink 16384 1 ip_set
#
# Samuil Arsov <support@itservice-bg.net>
#
clear
start() {
echo "spamhaus"
ipset create Spamhaus hash:net
wget -qc www.spamhaus.org/drop/drop.lasso -O /tmp/drop.lasso
for i in $(cat /tmp/drop.lasso | egrep -v '^;' | awk '{ print $1}'); do
ipset -A Spamhaus $i
done;
unlink /tmp/drop.lasso
iptables -A INPUT -m set --match-set Spamhaus src -j DROP
echo "china"
ipset create China hash:net
wget -qc http://www.okean.com/chinacidr.txt -O /tmp/drop.china
for i in $(cat /tmp/drop.china | egrep -v '^#' | awk '{ print $1}'); do
ipset -A China $i
done;
unlink /tmp/drop.china
iptables -A INPUT -m set --match-set China src -j DROP
echo "korea"
ipset create Korea hash:net
wget -qc http://www.okean.com/koreacidr.txt -O /tmp/drop.korea
for i in $(cat /tmp/drop.korea | egrep -v '^#' | awk '{ print $1}'); do
ipset -A Korea $i
done;
unlink /tmp/drop.korea
iptables -A INPUT -m set --match-set Korea src -j DROP
echo "openbl"
ipset create OpenBL hash:ip
wget -qc http://www.openbl.org/lists/base.txt -O /tmp/drop.openbl
for i in $(cat /tmp/drop.openbl | egrep -v '^#' | awk '{ print $1}'); do
ipset -A OpenBL $i
done;
unlink /tmp/drop.openbl
iptables -A INPUT -m set --match-set OpenBL src -j DROP
}
stop() {
iptables -D INPUT -m set --match-set Spamhaus src -j DROP
ipset destroy Spamhaus
iptables -D INPUT -m set --match-set China src -j DROP
ipset destroy China
iptables -D INPUT -m set --match-set Korea src -j DROP
ipset destroy Korea
iptables -D INPUT -m set --match-set OpenBL src -j DROP
ipset destroy OpenBL
}
status() {
SPAMHAUS=$(ipset list Spamhaus | wc -l)
CHINA=$(ipset list China | wc -l)
KOREA=$(ipset list Korea | wc -l)
OPENBL=$(ipset list OpenBL | wc -l)
echo "-----------------------------------------------------------"
iptables -nvL | grep match-set
echo "-----------------------------------------------------------"
echo " Spamhaus:$SPAMHAUS China:$CHINA Korea:$KOREA OpenBL:$OPENBL"
echo ""
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
Правим, скрипта изпълним:
sudo chmod 755 firewall.sh
И го изпълняваме със start
sudo ./firewall.sh start
Като след това със status трябва получим подобен резултат:
sudo ./firewall.sh status
От който виждаме, че DROP веригите се пълнят с пакети идващи от „лошите“ мрежи а на последния ред колко хиляди правила на ipset има във всяка от четирите вериги Spamhaus, China, Korea и OpenBL на iptables.
Всяка следващо изполване на скрипта с опцията restart ше обновява нашата blacklist актуална като не влияе по никакъв начин на правилата във Fail2ban.
sudo ./firewall.sh restart
Нека да направим така, че скрипта да се изпълнява всяка сутрин в 5 часа сутринта автоматично без човешка намеса. За целта трябва да редактираме /etc/crontab като добавим следния ред:
0 5 * * * root /home/samyil/firewall.sh
И рестартираме cron демона за да влязат настройките в сила:
sudo service cron restart




