Friday, November 22, 2013

A new kind of old phones hacking way

Image source:

After analysing some logs we got, it was obvious that the calls that had been made were successful attempts in placing calls to expensive and exotic numbers, and the biggest one was Sierra Leone. one of the most common places these thieves dial.

What was involved:

1) Two PaBXes, one PBX A and the other was Asterisk running FreePBX

2) TollFree number, e.g. 1800XX

Please note, this attempt was NOT via SIP (or hacked extensions) but pure PSTN and therefore can happen to anyone who connects to an Asterisk box or for that matter any kind of PaBX.


What happened?


  1. Thief dials tollfree 1800XX for example and realises there are a full PaBX in there
  2. Received by PBX A which just forwards to PBX B
  3. PBX B creates a forwarding number (via follow-me) to a queue. Because of this, the context which this user rides on is “from-internal”, therefore changing the entire context of “from-trunk” to “from-internal” or commonly known as the “ALLOW ANY” rule
  4. Then while reaching the destination of the forward, (upon answer or ring), the caller does a blind transfer in Asterisk/FreePBX by dialing ##
  5. Dials a new destination, therefore the arbitrary user created, e.g. 1000 is the source and whatever destination the thief dials is the destination.

Notes about this attack

  • Thief dials to 1800XX few hundreds of times wanting to do reconnaissance over which equipment you use
  • Once they find out, they will go up and research about the equipment you use, in this particular case it was Asterisk/FreePBX
  • They then attempts the call as per the flow chart above and successfully make calls


What you should know about this method

  1. It is do-able on any Asterisk/FreePBX if you have a forwarded context that’s not secure, e.g. from-internal or any kind of follow-me done on extensions or a particular extension itself, inheriting that extension’s context
  2. It is normally done with TollFree numbers so the attempts and calling from the thief for actual calls or reconnaissance is free for them


What should you do? – And make this a habit when deploying any Asterisk/FreePBX solution for your customers!

  1. Block international calls to exotic numbers (i have a list of numbers of very commonly used numbers for these kind of hacks and also very expensive calling routes)
  2. Change the from-internal-xfer context restricting it to calling internal extensions only
  3. Enable pin based dialling for International calls on your Outbound Routes
  4. Monitor international calls, always
  5. Inform your telco to monitor your calls and put a cap on the maximum amount of calls that can be made by you

Saturday, November 16, 2013

FreePBX/Asterisk – Per User Pin Set for the poor man

Firstly, FreePBX’s PRO module does this in such elegance Do support the FreePBX team and make the purchase and keep those devs motivated :-). Thank you for helping!


This article describes step by step to do a poor man’s PINSET per user/extension in FreePBX. Why? Cause users keep sharing pinsets and no one takes responsibility on its usage.

It may not be the prettiest way of doing things, but it sure does the job :-)


What do you need to use this, more info etc..

  1. FreePBX 2.8 /Asterisk 1.8 or higher (may work for lower versions)
  2. If using FreePBX 2.10 or higher, there’s a setting to bypass pin (pinless dialing), this guide/hack “supports”. Meaning if you enable pinless, you won’t need a pin.
  3. This method hacks the freepbx generated configs using the _override_ file, so be sure to know what is the repercussion of hacking this, e.g. you will lose some configs made in the GUI (except for record in CDR value)
  4. If using Record in CDR, this method honours this request and records it in Account Code column inside asteriskcdrdb
  5. If using the pinset number n in which we defined custom pinsets, it will go through the custom method (per user), otherwise, it will use back the pinsets generated in the PinSet module in FreePBX Gui and work per normal pinset module. Therefore, not affecting other PINsets that you’ve been doing/using.
  6. If a particular user does not have voicemail or you do not want voicemail for that extension, this method will not work. All you got to do is be creative and use another location/method to read
  7. Why i use voicemail password? Simple, cause its user manageable through Asterisk Recording Interface (freepbx gui) or voicemailmain app on Asterisk (when you dial *97)


