Как правило, сканеры безопасности не представляют угрозы для сайта, если конечно вы следите за его состоянием. Но активность сканеров может быть сигналом, да и ничего приятного нет когда копаются в ваших вещах. В данной заметке я рассмотрю несколько методов блокировки сканеров и создание графиков состояния фильтров fail2ban
Самый простой метод, но и самый недейственный - это блокировка User-Agent. Пример для Nginx:
if ($http_user_agent ~* ZmEu|nessus|libwhisker) {
return 403;
}
Второй метод, на мой взгляд, самый эффективный - организация honeypot. Вот хороший пример реализации этого метода - "How to Block Automated Scanners from Scanning your Site"
И еще один метод - это блокировка источников, которые используют шаблоны для сканирования сайтов. Такие сканеры определяются довольно легко - по всплеску ошибок 404 и 403 в логах сервера. Для блокировки создаются фильтры в fail2ban. Я создал отдельные фильтры для 404 и 403 ошибок:
#cat /etc/fail2ban/filter.d/nginx-403.conf
# fail2ban filter configuration for nginx
[Definition]
failregex = ^<HOST> .* "(GET|POST) [^"]+" 403
ignoreregex =
#/etc/fail2ban/filter.d/nginx-404.conf
# fail2ban filter configuration for nginx
[Definition]
failregex = ^<HOST> .* "(GET|POST) [^"]+" 404
ignoreregex =
Включаем фильтры в fail2ban, добавляем в /etc/fail2ban/jail.conf
[nginx-404]
enabled = true
filter = nginx-404
port = http,https
logpath = /var/log/nginx/access.log
bantime = 86400 ; 1 day
findtime = 600 ; 10 min
maxretry = 30
[nginx-403]
enabled = true
filter = nginx-403
port = http,https
logpath = /var/log/nginx/access.log
bantime = 86400 ; 1 day
findtime = 600 ; 10 min
maxretry = 30
Логика блокировки проста - при превышении порога количества ошибок в течении 10 минут, адрес блокируется.
Перейдем к визуализации и оповещению.
Следующим этапом организовываем графики количества блокировок. Для чего я использовал logster и graphite.
Устанавливаем logster:
# apt-get install logster
Для того что бы разобрать лог-файл fail2ban, я написал парсер Fail2Ban.py:
###
import time
import re
import os.path
from logster.logster_helper import MetricObject, LogsterParser
from logster.logster_helper import LogsterParsingException
class Fail2Ban(LogsterParser):
def __init__(self, option_string=None):
'''Initialize any data structures or variables needed for keeping track
of the tasty bits we find in the log we are parsing.'''
self.statsban = 0
self.statsunban = 0
self.reg = re.compile('.*(?P<ban>(Ban|Unban)).*')
def parse_line(self, line):
'''This function should digest the contents of one line at a time, updating
object's state variables. Takes a single argument, the line to be parsed.'''
try:
regMatch = self.reg.match(line)
if regMatch:
linebits = regMatch.groupdict()
if (linebits['ban'] == 'Ban'):
self.statsban += 1
elif (linebits['ban'] == 'Unban'):
self.statsunban += 1
else:
raise LogsterParsingException, "regmatch failed to match"
except Exception, e:
raise LogsterParsingException, "regmatch or contents failed with '%s'" % e
def get_state(self, duration):
# Return a list of metrics objects
if os.path.isfile('/tmp/ban.txt'):
fileban = open( '/tmp/ban.txt')
oldban = int(fileban.read())
else:
oldban = 0
currentban = oldban+(self.statsban-self.statsunban)
fileban = open( '/tmp/ban.txt', 'w+' )
fileban.write(str(currentban))
fileban.close
return [
MetricObject("Ban", (self.statsban), "IP"),
MetricObject("Unban", (self.statsunban), "IP"),
MetricObject("CurrentBan", (currentban), "IP"),
]
Парсер помещаем в директорию Logster - /usr/lib/python2.7/dist-packages/logster/parsers/
И добавляем выполнение этого скрипта с интервалом в 30 сек в crontab:
* * * * * root /usr/bin/logster -o graphite -p logster --graphite-host=10.0.0.1:2003 Fail2Ban /var/log/fail2ban.log
* * * * * root (sleep 30 ; /usr/bin/logster -o graphite -p logster --graphite-host=10.0.0.1:2003 Fail2Ban /var/log/fail2ban.log)
результат направляем в graphite. В результате получаем следующий график:
Для отображения актуального числа заблокированных адресов, после первого старта необходимо установить текущее количество заблокированных в файл /tmp/ban.txt . Например так:
#iptables-save |grep fail2|grep "\-s "|wc -l > /tmp/ban.txt
Вот собственно пока и все
- Войдите или зарегистрируйтесь, чтобы оставлять комментарии