Защита на Ubuntu 16.04 хостинг сървър с Fail2ban и ipset

Хостинг сървър
Под хостинг сървър разбираме, сървър с публични услуги от рода на http, https, ftp, ssh, smtp, dns, databases и други подобни. Хостинг сървъра не е нужно да е на хостинг компания, той може да е собственост на фирма или дори на частно лице обслужвайки собствен сайт, билингова система, ERP, онлайн архив, електронна поща и др. Причините за създаването на фирмен или личен хостинг сървър са повече от логични – никои не иска чувствителната му информация да се намира на място където може да бъде компроментирана като например споделен хостинг или “трибуквен” обществен мейл сървър. Хостинг сървъра може да е скрит в гардероба в спалнята, под бюрото на секретарката в офиса, виртуална машина (VPS) или нает сървър (dedicated server) в голяма хостинг компания но в термина хостинг сървър ние ще вложим линукс сървър с публични услуги достъпни навсякъде в “големия лош” Интернет.
Кибер атаки
Надявам се да не прозвуча като журналист но кибер атаките (Cyber Attacks) в по голямата си част са груба сила (Brute Force) което ще рече, че някой иска да спре или влоши определена услуга до неработещо състояние (DoS – denial of service) или иска да налучка паролата ви на SSH като използва текстов файл с най често използвани пароли (Wordlists). DoS – denial of service има различни нива на сложност. От аматьори (single UDP flood, TCP syn, smurf attack) до Бот мрежи (Botnet) които свалят сайтове на правителства, корпорации и медии. В повечето случаи ако сте жертва на DoS имате платена услуга или сте обидили някой, тоест става въпрос за пари или за политика. За Brute force (ssh, smtp, ftp Wordlists) обаче не е нужно да сте фактор а напротив, след като налучкат паролата ви и получат достъп до определена услуга, вие ще станете ресурс на някой Botnet или иначе казано “зомби”. Колкото сте по незначителен толкова повече ще ви се радват в Botnet мрежата защото не сте планирана част в защитните стени на компаниите които пък продават софуер за предотвратяване на такъв род атаки.
Видове защита
Всяка една онлайн услуга в Линукс сървъра има някакъв вид защитен механизъм. Apache directives, htaccess, htpassword, FTP deny/allow directives, sshd permit login и други. Всички те влизат в графа вътрешна защита, за тях си има отделна документация а и всичко е строго индувидуално какво ще обслужва услугата. В този пост ще обърна внимание на защитата на сървъра като цяло, нека я наречем с половин уста външна защита или политика на сигурност която ще използва защитната стена в Линукс
Защитна стена
Защитната стена в Линукс Netfilter (iptables е интерфейса на netfilter затова ще използваме само неговото име) е програма, която преглежда заглавните части (header) на идващите пакети като и решава съдбата. iptables може да реши да отхвърли (DROP) пакета (все едно този пакет никога не е пристигал), да приеме (ACCEPT) пакета (да разреши да премине), или да извърши друго по-сложно действие. В Линукс защитната стена е част от ядрото и можем да правим някои доста сложни неща в определени ситуации като например да построим една интелигентна защитна стена в нашия хостинг сървър. Защитна стена която ще блокира завинаги или за определен период от време, ще ми позволите жаргона лошите “Досери” (идва от DoS)

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 е международна неправителствена организация, която следи за спам и киберзаплахи като фишинг, злонамерен софтуер и ботнет, осигурява в реално време точен анализ за хостинг компании, корпорации и доставчици на Интернет. Spamhaus работи с правоохранителните органи от цял свят за да идентифицират и преследват източниците на спам и зловреден софтуер в световен мащаб.

Spamhaus държи списък с “лошите” мрежи http://www.spamhaus.org/drop/drop.lasso които аз искам да блокирам. Но тук аз срещам два проблема. Първият е, че в списъка има 827 мрежи което са си 827 правила в iptables. След като знаем как работи iptables знаем, че за всеки пакет се взима решение след като той премине през всички правила което на практика излиза, че всички пакети идващи към нашият сървър трябва да минат през тези правила. След Spamhaus аз искам да ползвам blacklist и на OpenBL където има 13191 IP адреса които са заразени или пращат спам.

Проектът OpenBL.org, известен преди като черния списък SSH има за цел откриване, регистриране и отчитане на различни видове интернет атаки. Сървърите на OpenBL следят портове 21 (FTP), 22 (SSH), 23 (TELNET), 25 (SMTP), 110 (POP3), 143 (IMAP), 587 (Submission), 993 (IMAPS) и 995 (POP3S) за Brute force атаки, както и сканиране на портове 80 (HTTP) и 443 (HTTPS) за уязвимите инсталации на PhpMyAdmin и други уеб приложения.

