Asterisk + Fail2Ban
Установим требуемые пакеты
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm &&
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm &&
rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm
yum install fail2ban
yum install phyton iptables
Создадим правила фильтрации
touch /etc/fail2ban/filter.d/asterisk.conf
# Fail2Ban configuration file
#
#
# $Revision: 250 $
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
#before = common.conf
[Definition]
#_daemon = asterisk
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Wrong password
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL
NOTICE.* <HOST> failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' \(from <HOST>\)
NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)
NOTICE.* .*: Failed to authenticate user .*@<HOST>.*
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
Синтаксис для Asterisk 1.6 отличается отсутствием номера порта '<HOST>'
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Wrong password
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Device does not match ACL
NOTICE.* <HOST> failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' \(from <HOST>\)
NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)
NOTICE.* .*: Failed to authenticate user .*@<HOST>.*
Fail2ban содержит правила и фильтры для Asterisk по умолчанию
/etc/fail2ban/filter.d/asterisk.conf
# Fail2Ban filter for asterisk authentication failures
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = asterisk
__pid_re = (?:\[\d+\])
# All Asterisk log messages begin like this:
log_prefix= (?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[C-[\da-f]*\])? \S+:\d*( in \w+:)?
failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - (Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not su$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d*",SessionID="$
^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )Ext\. s: "Rejecting unknown SIP connection from <HOST>"$
ignoreregex =
# Author: Xavier Devlamynck / Daniel Black
#
# General log format - main/logger.c:ast_log
# Address format - ast_sockaddr_stringify
#
# First regex: channels/chan_sip.c
#
# main/logger.c:ast_log_vsyslog - "in {functionname}:" only occurs in syslog
Fail2ban PjSIP
# Fail2Ban filter for asterisk authentication failures
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
_daemon = asterisk
__pid_re = (?:\[\d+\])
# All Asterisk log messages begin like this:
log_prefix= (?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[C-[\da-f]*\])? \S+:\d*( in \w+:)?
failregex = ^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - (Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not supposed to register|ACL error \(permit/deny\)|Not a local domain)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s SecurityEvent="(FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)",EventTV="[\d-]+",Severity="[\w]+",Service="[\w]+",EventVersion="\d+",AccountID="\d*",SessionID="0x[\da-f]+",LocalAddress="IPV[46]/(UD|TC)P/[\da-fA-F:.]+/\d+",RemoteAddress="IPV[46]/(UD|TC)P/<HOST>/\d+"(,Challenge="\w+",ReceivedChallenge="\w+")?(,ReceivedHash="[\da-f]+")?(,ACLName="\w+")?$
^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )Ext\. s: "Rejecting unknown SIP connection from <HOST>"$
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Request from '.*' failed for '<HOST>(:[0-9]{1,5})?' (.*) - (No matching endpoint found)$
ignoreregex =
# Author: Xavier Devlamynck / Daniel Black
#
# General log format - main/logger.c:ast_log
# Address format - ast_sockaddr_stringify
#
# First regex: channels/chan_sip.c
#
# main/logger.c:ast_log_vsyslog - "in {functionname}:" only occurs in syslog
Регулярное выражение (RegEx) fail2ban, Asterisk 12 или 13, для сообщений от драйвера chan_pjsip
^(%(__prefix_line)s|\[\]\s*)%(log_prefix)s Request from '.*' failed for '<HOST>(:[0-9]{1,5})?' (.*) - (No matching endpoint found)$
/etc/fail2ban/jail.conf
[asterisk]
enabled = true
filter = asterisk
action = iptables-multiport[name=asterisk-tcp, port="5060,5061", protocol=tcp]
iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp]
sendmail-whois[name=Asterisk, dest=root@localhost, sender=fail2ban@localhost]
logpath = /var/log/asterisk/messages
maxretry = 3
bantime = 259200
Или jail.local
[asterisk-iptables]
enabled = true
filter = asterisk
action = iptables-allports[name=SIP, protocol=all]
sendmail[name=SIP, dest=root@localhost, sender=root@localhost]
logpath = /var/log/asterisk/messages
maxretry = 5
bantime = 1800
<spoiler|устаревшее>
Добавим в файл jail.conf
/etc/fail2ban/jail.conf
[asterisk-iptables]
enabled = true
filter = asterisk
action = iptables-allports[name=ASTERISK, protocol=all]
sendmail-whois[name=ASTERISK, dest=root, sender=fail2ban@asterisk]
logpath = /var/log/asterisk/messages
maxretry = 3
bantime = 259200
</spoiler>
Создадим отдельный лог для fail2ban
/etc/asterisk/logger_logfiles_custom.conf
messages => notice,warning,error
# asterisk -rx "logger rotate"
Cтартуем
/etc/init.d/fail2ban start
/etc/init.d/iptables start
если все в порядке
chkconfig iptables on
chkconfig fail2ban on
Посылаем некорректные запросы на авторизацию
sipsak -U -s sip:s@192.168.0.1:5060
sipsak -U -s sip:s@192.168.0.1:5060
sipsak -U -s sip:s@192.168.0.1:5060
Смотрим iptables
iptables -L
Chain fail2ban-ASTERISK (1 references)
target prot opt source destination
DROP all -- 192.168.0.22 anywhere
RETURN all -- anywhere anywhere
Смотрим статус fail2ban
fail2ban-client status asterisk-iptables
Status for the jail: asterisk-iptables
|- filter
| |- File list: /var/log/asterisk/secure
| |- Currently failed: 0
| `- Total failed: 3
`- action
|- Currently banned: 1
| `- IP list: 192.168.0.22
`- Total banned: 1
удалить правило из iptables
iptables -D fail2ban-ASTERISK 1
дополнительно
Блокировка пакетов средствами IPtables по названию сканера
iptables -I INPUT -p udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP
iptables -I INPUT -p udp --dport 5060 -m string --string "sip-scan" --algo bm -j DROP
iptables -I INPUT -p udp --dport 5060 -m string --string "sundayddr" --algo bm -j DROP
iptables -I INPUT -p udp --dport 5060 -m string --string "iWar" --algo bm -j DROP
iptables -I INPUT -p udp --dport 5060 -m string --string "sipsak" --algo bm -j DROP
iptables -I INPUT -p udp --dport 5060 -m string --string "sipvicious" --algo bm -j DROP
Chain fail2ban-asterisk-udp (1 references)
target prot opt source destination
REJECT all -- ns304512.ip-94-23-212.eu anywhere reject-with icmp-port-unreachable
REJECT all -- 69.30.254.10 anywhere reject-with icmp-port-unreachable
REJECT all -- 178.32.131.44 anywhere reject-with icmp-port-unreachable
REJECT all -- s18080713.onlinehome-server.info anywhere reject-with icmp-port-unreachable
REJECT all -- 192.187.109.154 anywhere reject-with icmp-port-unreachable
REJECT all -- 46.165.251.197 anywhere reject-with icmp-port-unreachable
REJECT all -- 212-129-55-216.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable
REJECT all -- static-ip-188-138-120-135.inaddr.ip-pool.com anywhere reject-with icmp-port-unreachable
REJECT all -- s18081076.onlinehome-server.info anywhere reject-with icmp-port-unreachable
REJECT all -- 212-129-54-198.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable
REJECT all -- 62-210-148-71.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable
REJECT all -- 195-154-34-157.rev.poneytelecom.eu anywhere reject-with icmp-port-unreachable
REJECT all -- 107.150.61.186 anywhere reject-with icmp-port-unreachable
REJECT all -- h31-3-236-162.host.redstation.co.uk anywhere reject-with icmp-port-unreachable
REJECT all -- 107.150.52.234 anywhere reject-with icmp-port-unreachable
REJECT all -- 95.211.117.10 anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere
Нажмите, чтобы отобразить
Fail2Ban:
This is a pretty simple implementation, and can be done quickly. I have already setup an email relay on my Asterisk box to email me, so you may need to do that before hand or modify the settings slightly. I really enjoy being able to know by email what bad things are happening.
First, modify Asterisk to spit out errors in a separate log file:
Edit /etc/asterisk/logger.conf and:
– Un-comment the first dateformat line under [general]:
1
dateformat=%F %T ; ISO 8601 date format
– Then, modify the messages line near the bottom and add security:
1
messages => security,notice,warning,error
Restart the Asterisk logger module to make the changes take effect:
sudo asterisk -rx "logger reload"
Now, install fail2ban:
sudo apt-get -y install fail2ban
Add the folowing to the end of /etc/fail2ban/jail.conf:
[asterisk-iptables]
# if more than 4 attempts are made within 6 hours, ban for 24 hours
enabled = true
filter = asterisk
action = iptables-allports[name=ASTERISK, protocol=all]
sendmail[name=ASTERISK, dest=dest@email.here, sender=fail2ban@address.here]
logpath = /var/log/asterisk/security
maxretry = 4
findtime = 21600
bantime = 86400
Then, move the existing asterisk.conf in filter.d to a backup in the directory below (or wherever else you would like):
cd /etc/fail2ban/filter.d
sudo mv asterisk.conf ../asterisk.conf.orig
Create a new asterisk.conf in filter.d and add the following:
# Fail2Ban configuration file
#
#
# $Revision: 251 $
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
#_daemon = asterisk
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
# Asterisk 1.8 uses Host:Port format which is reflected here
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Wrong password
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Peer is not supposed to register
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - ACL error (permit/deny)
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL
NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - Wrong password
NOTICE.* <HOST> failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' \(from <HOST>\)
NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)
NOTICE.* .*: Failed to authenticate user .*@<HOST>.*
NOTICE.* .*: <HOST> failed to authenticate as '.*'
NOTICE.* .*: <HOST> tried to authenticate with nonexistent user '.*'
VERBOSE.*SIP/<HOST>-.*Received incoming SIP connection from unknown peer
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
Restart fail2ban:
1
sudo service fail2ban restart