Thursday, September 19, 2013

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

Image source: www.dictronics.com

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:

/usr/local/bin/update_wminfo.sh

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

externnotify=/usr/local/bin/update_wminfo.sh

#!/bin/bash
# sanjay@astiostech.com
# 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
server=10.10.10.1:6050
fullstring="$1 $2 $3 $4 $5"
isreload=`echo "$fullstring" | grep -c "@"`
#
if [[ "$isreload" -gt "0" ]]; then
   
exit 1
else   
    context="$1"
    ext="$2"
    newvm="$3"
    oldvm="$4"
    #   
    myurl="vmnotify.php?ext=$ext&new=$newvm&old=$oldvm"
    sendurlnow=`/usr/bin/curl --silent --connect-timeout 15
http://$server/$myurl`
   

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

        exit 0
    fi
fi
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.

Enjoy!

Tuesday, September 17, 2013

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


Image source: mommasaid.net

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

image

Friday, July 26, 2013

FreePBX 2.10 or 2.11 & Asterisk dynamic phone locking application


(image courtesy of www.unlock.my)

Introduction

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 freepbx.org 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 freepbx.org 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)

Usage

  • 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

Installation

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:

    [from-internal-custom]
    include => app-create-pin
    ;;;;;;;;;;;;;;;; Emergency and exceptions;;;;;;;;;;;;;;;
    exten => 999,1,Goto(from-internal,${EXTEN},1)
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;
    ;;;;;;;;;;;;;;;;;;;;HINTS;;;;;;;;;;;;;;;;;;;;;;;;;
    exten => 8001*159,hint,Custom:8001*159
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;
    exten => _.,1,Macro(predial-checks)
    [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
    http://goo.gl/x1U0gw  -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.
    image
  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 update_mix_monitor.pl 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)
    image
  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/update_mix_mixmonitor.pl ^{UNIQUEID} ^{MIXMONITOR_FILENAME}

    image
  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/update_mix_mixmonitor.pl
  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:

image

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 http://voxsc1.somafm.com:8502/
  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: http://somafm.com/

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

 

#!/bin/bash
# sanjayws@gmail.com
# usage #archivefiles 14 (meaning archivefiles will find files older than 14 days to do a move or copy)
#
# DEFINE THESE
SOURCEPATH=/var/spool/asterisk/monitor-mp3/
# With trailing / (slash )
SOURCEFILENAME=*
# filetypes to archive when archiving by main folder files .e.g *.mp3 for mp3 only files
DEST=/usr/usbhdg1/asterisk-recordings/
# With trailing / (slash )
MOVE=1
# NOTE:0 - copy, 1 - move, 2 - delete
#
# START THE SCRIPT
# CHECK IF OLDER THAN VARIABLE DEFINED
#
OLDERTHAN=$1
if [[ $OLDERTHAN = "" ]]; then
        echo "Define a period. Like 14 for older than 14 days"
    exit 1
else
        echo ""
fi

# CHECK IF VALUE ENTERED IS AN INTEGER
#
if [ $OLDERTHAN ]; then
    if [ ! $(echo "$OLDERTHAN" | grep -E "^[0-9]+$") ]; then
        echo $OLDERTHAN is not a valid integer.
        exit 1
    else
    if ! [ $OLDERTHAN -ge 0 ] || ! [ $OLDERTHAN -le 10000 ]; then
        echo $OLDERTHAN is an invalid value. Range is [1-10000]
        exit 1
    fi
    fi
fi

# CHECK IF SOURCE DIRECTORY EXIST
#
if [[ -d $SOURCEPATH ]]; then
        echo "OK - Source directory exits"
        cd $SOURCEPATH
else
        echo "Source Directory not found, check your settings... quitting"
        exit 1
fi

grabfiles=`ls -l  $SOURCEPATH | head -n 1 `
if [[ $grabfiles != "" ]]; then
        echo "OK - Source files exist"
else
        echo "Oops, no source files, check your settings...quitting"
        exit 1
fi
       
# CHECK IF DESTINATION EXISTS
#
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
fi   


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;

allowtransfers=no

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.

[from-internal-xfer-phm]
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 www.fb.com/Astiostech |

[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: https://sourceforge.net/projects/debianasterisk/[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.

IMPORTANT

  • 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 http://www.freepbx.org/support/documentation/installation/first-steps-after-installation)
  • REMEMBER REMEMBER REMEMBER: CHANGE PASSWORDS!
  • 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/wallfire.sh) – UPDATED and fixed wallfire.sh script …can be stopped and started #wallfire stop #wallfire start
  • Time i.e NTP autosyncs with ntp.org 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 2.11.0.38 (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)astiostech.com

Thanks!
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/checkintl.sh (or any location of your choice)
  2. Modify the parameters as described below
  3. Make it executable (chmod +x /usr/bin/checkintl.sh)
  4. Put this script in a cronjob if you wish to automate checking (crontab –e), e.g. like this     */15 * * * * /usr/bin/checkintl.sh -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)
  7. IMPORTANT: THIS SCRIPT CHECKS AFTER ASTERISK WRITES TO CDR AND ALSO WHILE IN CALL COMBINED, SO CHECK BOTH PLACES