Всъщност искам да блокирам и Китай, и Северна Кореа, защото те нямат работа в моя сървър, но така станаха над 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
Никъде не написах до тук, че сме защитили сървъра защото на практика свършихме само половината работа. Просто му подобрихме сигурноста и вероятноста да го “ударят” е доста по малка. Следващата стъпка с не по малко важност е вътрешната защита и по точно конфигурацията на услугите които са на сървъра.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This Post Has 6 Comments

  1. kvant

    Изключително полезна статия. Благодаря на автора.

  2. Станислав

    Здравейте бих искал да попитам как мога да блокирам (https://www.spamhaus.org/drop/asndrop.txt) след като списъка не е във вид на IP аддреси . За първи път ще пускам сървър . Използвам Дебиан 9 с Fail2ban (блокирах изходящия и входящия трафик и пропуснах IN–80,443 | OUT 53,80,443 Не позлвам SSH и Sendmail ! ), сега се опитвам да блокирам DDos UDP Атаките , но за жалост без успех . Преобърнах целия интернет . Моля за помощ .

  3. Самуил Арсов

    Не можете, това са автономни системи – ASN (доставчици на Интернет). Те могат да се блокират само от BGP маршрутизатора на вашият Интернет доставчик. Друг е въпроса, че искате да блокирате спам а не цели мрежи на доставчици което са различни неща. Затова не намирам смисъл да правите това.

  4. The_Admin

    Но пък с малък скрипт можете от автономните системи да изваждате префиксите които те обявяват и да ги превръщате в правила за блокиране:

    #!/bin/bash
    for ip in `whois -h whois.radb.net '!gAS3266' | grep / | sort -n | uniq`
    do
    echo  "iptables -A FORWARD -p all -d $ip -j REJECT"
    done
    

    Ето и резултата 🙂

    theadmin@telehost.bg:~$ sudo ./BGP-AS_net_list.sh 
    iptables -A FORWARD -p all -d 107.181.119.0/24 -j REJECT
    iptables -A FORWARD -p all -d 193.201.142.0/24 -j REJECT
    iptables -A FORWARD -p all -d 193.201.140.0/24 -j REJECT
    iptables -A FORWARD -p all -d 157.119.100.0/24 -j REJECT
    iptables -A FORWARD -p all -d 157.119.101.0/24 -j REJECT
    iptables -A FORWARD -p all -d 157.119.102.0/24 -j REJECT
    iptables -A FORWARD -p all -d 157.119.103.0/24 -j REJECT
    iptables -A FORWARD -p all -d 212.68.172.0/22 -j REJECT
    iptables -A FORWARD -p all -d 171.25.212.0/22 -j REJECT
    iptables -A FORWARD -p all -d 185.185.49.0/24 -j REJECT
    iptables -A FORWARD -p all -d 185.185.48.0/24 -j REJECT
    iptables -A FORWARD -p all -d 185.185.50.0/24 -j REJECT
    iptables -A FORWARD -p all -d 185.185.51.0/24 -j REJECT
    iptables -A FORWARD -p all -d 91.108.121.0/24 -j REJECT
    iptables -A FORWARD -p all -d 91.108.122.0/24 -j REJECT
    iptables -A FORWARD -p all -d 91.108.123.0/24 -j REJECT
    iptables -A FORWARD -p all -d 185.194.194.0/24 -j REJECT
    iptables -A FORWARD -p all -d 185.194.195.0/24 -j REJECT
    iptables -A FORWARD -p all -d 82.115.1.0/24 -j REJECT
    iptables -A FORWARD -p all -d 82.115.2.0/24 -j REJECT
    iptables -A FORWARD -p all -d 82.115.3.0/24 -j REJECT
    iptables -A FORWARD -p all -d 109.201.224.0/20 -j REJECT
    iptables -A FORWARD -p all -d 109.201.240.0/20 -j REJECT
    iptables -A FORWARD -p all -d 185.76.140.0/22 -j REJECT
    iptables -A FORWARD -p all -d 185.199.240.0/22 -j REJECT
    iptables -A FORWARD -p all -d 185.148.12.0/22 -j REJECT
    iptables -A FORWARD -p all -d 109.94.102.0/23 -j REJECT
    iptables -A FORWARD -p all -d 85.234.104.0/21 -j REJECT
    iptables -A FORWARD -p all -d 46.3.0.0/22 -j REJECT
    iptables -A FORWARD -p all -d 46.3.4.0/22 -j REJECT
    iptables -A FORWARD -p all -d 46.3.8.0/22 -j REJECT
    iptables -A FORWARD -p all -d 46.3.12.0/22 -j REJECT
    iptables -A FORWARD -p all -d 94.154.40.0/22 -j REJECT
    iptables -A FORWARD -p all -d 107.181.119.0/24 -j REJECT
    
  5. Станислав

    Здравейте при използването на горния скрипт съм задал echo 1 > /proc/sys/net/ipv4/ip_forward , но защо не мога да видя правилата като зададени с командата iptables -L FORWARD .

  6. Станислав

    Разбрах скрипта , явно съм го чел между редовете . Сега идва другия момент , Има ли нещо повече което мога да направя за сървъра ??? След като ползвам скрипта на г-н Самуил Арсов и The_Admin заедно с Fail2ban , .htaccess-.htpasswd за phpmyadmin , mod_security , mod_qos . Нещо друго може ли да добавя за да повиша сигурноста ?