Подробнее о TCP wrappers я писать не буду, ибо желающие могут прочитать о них в FreeBSD handbook. Хочу лишь сказать о причинах, побудивших меня использовать именно этот механизм ограничения доступа к интернет-сервисам.
Не секрет, что во многих случаях серверы обслуживающие те или иные службы интернет находятся за роутерами с поднятыми на последних firewall'ами и NAT. При таком раскладе часто нет нужды в использовании firewall непосредственно на самом сервере.
Кроме того, использование firewall непосредственно на обслуживающем интернет-сервисы сервере может быть сопряжено с дополнительным, иногда довольно существенным, использование ресурсов под обслуживание межсетевого экрана, что может негативно сказаться на производительности систем, непосредственно для функционирования которых данный сервер и предназначается.
Однако, отказ от использования firewall на самом сервере ставит вопрос о способе ограничения доступа к сервисам в случае борьбы с попытками взлома и т.п. В частности, этот вопрос возник у меня при настройке многим хорошо знакомого fail2ban.
И тут я вспомнил про уже упомянутые выше TCP wrappers. Оказалось, что имеющийся там механизм ограничения доступа поддерживается всеми используемыми мною интернет-сервисами и может быть вполне успешно использован в искомых целях.
Итак, у меня имеются и доступны их внешнего мира FTP (стандартный ftpd), SSH (стандартный sshd), SMTP (exim) и POP3/IMAP4 (dovecot), которые регулярно испытывают всевозможные виды bruteforce - атак.
Для борьбы с ними используется fail2ban.
Останавливаться на его установке я не буду, равно как и не буду подробно расписывать все детали начальной настройки.
Приведу лишь работающие (и отлично работающие) конфиги, на отладку и правку которых я потратил некоторое время.
Интересные моменты будут откоментированы ниже.
Важное замечание. Для использования TCP wrappers совместно с Exim и Dovecot они должны быть откомпилированы с одноимённой опцией.
Ввиду малой нагрузки sshd и ftpd у меня запускаются через inetd, а Exim и Dovecot независимо от него.
Итак, во-первых. Все модификации штатных конфигов fail2ban делались, как это и рекомендуется в мануале по нему, в их копиях с расширениями .local
Вот их список:
Код: Выделить всё
root@beta:/ # cd /usr/local/etc/fail2ban/
root@beta:/usr/local/etc/fail2ban # ll *.local
-rw-r--r-- 1 root wheel 1525 7 дек 16:11 fail2ban.local
-rw-r--r-- 1 root wheel 1671 11 дек 11:32 jail.local
root@beta:/usr/local/etc/fail2ban # ll action.d/*.local
-rw-r--r-- 1 root wheel 1303 7 дек 20:13 action.d/hostsdeny.local
-rw-r--r-- 1 root wheel 1680 22 окт 13:44 action.d/sendmail-whois-lines.local
-rw-r--r-- 1 root wheel 1488 21 окт 09:37 action.d/sendmail-whois.local
root@beta:/usr/local/etc/fail2ban # ll filter.d/*.local
-rw-r--r-- 1 root wheel 1603 7 дек 16:59 filter.d/bsd-sshd.local
-rw-r--r-- 1 root wheel 1119 7 дек 15:11 filter.d/bsdftp.local
-rw-r--r-- 1 root wheel 583 7 дек 20:03 filter.d/dovecot.local
-rw-r--r-- 1 root wheel 208 11 дек 19:16 filter.d/exim-spam.local
-rw-r--r-- 1 root wheel 638 11 дек 12:29 filter.d/exim.local
-rw-r--r-- 1 root wheel 1546 22 окт 13:43 filter.d/recidive.local
Самый главный тут файл hostdeny.local, поэтому с него и начнём.
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat action.d/hostsdeny.local | grep -v #
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = IP=<ip> && SRV=<srv> &&
mv <file> <file>.tmp &&
printf %%b "$SRV: $IP: deny\n" > <file> &&
cat <file>.tmp >> <file> &&
chmod 644 <file>
actionunban = IP=<ip> && SRV=<srv> &&
sed /$SRV:\ $IP:\ deny/d <file> > <file>.tmp &&
mv <file>.tmp <file> &&
chmod 644 <file>
[Init]
file = /etc/hosts.allow
Условия будут вставляться в начало файла hosts.allow, который используется в FreeBSD как для разрешения, так и для запрещения доступа. Важно вставлять их именно в начало, поскольку последним условием в данном случае, как правило, идёт разрешающее всем доступ ко всему
Код: Выделить всё
all: all: allow
Таким образом, ограничения должны быть описаны до него.
Общие настройки fail2ban - здесь всё стандартно.
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat fail2ban.local | grep -v #
[Definition]
loglevel = 3
logtarget = /var/log/fail2ban.log
socket = /var/run/fail2ban/fail2ban.sock
pidfile = /var/run/fail2ban/fail2ban.pid
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat jail.local | grep -v #
[DEFAULT]
ignoreip = 127.0.0.1/8
backend = auto
usedns = yes
[ssh-tcpwrapper]
enabled = true
filter = bsd-sshd
action = hostsdeny[srv="sshd"]
sendmail-whois[name=ssh, dest=root@host.ru]
ignoreregex = for myuser from
logpath = /var/log/auth.log
bantime = 3600 ; 1 hour
findtime = 180 ; 3 min
maxretry = 5
[ftp-tcpwrapper]
enabled = true
filter = bsdftp
action = hostsdeny[srv="ftpd"]
sendmail-whois[name=ftp, dest=root@host.ru]
logpath = /var/log/auth.log
bantime = 3600 ; 1 hour
findtime = 180 ; 3 min
maxretry = 5
[dovecot-tcpwrapper]
enabled = true
filter = dovecot
action = hostsdeny[srv="pop3,imap,pop3s,imaps"]
sendmail-whois[name=dovecot, dest=root@host.ru]
logpath = /var/log/maillog
bantime = 3600 ; 1 hour
findtime = 180 ; 3 min
maxretry = 5
[exim-tcpwrapper]
enabled = true
filter = exim
action = hostsdeny[srv="exim"]
sendmail-whois[name=exim, dest=root@host.ru]
logpath = /var/log/maillog
bantime = 3600 ; 1 hour
findtime = 600 ; 10 min
maxretry = 5
[spam-tcpwrapper]
enabled = true
filter = exim-spam
action = hostsdeny[srv="exim"]
sendmail-whois[name=spam, dest=root@host.ru]
logpath = /var/log/maillog
bantime = 10800 ; 3 hours
findtime = 900 ; 15 min
maxretry = 3
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
action = hostsdeny[srv="all"]
sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log]
bantime = 604800 ; 1 week
findtime = 86400 ; 1 day
maxretry = 3
jail [recidive] использован для явно злонамеренных хостов, которых не вразумили два предыдущих краткосрочных бана.
Если нет нужды получать оповещения о банах по e-mail, то из перечисления action можно исключить строки, которые начинаются с sendmail-
Ну и самое интересное - фильтры. Стандартные фильтры fail2ban пришлось местами изрядно обработать напильником.
Поехали.
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/bsd-sshd.local | grep -v #
[INCLUDES]
before = common.conf
[Definition]
_daemon = sshd
failregex = ^%(__prefix_line)s(?:error: PAM: )?[A|a]uthentication (?:failure|error) for .* from <HOST>\s*$
^%(__prefix_line)sDid not receive identification string from <HOST>$
^%(__prefix_line)sFailed [-/\w]+ for .* from <HOST>(?: port \d*)?(?: ssh\d*)?$
^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
^%(__prefix_line)sUser \S+ from <HOST> not allowed because not listed in AllowUsers$
^%(__prefix_line)sauthentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
^%(__prefix_line)sreverse mapping checking getaddrinfo for .* \[<HOST>\] .* POSSIBLE BREAK-IN ATTEMPT!$
^%(__prefix_line)sReceived disconnect from <HOST>: 11: Bye Bye \[preauth\]\s*$
ignoreregex =
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/bsdftp.local | grep -v #
[INCLUDES]
before = common.conf
[Definition]
_daemon = ftpd
failregex = ^%(__prefix_line)sFTP LOGIN (?:FAILED|REFUSED) FROM <HOST>,\s*.*$
ignoreregex =
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/dovecot.local | grep -v #
[INCLUDES]
before = common.conf
[Definition]
failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=(?P<host>\S*),.*
ignoreregex =
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/exim.local | grep -v #
[INCLUDES]
[Definition]
failregex = \[<HOST>\] (I=\[\S+\]:\d+) sender verify fail for <\S+>: (?:Unknown user|Unrouteable address|all relevant MX records point to non-existent hosts)
(?:dovecot_login|plain|login) authenticator failed for (\S+ )?\(\S+\) \[<HOST>\] (I=\[\S+\]:\d+): 535 Incorrect authentication data
\[<HOST>\] (I=\[\S+\]:\d+) F=(<>|[^@]+@\S+) rejected RCPT [^@]+@\S+: (relay not permitted|Sender verify failed|Unknown user|Unrouteable address)
ignoreregex =
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/exim-spam.local | grep -v #
[INCLUDES]
[Definition]
failregex = \[<HOST>\](:\d+)? (I=\[\S+\]:\d+)? (P=e?(smtp|smtps)) temporarily rejected by local_scan\(\):
ignoreregex =
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat filter.d/recidive.local | grep -v #
[Definition]
_jailname = recidive
failregex = fail2ban.actions:\s+WARNING\s+\[(?:.*)\]\s+Ban\s+<HOST>
ignoreregex = fail2ban.actions:\s+WARNING\s+\[%(_jailname)s\]\s+Ban\s+<HOST>
Ну и actions для отправки почтовых уведомлений. Можно было не стандартные.
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat action.d/sendmail-whois.local | grep -v #
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here are more information about <ip>:\n
`/usr/bin/whois <ip>`\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
actionunban =
[Init]
name = default
dest = root
sender = fail2ban
Код: Выделить всё
root@beta:/usr/local/etc/fail2ban # cat action.d/sendmail-whois-lines.local | grep -v #
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip>
Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"`
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here are more information about <ip>:\n
`/usr/bin/whois <ip>`\n\n
Lines containing IP:<ip> in <logpath>\n
`grep '\<<ip>\>' <logpath>`\n\n
Regards,\n
Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
actionunban =
[Init]
name = default
dest = root
sender = fail2ban
logpath = /dev/null
Всё работает, враги ловятся. И никаких firewall'ов!
Enjoy it!