Ok here are the steps:

  1. Create “USER-PINSET” in the Pin Set module, in FreePBX, optionally put the bla bla “Uses our…”
  2. NOTE: You can select to Record in CDR or not, this will be honoured in this custom per use pinset way
  3. When pinsets are created, it will be in placed in a chronological order which it was created, so if you created this particular pinset as the 3rd one, remember that order/number, we will use it later. In my example, this is my first ever created pinset, so it has the chronological order of 1.
  4. The second that i created (AA-Second) will be no 2 and so on …
  5. Now, create a file in /var/lib/asterisk/agi-bin/, paste the following content in there;
  6. Change the location of vmconfloc if needed. Most cases you don’t have to.

    while test -n "$1"; do
        case "$1" in
    if [[ "$ext" == "" ]]; then
        echo "ERR" | tr -d '\n' | tr -d ' '
        exit 1
    #Get pin stored in conf file
    mypin=`cat $vmconfloc | grep $ext | cut -d '>' -f2 | cut -d , -f1 | tr -d " " | tr -d "\n"`
    if [[ "$mypin" == "" ]]; then
        echo "ERR" | tr -d '\n' | tr -d ' '
        exit 1
        echo "$mypin" | tr '\n' ' ' | tr -d ' '
        exit 0
    exit 2

  7. Make the file executable and make asterisk user own it, in my case asterisk user/group is asterisk
    #chmod +x /var/lib/asterisk/agi-bin/
    #chown asterisk:asterisk /var/lib/asterisk/agi-bin/
  8. The above script reads the voicemail configuration file, which normally is located in /etc/asterisk/voicemail.conf. It does read only, doesn’t write anything so no special permissions required. If this file don’t exist, it means no user has voicemail enabled on the system.
  9. Now, edit the file /etc/asterisk/extensions_override_freepbx.conf and paste the content/context below in it, somewhere
  10. Define which order this special “USER-PINSET” was created, in my case its the first pinset, therefore, its 1, see bold text below

    include => macro-pinsets-custom
    exten => s,1,NoOp(Starting custom PINSETS)
    exten => s,n,Set(MYCUSTOMPIN=1)
    exten => s,n,GotoIf($["${MYCUSTOMPIN}" = "${ARG1}"]?mypinset,1)
    exten => s,n,GotoIf(${ARG2} = 1?cdr,1)
    exten => s,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?Authenticate(/etc/asterisk/pinset_${ARG1}))
    exten => s,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?ResetCDR())
    exten => cdr,1,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?Authenticate(/etc/asterisk/pinset_${ARG1},a))
    exten => cdr,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?ResetCDR())
    exten => mypinset,1,NoOp(Custom Pinsets)
    exten => mypinset,n,GotoIf($["${ARG2}" = "1"]?mypinset-cdr,1)
    exten => mypinset,n,Set(MYPRIVATEPIN=${SHELL(/var/lib/asterisk/agi-bin/ -E ${AMPUSERCID})})
    exten => mypinset,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?Authenticate(${MYPRIVATEPIN}))
    exten => mypinset,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?ResetCDR())
    exten => mypinset-cdr,1,NoOp(Custom Pinsets)
    exten => mypinset-cdr,n,Set(MYPRIVATEPIN=${SHELL(/var/lib/asterisk/agi-bin/ -E ${AMPUSERCID})})
    exten => mypinset-cdr,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?Authenticate(${MYPRIVATEPIN},a))
    exten => mypinset-cdr,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]?ResetCDR())

  11. Important: The variable AMPUSERCID must contain a value otherwise this will not work, or use your own variable if you know what you’re doing. FreePBX users need not worry, this value should always be there!
  12. You can first test to see if the script is executable or not, here i am testing for user 1000, which should return the value of 9999 (her voicemail pin number)
    #/var/lib/asterisk/agi-bin/ -E 1001
  13. IMPORTANT: If there’s no voicemail password/pin defined, or there was an error or it can’t find the extension, or there’s no E value parsed, the output value ERR will be returned therefore, its impossible for a user to make that call particular call when this pinset is used. 
  14. Now, simply go edit your outbound route to use this pinset, like so;
  15. Go to a particular user’s configuration page, add/edit their vm password, like so;
  16. Click on Apply Config or reload the dialplan via CLI.
  17. And here’s how the CLI looks like when making a call…( i am using extension 1058, with a pin defined in my vm as 1012
  18. Notice the MYPRIVATEPIN=1012, yes, that was read off the voicemail.conf file
  19. And since check the “Record in CDR” flag in that pinset inside FreePBX, the authentication parses the “,a” option
  20. Putting the value in CDR allows me to run reports using the FreePBX’s CDR Report tool and filter the “Account Code” section where the Pinset used when dialling are recorded.
  21. Enjoy and as usual, do give us feedback!

Tuesday, October 15, 2013

Debian 6 Squeeze(32/64) - Asterisk 11, FreeSWITCH living under one root(f) to make SKYPE free again!

Images taken off various sources on the internet

[UPDATE 15-10-2013]

This guide was taken off various sources but it all started from the Nerd Vittles’s forum entry here and various other wonderful resources such as FS-Wiki. I do not claim any rights/credits to this. It’s all of the contributors around the world of Asterisk that helped me put together a simple guide for simple implementation. Thanks to all the great work from all these great people who made this guide possible, Ward Mundy, the work from PSU VoIP, thank you. This is just a shortcut small mod for Debian 6 (Squeeze) 32/64bit.

Ready to Skype?

(img src


Warnings/Notices and Requirements:






  • A sound card
  • Virtualised sound card (like in VMs), like below for VirtualBox (to detect audio device in VMs, you need their respective guest addons software)
  • You must be able to see an audio device when do you
    • #lspci | grep Audio
  • e.g. Virtualbox setup for virtual audio
    • NOTE: I’ve had better quality with ICHAC97 for virtual box

Optionally you could

  • Run a local asterisk (all in one soup)
  • swsterisk debian 64bit image

How it works

  • A Skype mod in FreeSWITCH called mod_skypopen load and registers Skype client connections made by the Linux Skype client which can be loaded as many times as you want (each load=1 channel) meaning you can possible have multiple channels on Skype for free

How is this different from Skype Manager/Business

  • This is not the SIP trunk service called SkypeConnect
  • It connects far faster than SkypeConnect
  • It supports multichannels for Free
  • It support all skype clients, including normal skype users or business users (created in Skype Manager)
  • This is free but should be used for testing (do not infringe any terms and conditions from Skype by using this commercially)
  • Its FREE
  • Its FREE
  • Its FREE again


  • You will need to expose your skype password in clear, so be aware of that
  • At minimum you need FreeSWITCH, Asterisk is optional, but since are Asterisk and FreePBX fanboys we make the all-in-one soup

And here are the steps!

  • You can use a bare installed Debian 64 or 32 (highly recommended to use 32 bit)
  • Add contrib into your repo
  • #nano /etc/apt/sources.list
  • At the end of each line that says main, add the word contrib like below
  • Run
  • #apt-get update 
  • #apt-get install libX11-dev subversion automake autoconf wget  libtiff4-dev libtool \
    libncurses5-dev xvfb libx11-dev libasound2-dev xfs xfonts-100dpi \
    xfonts-75dpi xfonts-scalable git-core dpkg-cross binutils-multiarch libasound2 \
    libstdc++6 libgcc1 libstdc++6 libncurses5-dev zlib1g alsa-base \
    linux-sound-base libfontenc1 libfs6 libice6 libpixman-1-0 libsm6 \
    libx11-6 libx11-data libx11-dev libxau-dev libxau6 libxaw7 libxcb1 \
    libxcb1-dev libxcursor1 libxdmcp-dev libxdmcp6 libxext6 libxfixes3 \
    libxfont1 libxi6 libxinerama1 libxkbfile1 libxmu6 libxmuu1 libxpm4 \
    libxrandr2 libxrender1 libxss1 libxt6 libxv1 x11-common pulseaudio-module-hal     \
    x11proto-core-dev x11proto-input-dev x11proto-kb-dev xauth libqt4-dbus libqt4-webkit \
    xfonts-100dpi xfonts-75dpi xfonts-encodings xfonts-scalable \
    xfonts-utils xfs xkb-data xml-core xserver-common xtrans-dev xvfb \
    libgl1-mesa-dri libcurl4-openssl-dev libjpeg62-dev pulseaudio  xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic \
    linux-headers-`uname -r` cabextract x-ttcidfont-conf
  • Select freetype when prompted
    • #dpkg-reconfigure x-ttcidfont-conf
  • #nano /etc/X11/XF86Config-4
  • Add  the following two lines
    • FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
    • FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/CID"
  • #nano /etc/X11/fs/config
  • At the end of the catalogue= add the following lines separated by commas like below (don’t forget the first comma)
    • ,/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType/,/var/lib/defoma/x-ttcidfont-conf.d/dirs/CID/
  • Restart xfs
    • # /etc/init.d/xfs restart
  • FOR 64bit SQUEEZE only, NOTE: Because you are forcing different arcs, you may get errors on your next run of #apt-get install….
  • #reboot    (strongly suggested)
  • Time to install FreeSWITCH
  • #cd /usr/src
  • #git clone git://
  • #cd freeswitch && ./ && ./configure
  • #sed -i 's/\#codecs\/mod_g729/codecs\/mod_g729/g' /usr/src/freeswitch/modules.conf
  • #sed -i 's/\#codecs\/mod_silk/codecs\/mod_silk/g' /usr/src/freeswitch/modules.conf
  • #sed -i 's/\#endpoints\/mod_skypopen/endpoints\/mod_skypopen/g' /usr/src/freeswitch/modules.conf
  • #make && make install
  • #mv /usr/local/freeswitch/conf/autoload_configs /usr/local/freeswitch/conf/autoload_configs_noload
  • #cd /usr/src/freeswitch/src/mod/endpoints/mod_skypopen/oss
  • #make clean && make &&  insmod ./skypopen.ko && mknod /dev/dsp c 14 3
  • Create a backup of the freeswitch.xml files as we will be getting our own basic configuration that does not listen to 5060 (As it will conflict with Asterisk, we will use UDP 5070) and simply throws all calls coming into FreeSWITCH to Asterisk via SIP and all calls from Asterisk to throw to mod_skypopen and into Skype VoIP cloud. If you are throwing the calls out on another Asterisk box (external box) be sure to modify the value inside the new freeswitch.xml <settings> tag to something like your local IP and/or the public (natted) IP if it is natted. Also, when the asterisk server is external, change to your external asterisk server IP address under the tag <gateways>. If you are planning to install and run Asterisk 11 on the same box, then don’t change anything there!

  • #mv /usr/local/freeswitch/conf/freeswitch.xml /usr/local/freeswitch/conf/freeswitch.xml.bak
  • #cd /usr/src
  • #mkdir fs-skypecfg
  • #cd fs-skypecfg
  • #wget
  • #tar -zxvf freeswitch.tar.gz
  • #cp ./freeswitch.xml /usr/local/freeswitch/conf/
  • #chmod +x
  • Ok, now its time to setup one or more of your Skype Accounts, simply run and follow on screen instructions. PS: If you can’t get through this below, what are you doing here mate?. WARNING! You should not get any errors! If you do, let us know report here!

  • #./
    • It will ask your skype username

    • It will ask your skype password (be sure to test logon using a normal Skype client to see can work or not!)

    • Destination –> Use as suggested

    • Channels –> How many channels you need concurrently

    • Answer few more questions and it will download Skype client 4.2

    • At the end you must see the word SUCCESS!!!

  • Be sure freeswitch run as a normal user for startime

    • #adduser --disabled-password  --quiet --system --home /usr/local/freeswitch --gecos "FreeSWITCH Voice Platform" --ingroup daemon freeswitch
    • #chown -R freeswitch:daemon /usr/local/freeswitch/
    • #chmod -R o-rwx /usr/local/freeswitch/
  • Add the init scripts for freeswitch and fsskype as fsskype single script

    • #cd /etc/init.d/
    • #wget
    • #chmod +x fsskype
    • NOTE: fsskype starts and stops freeswitch as well, so just start fsskype during startup. Also be sure that this starts right at the end

    • #update-rc.d fsskype defaults 99
  • Now, do your regular Asterisk install as described in the most basic way here, or if you are running Asterisk and FreePBX then great, proceed to enable/configure Asterisk trunk settings and allowing communications.

  • Add a SIP trunk inside FreePBX like this

    • TrunkName: FreeSWITCH-Asterisk
    • Trunk Name in peer details: freeswitch
      • username=freeswitch
      • type=user
      • trustrpid=yes
      • sendrpid=yes
      • port=5070 ;remember freeswitch sip runs on this port
      • insecure=port,invite
      • host= ; remember freeswitch only listens to localhost
      • context=from-trunk
  • Setup an inbound route. Lets say your skype username is sanjayws, then create an inbound route where the DID will then be sanjayws, e.g. like below
    • Send the incoming call to any destination of your fancy, in my case, its a conference room
  • Under Asterisk SIP settings, be sure to allow as your local network, to avoid one way audio issues or natting problems, my other network, the normal ETH0 network is 192….while the 202 is my liveIP incase i need to connect from Outside of my LAN or via my public network with NAT
  • And you’re done!, lets start fsskype

    • WARNING you should not get any errors before, while or after starting fsskype!, if you do, report here

    • DO NOTE, the more channels you have the longer the start will be, it can be very long, so chillout and don’t freak out!

    • #/etc/init.d/fsskype start
  • Now, you should see your skype username (if you’ve already added that person into your skype account, pop open as online). If you do not see it online, its likely that you’ve not logged into that account and added manually or just ignore that and straightaway right click on the name and call (not via PSTN call or Phone number)

  • Just wait a while if Skype doesn’t automatically bridges calls to FS and Asterisk, wait like a minute!

  • Try also outbound [not covering here], you need a phone capable of dialing out with letters since Skype are all alpha {duh}

  • Well anyway, here are some screen shot

  • My skype, with user sanjayW online inside our Debian box

    image image
  • FreeSWITCH received the call and passing it to Asterisk


  • Asterisk passing it to Conference app


  • Process info – Skype single channel, if you got more channels, more lines will appear



Thank you for reading. And as usual please do give us your feedback! Thank you.

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:


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/",

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, 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
  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
  5. #tar –zxvf fail2ban_0.8.8.orig.tar.gz
  6. #cd fail2ban && python 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


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


  11. Inside jail.conf, there’s a option called ignoreip =, 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.


    # Fail2Ban configuration file
    # Author: Xavier Devlamynck


    # Read common prefixes. If any customizations available -- read them from
    # common.local
    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*$
                ^%(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 =


  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]

Asterisk/FreePBX – Post voicemail trigger (e.g. send sms after new voicemail)

Image source:

Asterisk has a function to run a program after voicemail changes happen. The changes in voicemail could include

  • Received new voicemail
  • Read new voicemail
  • Moved voicemail to different folders
  • Cleared voicemails
  • ..etc

This is especially useful if you wish to integrate Asterisk as a voicemail system and notify another PaBX (or software/service) that a particular user has the above.

In our new Hotel System module for Asterisk, we had to “inform” frontdesk if a voicemail still exist in rooms before moving a user to another room. So that the user can choose to move it or leave it there. Of course, there could then be other uses for this.


How to enable post voicemail triggers on Asterisk.

Asterisk has a function in the voicemail.conf configuration file (or use FreePBX’s voicemail admin module) called “externnotify”. This option executes your app or scripts on voicemail changes. In my case above, i wrote a simple shell script in bash to call a webservice and “tell” that webservice of a user’s voicemail changes. This will give you an idea what are the possible variables and/or options and all the possibilities it can do.

Now, to enable this, if using FreePBX use the Voicemail Admin module and under settings, add a line like this in the eternnotify box:


If not using FreePBX, edit the [general] section in /etc/asterisk/voicemail.conf and add a line like this


# invokes sending to webserver socket when there's a change in voicemail events for user
# v.1.0
# prequalify if this is a reload or not, if reload, we don't do anything
fullstring="$1 $2 $3 $4 $5"
isreload=`echo "$fullstring" | grep -c "@"`
if [[ "$isreload" -gt "0" ]]; then
exit 1
    sendurlnow=`/usr/bin/curl --silent --connect-timeout 15

    if [[ "$sendurlnow" == "" ]]; then
        echo "ERR"
        exit 1
        echo "SUCECSS"

        exit 0
exit 0

Above is a simple script was written to contact a webserver (and it works btw) when VM events like above happen but eliminating reload notifications which also will trigger the externnotify, by design. The above script does a simple tasks to “qualify” reloads vs VM events, when reloads happen, a distinctive @ symbol always appears in the first variable parsed after your script (see below for variables parsed). So we take advantage of that to quality reloads vs real VM events. Take for example, extension 8000 has a new voicemail and a reload was done. We want to “catch” the VM events as described above, not reloads. Reload lines will contain something like this: 8000@default 1 0 0. The @ symbol is uniquely available when only reloads happen, we don’t want to trigger the script if it “just reloads”.

Whereas, VM events will contain something like this:  default 8000 1 0 0 without the @ symbol, the script will then proceed to do “something”, as written in your script or like above, send a trigger to a webserver. The variables are automatically parsed after the script you defined in externnotify. Your app would need to pickup the four variables parsed, those are;

1st variable – Extension (e.g. 8000 for VM events or 8000@default for reloads)
2nd variable – Number of new voicemails
3rd variable – Number of old voicemails, in the “old” folder
4th variable – Don’t know what this represents :S

Also see “externpass” and “externpassnotify” if you wish to integrate with another PaBX where Asterisk stores voicemails and the other PaBX doesn’t.

Do let us know if this worked or can be improved upon.


Tuesday, September 17, 2013

Office 2013 – Disable SKYDRIVE save option when you do a SAVE or SAVE AS

Image source:

Office 2013 is one of the greatest office releases from Microsoft. But somehow, they tried to shove Skydrive down your throat by enabling it right on top of all options when saving files. This is fine for those using the MS Cloud Skydrive option to keep documents. But with the whole privacy of everything and anything at risk, it becomes one option i wish to skip for now.

While it is awesome for some, its God forbid life threatening to others, why? For those who don’t have Skydrive or don’t have an account that first Skydrive options is always selected and being quite fluent in MS Office products, you tend to not check and just keep going at it but unbeknownst to those speed workers, Skydrive is the always enabled first option or location to save files. So, you go ahead and select Skydrive but you don’t subscribe, then whole MS Office app now hangs or waits for a response to sign you up/in. What’s worse, if you’re offline, you wait, and wait and wait till a timeout occurs or simply force to close the app.

The good thing is Microsoft always gives you options! If this was Google, their support would probably say “..sorry this is not our problem, you have sign in or don’t use our products at all”

So, i did some poking around and found the quickest way to “stop” this behaviour,

Open Word (or any office app)

  1. Click on File, click on Option
  2. Click on Save
  3. Uncheck Show Additional places for saving…bla bla (see image)
  4. Check Save to Computer by default (see image)

And done, annoyance removed


Friday, July 26, 2013

FreePBX 2.10 or 2.11 & Asterisk dynamic phone locking application

(image courtesy of


We had a couple of clients requested this function of on the fly locking and unlocking functionalities independent of the phone manufacturer. This means also web phones, softphones and mobile softphones and what not. There are so many unmaintained hacks out there and most of the stuff in contributed modules are either not working or they cannot integrate properly or they’ve not been maintained for newer versions of FreePBX.

So I decided to write a small dialplan with the relevant recordings for you to use straight off. Please however read the following and as usual please send your feedbacks if something didn’t work or just to say hi :)

Notes and disclaimers

  1. This specific dialplan and instructions are designed for FreePBX 2.10 or higher and Asterisk version 1.8 or higher. You most probably can use them for older versions, but it is not covered in this guide though
  2. It is extremely important to define and test out the emergency numbers before rolling out. Malaysian emergency number is 999, change or add more as you wish, add as many exceptions by just copy pasting that 999 line and add the copied line below 999 and modify accordingly.
  3. Please ensure you test this, as this hooks the first priority of any given device (extension) in FreePBX, it may break custom context* module. So if this is broken, no devices/extensions can call out
  4. It uses AstDB to store the pin numbers, so drama there.
  5. It is tested with extensions mode or device and user mode
  6. It comes with the recordings which you can download from here
  7. I do not guarantee the functionality with heavily modified FreePBX setups
  8. This assumes all extensions uses the from-internal context. If you use custom context modules and name your context say “National-Calls” for instance, then whatever you see in the [from-internal-custom] needs to be also set in [National-Calls-Custom] as the custom context module includes custom dialplans too.
  9. You may use BLFs to indicate locking statuses, but the hints “declared” done inside from-internal[-custom] contexts or which context you’ve set as the hints context, i.e. subscribecontext value in sip.conf or sip_general_custom.conf or the SIP Settings in Settings. Leave it default(unset) if you’re not sure. You have to define for each extension you wan’t to use BLFs, in this example below, its extension 8001
  10. TTS sounds courtesy of AT&T Natural Voices® Text-to-Speech Demo
  11. Parts of the dialplan were taken off various web sources, but mainly it came from forums
  12. We always have a master pin to ensure you can help those who’ve not remembered their PINS (of course, the other way is to list astdb entries for that extension)


  • Dial *159 to set phone lock
  • Dial any number you wish to dial and enter the pin to unlock
  • Unlock masterkey is 2606 incase someone forgets


Steps to get this working on an unmodified core of FreePBX 2.10, 2.11. Be sure to read instructions and notes inside the dialplan too.

  1. Edit the file in /etc/asterisk/extensions_custom.conf. Paste the following diaplan there:

    include => app-create-pin
    ;;;;;;;;;;;;;;;; Emergency and exceptions;;;;;;;;;;;;;;;
    exten => 999,1,Goto(from-internal,${EXTEN},1)
    exten => 8001*159,hint,Custom:8001*159
    exten => _.,1,Macro(predial-checks)
    exten => s,1,NoOp(Phone locking module starting..)
    exten => s,n,Gotoif($[${DB_EXISTS(AMPUSER/${CALLERID(num)}/locked)}=0]?proceed)
    exten => s,n,Set(PINCOUNT=0)
    exten => s,n(readpin),Read(PIN,custom/lockunlock,,,1,5)
    exten => s,n,Set(MASTERUNLOCKER=2606)
    exten => s,n,GotoIf($[${PIN}=${MASTERUNLOCKER}]?unlocked)
    exten => s,n,Gotoif($[${PIN}=${DB(AMPUSER/${CALLERID(num)}/locked)}]?unlocked)
    exten => s,n,Set(PINCOUNT=$[${PINCOUNT}+1])
    exten => s,n,GotoIf($[${PINCOUNT}>2]?toomanyerros)
    exten => s,n,Playback(custom/wrongpintryagain)
    exten => s,n,Goto(readpin)
    exten => s,n(endit),Playback(an-error-has-occured)
    exten => s,n,Playback(terminating)
    exten => s,n,Hangup(16)
    exten => s,n(toomanyerros),Playback(custom/toomanyerrors)
    exten => s,n,Playback(terminating)
    exten => s,n,Hangup(16)
    exten => s,n(unlocked),NoOp(${DB_DELETE(AMPUSER/${CALLERID(num)}/locked)})
    exten => s,n,Set(DEVICE_STATE(Custom:${CALLERID(num)}*159)=NOT_INUSE)
    exten => s,n,Playback(custom/unlockedsuccess)
    exten => s,n,MacroExit()
    exten => s,n(proceed),NoOp(${DB_DELETE(AMPUSER/${CALLERID(num)}/locked)})
    exten => s,n,MacroExit()
  2. [app-create-pin]
    exten => *159,1,NoOp(In Set Lock)
    exten => *159,n,Read(PIN1,custom/enterpinnumber,,,,)
    exten => *159,n,Read(PIN2,custom/confirmpinnumber,,,,)
    exten => *159,n,Gotoif($[${PIN1}=${PIN2}]?setpin)
    exten => *159,n,Playback(custom/invalidverify)
    exten => *159,n,Hangup(16)
    exten => *159,n(setpin),Set(DB(AMPUSER/${CALLERID(num)}/locked)=${PIN1})
    exten => *159,n,Set(DEVICE_STATE(Custom:${CALLERID(num)}*159)=RINGING)
    exten => *159,n,Playback(custom/locksuccess)
    exten => *159,n,Playback(goodbye)
    exten => *159,n,Hangup(16)

  3. Note, if you already have something in [from-internal-custom], the ones I add above needs to be right on top. The code for locking is inside [app-create-pin] and the code for checking and unlocking is inside [macro-predial-checks].
  4. Download and store the recordings in the /custom folder
    # cd /var/lib/asterisk/sounds/custom
    # wget  -O phonelocker.tar.gz && tar -zxvf phonelocker.tar.gz
  5. Change ownership of these files to the asterisk daemon user/group you’re running with, in many cases and also in my case its “asterisk/asterisk”
    # chown asterisk:asterisk confirmpinnumber.wav
    # chown asterisk:asterisk enterpinnumber.wav
    # chown asterisk:asterisk invalidverify.wav
    # chown asterisk:asterisk locksuccess.wav
    # chown asterisk:asterisk lockunlock.wav
    # chown asterisk:asterisk toomanyerrors.wav
    # chown asterisk:asterisk unlockedsuccess.wav
    # chown asterisk:asterisk wrongpintryagain.wav
  6. Reload asterisk dialplans
    # asterisk -rx "dialplan reload”
  7. Test by dialing *159, lock ya phone!
  8. Dial anywhere and unlock it with the pin you set in item 6 just now.
  9. Be sure to test dialing your emergency numbers
  10. If you want to use BLFs, here’s a screenshot of blfs using a Yealink phone, the key item here is 8001*159 as the hint code for the phone, 8001.
  11. Hints are currently set to blink when locked or the DEVICE_STATE of “ringing”.

Good luck and happy securing your phones!

Sunday, July 14, 2013

FreePBX 2.11 and Asternic mp3/database conversion/update post recording script

Hello all, got a confirmation from Nicolas on Asternic and FreePBX 2.11 and as suspected, its no longer needed to apply the post recording patch called anymore. FreePBX 2.11 has already a place to add a post-recording script (which is what the patch from Nicolas/Asternic does anyway in the older versions). All existing patches won’t work on FreePBX 2.11, just so you know. Now, it is done more elegantly :) and you won’t have to keep patching when there’s a new release of  FreePBX Core/Framework or updates.

Here’s how:

  1. Read Asternic’s INSTALL file, when it comes to patching, do this instead if you’re using FreePBX 2.11 only, all other lower versions please use Asternic’s guide
  2. Log on to FreePBX
  3. Click on Settings | Advance Settings
  4. Turn on Display ReadOnly Settings & Override Readonly Settings like below (be sure to check the tiny checkbox after changing each field)
  5. Click Apply_Conf
  6. Refresh the page by hitting F5 or similar on your browser
  7. Now, under Developer and Customization, locate “Post Call Recording Script”
  8. In the empty field there, paste this exactly like this below;

    /usr/local/parselog/ ^{UNIQUEID} ^{MIXMONITOR_FILENAME}

  9. Again, be sure to hit that tiny check and then apply_conf again, and you’re done.
  10. Also, you might want to turn on the setting that enables it to convert to MP3, it is in the file /usr/local/parselog/
  11. Also also, be sure to set the correct Database Username/Password there and the location of the folders in which the records will be converted or moved exist and has the same rights as Asterisk daemon user
  12. I’ve had numerous times had to create arbitrary files in the “dest” directory first then do #chown -R asterisk:asterisk /var/spool/asterisk/asternic (where asterisk is the user/group which the asterisk daemon runs as)
  13. Follow the rest of the INSTALL guide
  14. NOTE: This is applicable for incoming calls, the outgoing call method is still the same, done via dialplan, and if you want a how-to for that too, here’s how
  15. Be sure to set your queues to record in WAV!, Enjoy Asternic!

Busy Lamp Field (BLF) and the Custom Context module

Hi guys, you may have this “issue” where BLFs do not work after using other than from-internal contexts? Well the fix is pretty simple, just head on to Advance SIP settings, and add a line right at the bottom like this:


Add: subscribecontext = from-internal

Now you can use your Custom Context modules and still have good fun with BLFs.

Add streaming music to FreePBX 2.10 or 2.11/Asterisk

Hi guys, here’s a simple guide many have been asking how to add streaming music to your FreePBX box’s MOH

  1. Login to FreePBX
  2. Click on Settings, click on Music on Hold
  3. Click on Add Streaming Category
  4. In the application section, add this: /usr/bin/mpg123 -q -s --mono -r 8000 -f 8192 -b 0
  5. Submit Changes, Apply configuration
  6. Now, make sure mpg123 has the appropriate permissions. In Debian OSes, it is located in /usrbin/mpg123, so do this below
  7. #chown asterisk:asterisk /usr/bin/mpg123
  8. And done!, you’ve got internet streaming straight off Asterisk.

Here’s some sources:

Basically anything that’s HTTP based streaming can work here!

Saturday, May 11, 2013

Archive script for FreePBX recordings (Asternic recordings)

Hi guys, just setup cron for this script and it will at the time you specify do a move, copy or delete files based on n number of days. If run manually, it will be like this; say I want to archive any files or directories older than 14 days, I can run it like this;

# archivefiles 14

This will set actions on folders older than 14 days. Remember, for folders, it will not traverse within each files inside folders to determine its age, it will only check the subfolders within the specified folder. However, you can specify the depth but that’s not recommended to change to other than 1. Modify as you wish, its yours to test. If you want to check the output, do a copy first, don’t do a move, thus MOVE=0 must be set. The newer Asternic and Asterisk recordings do store files by directories and not mixed up inside

Just copy paste into into an appropriate location and either setup a cronjob, e.g. below, or run manually from CLI

Crontab daily..

@daily /usr/local/sbin/archivefiles 14

Copy paste the script below, make it executable by #chmod +x archivefiles


# usage #archivefiles 14 (meaning archivefiles will find files older than 14 days to do a move or copy)
# With trailing / (slash )
# filetypes to archive when archiving by main folder files .e.g *.mp3 for mp3 only files
# With trailing / (slash )
# NOTE:0 - copy, 1 - move, 2 - delete
if [[ $OLDERTHAN = "" ]]; then
        echo "Define a period. Like 14 for older than 14 days"
    exit 1
        echo ""

if [ $OLDERTHAN ]; then
    if [ ! $(echo "$OLDERTHAN" | grep -E "^[0-9]+$") ]; then
        echo $OLDERTHAN is not a valid integer.
        exit 1
    if ! [ $OLDERTHAN -ge 0 ] || ! [ $OLDERTHAN -le 10000 ]; then
        echo $OLDERTHAN is an invalid value. Range is [1-10000]
        exit 1

if [[ -d $SOURCEPATH ]]; then
        echo "OK - Source directory exits"
        cd $SOURCEPATH
        echo "Source Directory not found, check your settings... quitting"
        exit 1

grabfiles=`ls -l  $SOURCEPATH | head -n 1 `
if [[ $grabfiles != "" ]]; then
        echo "OK - Source files exist"
        echo "Oops, no source files, check your settings...quitting"
        exit 1
if [[ $MOVE = "1"  ]];then
    #first way by files
    #find  $SOURCEPATH$SOURCEFILENAME -maxdepth 0 -mtime +$OLDERTHAN -exec mv -f {} $DEST \;
    #second way by directory
    for i in `find $SOURCEPATH -maxdepth 1 -type d -mtime +$OLDERTHAN -print`; do mv -f $i $DEST; done
elif [[ $MOVE = "0" ]]; then

    #first way by files
    #find  $SOURCEPATH$SOURCEFILENAME -maxdepth 0 -mtime +$OLDERTHAN -exec cp -f {} $DEST \;
    #second way by directory
    for i in `find $SOURCEPATH -maxdepth 1 -type d -mtime +$OLDERTHAN -print`; do cp -f $i $DEST; done
elif [[ $MOVE = "2" ]]; then

    #first way by files
    #find  $SOURCEPATH$SOURCEFILENAME -maxdepth 0 -mtime +$OLDERTHAN -exec rm {} $DEST \;
    #second way by directory
    for i in `find $SOURCEPATH -maxdepth 1 -type d -mtime +$OLDERTHAN -print`; do rm -r $i $DEST; done

exit 0

Saturday, April 27, 2013

Modifying transfer contexts in FreePBX 2.10 higher or lower, and applying restrictions

(Image copyright PizzaHut Malaysia, QSR Brands)

Few days back, we dealt with a challenge to lock down phones in a callcenter of PizzaHut Malaysia. That was easy, we fired up a specialized context which I developed that uses Device User Mode based restriction. (If you wanna know more, about that, write me!). Now, we had a daunting task of getting the same kind of restrictions applied to user who perform transfers. By default, transfers are applied using the context “from-internal-xfer”. This is previously definable in FreePBX Advance settings, somehow it is now not available through the GUI. We had to make the same kind of restriction to those doing transfers too, so what we had to do, using Adminer (GUI database manager), look for a value in DB asterisk, table freepbx_settings called “from-internal-xfer”, for freepbx 2.10, look in asterisk DB, table, Globals, we changed that to “from-internal-xfer-phm”. Now, we forked the context out into our own little coding like here. Do note, after making changes in the DB, you need to make a change in the FreePBX gui, somewhere, and hit on the “Apply Config” button to materialize these changes.

To verify, run # asterisk –rx “dialplan show globals” and it should show you “TRANSFER_CONTEXT=from-internal-xfer-phm” or whatever you’ve called it.

Now that we are able to control transfers using our own context, we had to do it right and properly not to break other transfer functions with those whom are not bound by these restrictions.

In this example below, I have agents in Device Usermode, logged in as a 6XXX extension. What we are required to do is to not allow transfers using phone (button transfer) or even Asterisk code *2. Now, with the phone we had to modify the Asterisk SIP Setting and add a value like below, in the other SIP Setting;


That fixed the phone transfers, no one can use transfers using SIP invites anymore directly. Cool.! Now, we force users to use *2 instead and when that code is pressed, the calls are being thrown to context [from-internal-xfer-phm]

In this context below, if any calls originating from 6XXX, retrieved from variable “PICKUPMARK” and is doing a transfer, looking at variable “TRANSFERNAME” which basically is populated when # transfers happen; we perform a soft hangup when those conditions are met, like below, otherwise, all others, we send back to the normal from-internal context, and basically allowing them to transfer it to wherever they like. , using this, you are free to write further more complex conditions as you please.

exten => _[4-6]XXX,1,ExecIf($["${PICKUPMARK:0:1}" = "6" & "${TRANSFERERNAME}" != "" ]?SoftHangup(Local/${EXTEN}))
exten => _X.,1,Goto(from-internal,${EXTEN},1)


Notes on the context above:

1) We catch calls in transfers made that start with digits 4 to 6, to digit “6” i.e. the call center agents. (We don’t want callcenter agents to call each other or in this case, transfer calls to each other)

2) It must be a transfer, i.e. must have the value TRANSFERNAME populated with something (With the two conditions above met, we do as below…, softhangup)

3) We softhangup the destination, i.e. EXTEN, causing the call to come back to the transferee


Have a good weekend folks!

Thursday, April 25, 2013

Asterisk –Debian based Asterisk 11, Freepbx 2.11 on VMware / Virtualbox (Asterisk VM/Asterisk Ready Virtual Machine)

Show some love,  do like our FB page |

[UPDATED: 03 FEB 2015]

Here’s a VMDK image to run a full featured Asterisk PaBX with FreePBX as the management UI using our default and secure install practices. No registrations, no username/password, no signing up for newsletter.

Get it from Sourceforge:[Select SWSterisk11 folder, then download the zip file therein]


After extracting, You either need VirtualBox or VMPlayer/VMWare or any Virtualization products that supports VMDK files or if you’re using Hypervisor, convert the image to VHD using MVMC from here.  This is to give you a feel of Asterisk with FreePBX without worrying about installation etc., its plug and play, literally. Just start up to your VirtualBox/VMplayer nd get it up and running in seconds. Go in to FreePBX and start creating extensions and enable other features. This image is free from any lockdowns or customizations that you cannot reverse or disable or enable as you wish. It is completely FREE from any personal restrictions. This image does not trace usage, or “dials home” or anything strange like that. Totally clean, totally lean and totally fast. It is functional and you can hook it up to a real production environment and you almost have a full fledge PBX, just add a Digium VoIP Gateway or another IP based PSTN.


  • While it is enterprise ready, it should rather be used for “playing” or “testing”….
  • DISCLAIMER: By using this VIRTUAL MACHINE IMAGE, i disclaim any sorts of liability whatsoever. What you do with this image is purely your choice/actions.
  • This is not "another disto", nothing proprietary, i don't claim any copyrights, just make it look and feel like its mine for fun, but of course any of those customizations can be reversed. All other trademarks are properties of their respective owners. All rights reserved.
Here’s some information about the VM image you just downloaded
  • It’s in ZIP compression, just get WinRAR or 7-ZIP to extract. After extracting, there should be one vmdk just mount the vmdk into VMWare/VMPlayer or Virtualbox and start the image
  • Username/password
  • OS
    - Username: root (the other non root user is swsterisk with same password as below)
    - Password: asteriskrocks (change this!)
  • FreePBX(admin), MySQL(root), AMI(admin): usernames and passwords;
    username: admin
    password: @steriskRocks1 (change this, here’s a good guide to start you off with
  • The network adapter is set to auto on eth0.
  • Image needs at least 384M memory (or more if you have more)
  • All source files except kernel-headers are removed to save disk space for downloading, you need to download them manually
  • Be sure your image can access internet when starting otherwise NTP and EXIM will start slow, don’t blame me!

OS features/settings

  • Debian 6.0.7 64bit (Source AMD64 netinstall) – UPDATED, Bash Vulnerability Fixed with latest patch no33, SSLV3 disabled and Ghost Vulnerability fixed. All binaries are retrieved from Debian’s 6 LTS repos. So they are up to date.
  • The interface, extX, is set to use DHCP, so be sure to hook up DHCP or manually. In case you can’t bring the interface up, run #ifconfig –a . Then edit the file in /etc/network/interfaces and set all values to correspond to the interface shown when you run ifconfig –a (not loopback of course)
  • IPV6 disabled
  • MySQL backend (performance tuned)
  • Webmin installed but not started (# /etc/init.d/webmin start , then access using https://<ipaddress>:10000)  - UPDATED!
  • Apache as webserver with enforced HTTPS
  • MySQL administration with Adminer in https://<ipaddress>/dbmanager  - UPDATED!
  • DHCP and TFTP server downloaded, not installed
  • Firewalled with IPTables (be sure to see /bin/ – UPDATED and fixed script …can be stopped and started #wallfire stop #wallfire start
  • Time i.e NTP autosyncs with daily, when starting and when stopping
  • Exim4 (mailserver) configured to relay, configure your email appropriately #dpkg-reconfigure exim4-config
  • fail2ban for Asterisk and SSH with enhancement to the log checking facility which includes asterisk security channel inside messages log (modify notification email here /etc/fail2ban/jail.conf) – UPDATED to 0.9.1!
  • Munin for monitoring in https://<ipaddress>/munin
  • Phpsysinfo for server information in https://<ipaddress>/phpsysinfo
  • Many CLI tools for troubleshooting like tcpdump, ntop, htop…
  • Astribank support [if ever u need it]
  • Removed VirtualBox OSE support to make it more cross platform compatible.
Asterisk features
FreePBX features
  • https://<ipaddress> to access FreePBX
  • FreePBX (with only basic modules pre-installed) - UPDATED
  • Enhanced FreePBX security built in
  • SIP defaults to NAT yes (avoid all one way audio issue)
  • Security basic hardening in extensions
  • CEL support in FreePBX CDR
  • Enabled g729, speex and silk (enabled for IAX and SIP)
  • Most services are started with /etc/init.d/btelsvc

Additional reading


As usual do give me your feedback. ==> sanjay(the at symbol)

Sanjay Willie

Monday, March 4, 2013

Asterisk or FreePBX call alert script (e.g. for sudden spike in international calls) that runs independently or via Nagios (Nagios compatible)

Lets face it, some of us may have had our share of FreePBX/Asterisk compromises and abusers almost always use the facility to make international calls to exotic numbers. The bill at the end of the month is already too late and there’s significant monetary damage. While its good to know in realtime of what’s going on, its of course best to prevent anything to compromise your server. see this guide here to get you started.

Here’s a small script we wrote that works for me to check as often as cronjob/Nagios allows it to, based on the parameters you set and report back via email if the script is triggered.

This script here does the following;

  • It checks the CDR for n minutes of past records also set by flags
  • Uses filters based on the dst column on your CDR to match that you specify during execution (the parameters), this can be prefixes or whole numbers, and run multiple instances. 
  • You can set the flag to check the prefix and the number of digits which is same or greater so that you won’t catch local calls, normally international calls have higher number of called digits, i.e. > 10
  • To automatically check or do it almost realtime, you can use cron on your server locally (It can also work with Nagios too, however, this guide does not cover configuring on Nagios, set NAGIOSMODE=YES). If you set Nagiosmode, it will not independently send out email and instead your Nagios server will decide what to do according to what you’ve set it to.
  • Be sure to change SYSADMINEMAIL, FROMUSER,SERVER,PORT,DATABASE,TABLE,USER,PASS in the script relevant to your setup

Getting started:

  1. Copy paste this script below in /usr/bin/ (or any location of your choice)
  2. Modify the parameters as described below
  3. Make it executable (chmod +x /usr/bin/
  4. Put this script in a cronjob if you wish to automate checking (crontab –e), e.g. like this     */15 * * * * /usr/bin/ -w 5 -c 10 -i 30 -p 00:6,900:6"
    • Above cronjob does the checks for every 15 minutes 30 records in CDR and warns on 5 critical alerts on 10 for pattern 00, with length greater than or equals 6 numbers and for pattern 900 with length greater than or equals 6 numbers
  5. Test manually. You surely can run this manually and try to invoke the trigger by making n number of calls and you should get an email alert based on the email address you specified
  6. This script requires a MySQL CDR for Asterisk (therefore making it perfect for use with FreePBX, out of the box)

Set these below before running the script

  • If using Nagios, just set the flag NAGIOSMODE=YES
  • Everything copied from below must be in a single line, no line breaks

Here’s the script, copy paste this as per item 1. getting started guide.


RELEASE="Version 2"
# – BASH 4.1.X or higher
# – FREEPBX and MYSQL of course
# – CLI tools like mail, awk, tr, curl,grep,mysql bin

# - ABLE TO SEND EMAIL OUT USING #mail with exim etc..
# ChangeLog
# - 1.1 Minor changes encapsulating output for compatibility
# - 2.0 Updated checking algorithm
# Place a cronjob, e.g. check every 5 minutes
# */15 * * * * /<locationofscript>/
USERDATEFORMAT=`date +%d-%m-%Y_%H:%M:%S`
NAGIOSMODE=NO #add more separated by commas
########END MODIFY########
function sendoutmail()
print_release() {
    echo "$RELEASE $AUTHOR"
print_usage() {
    echo ""
    echo "$PROGNAME $RELEASE - Checks international calls"
    echo ""
    echo "Usage: [flags]"
    echo ""
    echo "e.g  : ./ -w 5 -c 10 -i 30 -p 00:6,900:6"
    echo "Where it warns at 5 intl calls, and makes a critcal alert 10 calls at every 30 minutes "
    echo "of past CDR record for prefixes 00 and 900 combined total of equals to or higher than 6 digits"
    echo ""
    echo "Flags:"
    echo "  -w <number> : Warning value for number of international calls."
    echo "  -c <number> : Critical value for number of international calls"
    echo "  -i <number> : How many minutes of CDR data to poll to evaluate"
    echo "  -p <prefix:length,prefix:length,prefix:length> : Comma separated prefixes with IDD, e.g. 900:5,800:5,00:5. Length value is equals or higher. Default is 5 or higher chars"
    echo "  -h  Show this page"
    echo ""
    echo "Usage: $PROGNAME --help"
    echo ""
print_help() {
        echo ""
        echo "This plugin will check international calls made on Asterisk CDR"
        echo ""
    exit 0

# Parse parameters
while [ $# -gt 0 ]; do
    case "$1" in
        -h | --help)
            exit $STATE_OK
        -v | --version)
                exit $STATE_OK
        -w | --warning)
        -c | --critical)
        -i | --interval)
        -p | --prefix)
        *)  echo "Unknown argument: $1"
            exit $STATE_UNKNOWN
if  [[ "$WARNING_THRESHOLD" == "" ]]; then
    echo "Warning value not set, quitting.."
    exit $STATE_OK
if  [[ "$CRITICAL_THRESHOLD" == "" ]]; then
    echo "Critical value not set, quitting.."
    exit $STATE_OK
if  [[ "$INTERVAL" == "" ]]; then
    echo "Interval value not set, quitting.."
    exit $STATE_OK
if  [[ "$PREFIXES" == "" ]]; then
    echo "You must define at least one prefix, quitting.."
    exit $STATE_OK
MYSQLBIN=`which mysql`
MYAST=`which asterisk`
unixtime=`/bin/date --date="$todate" +%s`
checkdb=`$MYSQLBIN -b -n -N -s -h $server -P $port -u $user -p$pass -D $database -e "show databases;" | grep -c $database`
if  [[ $checkdb -lt 1 ]]; then
    echo "Error connecting to MySQL CDR DB"
    if [[ "$NAGIOSMODE" == "NO" ]]; then
        sendoutmail -f "Error connecting to MySQL CDR DB"
    for i in $PREFIX; do
        i=`echo $i | awk -F':' '{print $1}'`
        length=`echo $i | awk -F':' '{print $2}'`
        if [[ $length == 0 ]]; then
        rawdata=`$MYSQLBIN -b -n -N -s -h $server -P $port -u $user -p$pass -D $database -e "SELECT dst FROM $table WHERE cdr.calldate > now() - INTERVAL $interval MINUTE and CHAR_LENGTH(dst) >= '$length';" | grep -o '[0-9]*' | grep -e '\<'$i'.*\>' | tr -d ' '`
        subtotal=`echo $rawdata | awk 'NF > 0' | wc -l`
        echo $rawdata >> /tmp/$filename
    for n in $PREFIX; do
        n=`echo $n | awk -F':' '{print $1}'`
        length=`echo $n | awk -F':' '{print $2}'`
        if [[ $length == 0 ]]; then
        rawdata2=`$MYAST -rx "core show channels concise" |grep Outgoing | grep -e '\<'$n'.*\>' `
        if [[ "$rawdata2" != "" ]]; then
            subtotal=`echo $rawdata2 | awk 'NF > 0' | wc -l`
            echo $rawdata2 >> /tmp/$filename       
csved=`cat /tmp/$filename | tr -d ' ' | awk 'NF > 0' | tr "\n" ","`
# Now we start reporting to Nagios/sendmail if required
if [[ "$totalcalls" == "0" ]]; then
    echo "OK:$totalcalls |intl_calls=$totalcalls;$warning_value;$critical_value"
    exit $STATE_OK
elif [[ "$totalcalls" -ge "$critical_value" ]]; then
    echo "CRITICAL:$totalcalls LISTING:[START] $csved[END]|intl_calls=$totalcalls;$warning_value;$critical_value"
    if [[ "$NAGIOSMODE" == "NO" ]]; then
        sendoutmail -f "CRITICAL:$totalcalls LISTING:[START]$csved[END] | Critical threshold set: $critical_value"
elif [[ "$totalcalls" -ge "$warning_value" ]]; then
    echo "WARNING:$totalcalls LISTING:[START] $csved[END]|intl_calls=$totalcalls;$warning_value;$critical_value"
    if [[ "$NAGIOSMODE" == "NO" ]]; then
        sendoutmail -f "WARNING:$totalcalls LISTING:[START] $csved[END] | Warning threshold set: $warning_value"
    echo "TOTAL:$totalcalls LISTING:[START] $csved[END]|intl_calls=$totalcalls;$warning_value;$critical_value"
    exit $STATE_OK