Set these below before running the script

  • The emailtoSYSADMINEMAIL, emailFROMUSER,SERVERip,serverPORT,cdrDATABASE,cdrTABLE,dbUSER,dbPASS
  • 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.

###PASTE START###

#!/bin/bash
RELEASE="Version 2"
AUTHOR="sanjay@astiostech.com"
PROGNAME="checkintl.sh"
#
# PRE-REQ
# – BASH 4.1.X or higher
# – FREEPBX and MYSQL of course
# - ASTERISK WITH CDR SUPPORT
# - ACCESS TO ASTERISKCDR DB
# – CLI tools like mail, awk, tr, curl,grep,mysql bin

# - ABLE TO SEND EMAIL OUT USING #mail with exim etc..
#
# ChangeLog
# - FIRST RELEASE
# - 1.1 Minor changes encapsulating output for compatibility
# - 2.0 Updated checking algorithm
#
# Place a cronjob, e.g. check every 5 minutes
# */15 * * * * /<locationofscript>/checkintl.sh
#
# NOTHING TO CHANGE HERE
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
USERDATEFORMAT=`date +%d-%m-%Y_%H:%M:%S`
#
########MODIFY HERE
########
NAGIOSMODE=NO
SYSADMINEMAIL=youradmin@yourdomain.com #add more separated by commas
FROMUSER=youruser@yourdomain.com
EMAILSUBJECT="CALL ALERTER – By Astiostech"
server="localhost"
port="3306"
database="asteriskcdrdb"
table="cdr"
user="<mysqluser>"
pass="<mysqlpass>"
########END MODIFY########
#
#
##FUNCTIONS
function sendoutmail()
{
( echo [$USERDATEFORMAT] - $2 ) | mail -aFrom:$FROMUSER -s "$EMAILSUBJECT" $SYSADMINEMAIL
return
}
#
print_release() {
    echo "$RELEASE $AUTHOR"
}
#
print_usage() {
    clear
    echo ""
    echo "$PROGNAME $RELEASE - Checks international calls"
    echo ""
    echo "Usage: checkintl.sh [flags]"
    echo ""
    echo "e.g  : ./checkintl.sh -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() {
    print_usage
        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)
            print_help
            exit $STATE_OK
            ;;
        -v | --version)
                print_release
                exit $STATE_OK
                ;;
        -w | --warning)
                shift
                WARNING_THRESHOLD=$1
                ;;
        -c | --critical)
               shift
                CRITICAL_THRESHOLD=$1
                ;;
        -i | --interval)
               shift
               INTERVAL=$1
                ;;
        -p | --prefix)
               shift
               PREFIXES=$1
                ;;
        *)  echo "Unknown argument: $1"
            print_usage
            exit $STATE_UNKNOWN
            ;;
        esac
shift
done
#
if  [[ "$WARNING_THRESHOLD" == "" ]]; then
    echo "Warning value not set, quitting.."
    exit $STATE_OK
fi
if  [[ "$CRITICAL_THRESHOLD" == "" ]]; then
    echo "Critical value not set, quitting.."
    exit $STATE_OK
fi
if  [[ "$INTERVAL" == "" ]]; then
    echo "Interval value not set, quitting.."
    exit $STATE_OK
fi
if  [[ "$PREFIXES" == "" ]]; then
    echo "You must define at least one prefix, quitting.."
    exit $STATE_OK
fi
#
# SET VARIABLES
warning_value="$WARNING_THRESHOLD"
critical_value="$CRITICAL_THRESHOLD"
interval="$INTERVAL"
PREFIX="$PREFIXES"
MYSQLBIN=`which mysql`
MYAST=`which asterisk`
#
# CONSTANTS
todate=`/bin/date`
unixtime=`/bin/date --date="$todate" +%s`
filename=mycdrlogforintl.$unixtime.txt
#
# DB CONNECTION CHECKER
checkdb=`$MYSQLBIN -b -n -N -s -h $server -P $port -u $user -p$pass -D $database -e "show databases;" | grep -c $database`
# START CHECKING CALLS
IFS=$OLDIFS
IFS=,
if  [[ $checkdb -lt 1 ]]; then
    echo "Error connecting to MySQL CDR DB"
    if [[ "$NAGIOSMODE" == "NO" ]]; then
        sendoutmail -f "Error connecting to MySQL CDR DB"
    fi
    exit $STATE_UNKNOWN
else
    for i in $PREFIX; do
        i=`echo $i | awk -F':' '{print $1}'`
        length=`echo $i | awk -F':' '{print $2}'`
        if [[ $length == 0 ]]; then
            length=5
        fi
        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
        ((totalcalls+=$subtotal))
    done
    for n in $PREFIX; do
        n=`echo $n | awk -F':' '{print $1}'`
        length=`echo $n | awk -F':' '{print $2}'`
        if [[ $length == 0 ]]; then
            length=5
        fi
        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       
            ((totalcalls+=$subtotal))
        fi   
    done
IFS=$OLDIFS
fi
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"
    fi
    exit $STATE_CRITICAL
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"
    fi
    exit $STATE_WARNING
else
    echo "TOTAL:$totalcalls LISTING:[START] $csved[END]|intl_calls=$totalcalls;$warning_value;$critical_value"
    exit $STATE_OK
fi

###PASTE END###