image source: www.thegeekstuff.com
Asterisk 11 introduced the security log event channel which basically throws all security (success, failure, etc) which the past full log couldn’t show. Scripts attacks like sipvicious that does scanning on your system or even tries to bombard your system with auth requests would trigger a super uber cool tool like fail2ban because the source IP is not show, such as the log entries like below;
[2013-08-13 19:05:16] NOTICE[C-000051b0] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=d6b948e3
[2013-08-13 19:05:17] NOTICE[C-000051b1] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=baeae036
[2013-08-13 19:05:18] NOTICE[C-000051b2] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=0097749c
[2013-08-13 19:05:19] NOTICE[C-000051b3] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=f2a79638
[2013-08-13 19:05:21] NOTICE[C-000051b4] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=2bc55684
[2013-08-13 19:05:22] NOTICE[C-000051b5] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=f7ba490c
NOTE: <myserverIP> has been changed by me to hide my server IP.
As you can see, the “attack” above can go on and on without fail2ban being able to do anything since the source IP is not shown in that log, sadly.
Now with Asterisk 11 and enabling with security log, you could see much more data of the similar attack/test;
[2013-09-18 02:56:20] SECURITY res_security_log.c: SecurityEvent="InvalidPassword",EventTV="1379444180-215558",Severity="Error",Service="SIP",EventVersion="2",AccountID="100",SessionID="0x9ad18cc",LocalAddress="IPV4/UDP/<myserverIP>/5060",RemoteAddress="IPV4/UDP/22.214.171.124/12495",
NOTE: <myserverIP> has been changed by me to hide my server IP.
Now, notice the similar attack with security logging channel enabled, shows the IP of the attacker highlighted in bold, as above. Now, there’s enough information for fail2ban to do “something” like ban his ass for 2000 years :)
Enough to convince you to use Asterisk 11? For me it is sufficient to put 11 as our main distribution.
If you’re convinced, and would like to use this, you would need the following
1) Asterisk 11 (with or without FreePBX)
2) Enable security channel
3) Install/use latest fail2ban or version 0.8.8
4) Setup the appropriate jail.conf and patterns
5) Auto start fail2ban after asterisk starts (important!)
In this guide i will not show you how to setup or upgrade to Asterisk 11, but there’s a blog posting here in my blog which you can already find such steps. I will start from no.2 onwards. Do note, this is designed for a Debian system, but you can use the settings herein of course to match your own operating system. To find out requirements for fail2ban, visit www.fail2ban.org, basically for this below, have iptables and python v 2.4 or higher
Enable security channel logs
- FreePBX users, the “Log File Setting” module does not support security as its option, so the only way is to edit the file /etc/asterisk/logger_logfiles_custom.conf. By default, the “messages” channel is also not created in FreePBX, so now when you want to take advantage of fail2ban enable it. Add the following lines for FreePBX users
messages => security,notice,warning,error
- If you’re not using freepbx, simply add that above line in logger.conf under [logfiles] section
- Reload the logger
#asterisk –rx “logger reload”
- Now, check if the messages log is populated, in my installation log files are in /var/log/asterisk/
#tail –f /var/log/asterisk/messages
- If you see entries with “SECURITY” as the event type, then it works great, proceed to next step
Install/use/upgrade/configure/autostart to latest fail2ban
The apt repo for fail2ban is only at version 0.6.X which does not have some cool features like single host unbanning. Install fail2ban with dpkg first, then do the source file way of upgrading
- #wget http://ftp.us.debian.org/debian/pool/main/f/fail2ban/fail2ban_0.8.6-3wheezy1_all.deb
- #dpkg -i fail2ban_0.8.6-3wheezy1_all.deb
This will properly populate all files including the init.d files for you
- Now, we perform the upgrade
- #wget http://www.astiostech.com/asterisk-installer/astbin/current/fail2ban_0.8.8.orig.tar.gz
- #tar –zxvf fail2ban_0.8.8.orig.tar.gz
- #cd fail2ban && python setup.py install
- Now, lets start editing the important files, be sure to copy paste correctly
- #cd /etc/fail2ban
- #cp jail.conf jail.original.conf
- #nano jail.conf
Be sure to edit the dest email, this action triggers iptables-apports meaning ban the source address from all ports for 259200 seconds after 6 attempts. Modify as you wish. An email with WHOIS information will be sent to the email address specified. Notice we are checking the /var/log/asterisk/messages as defined above for the event triggers as seen in item 15 asterisk.conf below.
Add the following codes into jail.conf at the end
enabled = true
filter = asterisk
action = iptables-allports[name=ASTERISK, protocol=all]
# Modify and uncomment below to send email, make sure exim4 has been reconfigured
mail-whois[name=ASTERISK, email@example.com, firstname.lastname@example.org]
logpath = /var/log/asterisk/messages
maxretry = 6
bantime = 259200
- Inside jail.conf, there’s a option called ignoreip = 127.0.0.1, you can add more IPs which you want to whitelist there. "ignoreip" can be an IP address, a CIDR mask or a DNS host separated by a space for each entry.
- Now, we edit the filter, this is where we take advantage of the security log, see the final few entries which has the option for security log based log entries as well.
- #cd /etc/fail2ban/filter.d/
- #cp asterisk.conf asterisk.original.conf
- #nano asterisk.conf
Copy and paste exactly like shown below, remember, everything here must be in a single line even if it doesn’t show it that way in the blog. Change where you see fit, do note, if you don’t know what you’re doing, don’t change it.
# Fail2Ban configuration file
# Author: Xavier Devlamynck
# Read common prefixes. If any customizations available -- read them from
before = common.conf
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT
log_prefix= \[\]\s*(?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[\S+\d*\])? \S+:\d*
failregex = ^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Wrong password$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - No matching peer found$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Username/auth name mismatch$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Device does not match ACL$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Peer is not supposed to register$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - ACL error \(permit/deny\)$
^%(log_prefix)s Registration from '[^']*' failed for '<HOST>(:\d+)?' - Not a local domain$
^%(log_prefix)s Call from '[^']*' \(<HOST>:\d+\) to extension '\d+' rejected because extension not found in context 'default'\.$
^%(log_prefix)s Host <HOST> failed to authenticate as '[^']*'$
^%(log_prefix)s No registration for peer '[^']*' \(from <HOST>\)$
^%(log_prefix)s Host <HOST> failed MD5 authentication for '[^']*' \([^)]+\)$
^%(log_prefix)s Failed to authenticate (user|device) [^@]+@<HOST>\S*$
^%(log_prefix)s (?:handle_request_subscribe: )?Sending fake auth rejection for (device|user) \d*<sip:[^@]+@<HOST>>;tag=\w+\S*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
- And that’s it, it will now be able to detect almost any kind of security related events. If you know how to edit regexes, this will be a super security Swiss army knife for you.
- Now, start/restart fail2ban
- Checkout if fail2ban is running / not
#iptables –L –vn
You should see the fail2ban-asterisk somewhere at the end of IPTABLES chains definitions
- Now, before you do this test below, be sure you’ve got a way to access your server when it does get banned
- Do a sipvicious scan on your server and after 6 lame attempts, you get banned! [or not, if this above is not configured properly]