fail2ban is a tool to stop simple bruteforce attacks by banning IPs that repeatedly try to login or perform an unwanted action that we can catch in log files.

I've been trying to setup a jail + filter for fail2ban to block IPs that were abusing of an Asterisk server. I took the examples on the fail2ban wiki and on voip-info.org, and both were wrong.

I corrected the multiple problems with the examples and now it's working well with Asterisk 1.8.

Here's the jail definition (put that in /etc/fail2ban/jail.local):

[asterisk]
enabled  = true
filter   = asterisk
port     = iax,sip,sip-tls
protocol = all
logpath  = /var/log/asterisk/messages
maxretry = 5

And here's the filter (put that in /etc/fail2ban/filter.d/asterisk.conf):

# Derived from example at http://www.voip-info.org/wiki/view/Fail2Ban+%28with+iptables%29+And+Asterisk

[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>:.*' - 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.* .*: Registration from '.*' failed for '<HOST>:.*' - Peer is not supposed to register
            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.* .*: Call from '.*' \(<HOST>:.*\) to extension '.*' rejected because extension not found in context '.*'\.

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

The modifications I made are the following:

  • For the jail, they were using the "iptables-allports" action, but there was an argument to the action that was missing, the chain name. I actually took the action out entirely and instead configured specific ports to block with the default action iptables-multiport. I've also watered down the bantime from 3 days to the default of 10mins.

  • The filter wasn't matching anything. The reason for that is that hosts were followed by the portname in my log files and the regexes weren't considering this.

  • I also added a regex to ban excessive tries at invalid extensions, since we've had ppl trying to bruteforce extensions on the system. There may be better ways to do that like permitting with the firewall only connections from your known peers, but in my case peers could actually move around so this solution is impracticable.