Thursday, September 19, 2013

Upgrade to Asterisk 11 and fail2ban 0.8.8 to protect Asterisk like never before, here’s why and how.

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[4027][C-000051b0] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=d6b948e3
[2013-08-13 19:05:17] NOTICE[4027][C-000051b1] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=baeae036
[2013-08-13 19:05:18] NOTICE[4027][C-000051b2] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=0097749c
[2013-08-13 19:05:19] NOTICE[4027][C-000051b3] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=f2a79638
[2013-08-13 19:05:21] NOTICE[4027][C-000051b4] chan_sip.c: Failed to authenticate device 100<sip:100@<myserverIP>>;tag=2bc55684
[2013-08-13 19:05:22] NOTICE[4027][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[8324] 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/37.8.42.146/12495",
Challenge="642e69ae",ReceivedChallenge="642e69ae",ReceivedHash="56c74b58db0a623d5193a7afee4da7ff"

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

  1. 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
  2. If you’re not using freepbx, simply add that above line in logger.conf under [logfiles] section
  3. Reload the logger
    #asterisk –rx “logger reload”
  4. Now, check if the messages log is populated, in my installation log files are in /var/log/asterisk/
    #tail –f /var/log/asterisk/messages
  5. 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

  1. #wget http://ftp.us.debian.org/debian/pool/main/f/fail2ban/fail2ban_0.8.6-3wheezy1_all.deb
  2. #dpkg -i fail2ban_0.8.6-3wheezy1_all.deb
    This will properly populate all files including the init.d files for you
  3. Now, we perform the upgrade
  4. #wget http://www.astiostech.com/asterisk-installer/astbin/current/fail2ban_0.8.8.orig.tar.gz
  5. #tar –zxvf fail2ban_0.8.8.orig.tar.gz
  6. #cd fail2ban && python setup.py install
  7. Now, lets start editing the important files, be sure to copy paste correctly
  8. #cd /etc/fail2ban
  9. #cp jail.conf jail.original.conf
  10. #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

    ##start##
    [asterisk-iptables]

    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, dest=support@astiostech.com, sender=root@asterisk.localhost]
    logpath  = /var/log/asterisk/messages
    maxretry = 6
    bantime = 259200

    ##end##

  11. 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.
  12. 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.
  13. #cd /etc/fail2ban/filter.d/
  14. #cp asterisk.conf asterisk.original.conf
  15. #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.

    ##start##

    # Fail2Ban configuration file
    # Author: Xavier Devlamynck

    [INCLUDES]

    # Read common prefixes. If any customizations available -- read them from
    # common.local
    before = common.conf

    [Definition]

    # 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*$
                ^%(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]+")?$

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

    ##end##

  16. 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.
  17. Now, start/restart fail2ban
    #/etc/init.d/fail2ban restart
  18. Checkout if fail2ban is running / not
    #iptables –L –vn
    You should see the fail2ban-asterisk somewhere at the end of IPTABLES chains definitions
  19. Now, before you do this test below, be sure you’ve got a way to access your server when it does get banned
  20. Do a sipvicious scan on your server and after 6 lame attempts, you get banned! [or not, if this above is not configured properly]

9 comments:

Cjsdfw said...

Hi Sanjay, can you shed some lighth in the use of '%' sign in the regex'es?

log_prefix= \[\]\s*(?:NOTICE|SECURITY)%(__pid_re)s:?(?:\[\S+\d*\])? \S+:\d*

I'm really naive about Regex and Python but I have search all over google to no avail.

Thanks

Anonymous said...

Hi Sanjay,

I have followed your instructions to the letter. Once I got to the fail2ban restart step, it failed to restart. I changed the .conf files back to the way they were and fail2ban still will not restart. I will say the weezy1 version of fail2ban was not available at the link provided so I used the same version but weezy2 file which was available. Please advise what steps can be taken to fix my broken system. Thanks.

Anonymous said...

Hi Sanjay,

I have followed your step by step instructions to the letter. However, once I got to the fail2ban restart step, the service failed to restart. I changed the .conf files back to the way they were and still it failed to restart.

There was one problem with the files. The fail2ban version was not available at weezy1 but weezy2 was. I used that file.

Please advise how to fix this broken system.

Thanks.

Phillip Ford

Emmdee said...

Fail2ban is ok but generally not recommended as a real intrusion detection/prevention tool (see http://forums.asterisk.org/viewtopic.php?p=159984). I use the free version of SecAst (www.generationd.com) and its like a super fail2ban...

MR VOIP said...

Hi - test with one regex. Simplify it and run the fail2ban-regex command over your new simplified test regex.

I wrote a quick blog post on a suggestion how I would go about doing it.

This is the URL http://www.mrvoip.com.au/blog/updated-fail2ban-and-asterisk

HTH
Cheers

flydr2 said...

This works as described... Even banned my cell phone sip client.

The problem is unbanning. I wish I knew which file as the banned IP's

It would be much easier than ssh...

flydr2 said...

This works very well.

I got my cell phone sip banned.
The problem is unbanning... I wish I knew the file location which holds the banned IP's

JayWS said...

it is banned using iptables,

simply run
#iptables -L -vn

to unban
#fail2ban-client set asterisk-iptables unbanip [ip-address]

flydr2 said...

Thanks.
Where are the banned IP stored? Which file holds them?

Also is there a way to permanently ban an IP range... lets say I want to ban everything that starts with 198.23.x.x

I've tried adding to the /etc/sysconfig/iptables a line like this -A INPUT -s 198.23.0.0/24 -j DROP
but it's not doing it.

I still have lots to learn.
Cheers
Marco