Using a dynamic DNS (DDNS) to solve the problem of keeping a firewall open to remote users at changeable IP addresses

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

(Updated July 1, 2011 to include rudimentary test for string returned that doesn’t contain an actual IP address)

One problem faced by Asterisk users (and probably also users of other software PBX’s) is that you want to secure your system by not opening ports up to the entire Internet, but if you have remote users (users not on the same local network as your Asterisk server) you need to make an exception for them to allow them to penetrate your firewall.  If all your external users have fixed IP addresses, it’s not a problem — you simply add a specific rule in your firewall to permit access from each user’s IP address.  However, if their ISP changes their IP address frequently, or if they are using a softphone on a laptop computer, then you can’t just assume they will constantly be at same IP.  And if one of those users happens to be your boss or your mother, they are not going to be happy if they can’t use the phone until they make contact with you, and you enter their new IP address in the firewall.  And they’re probably not going to be real happy if they have to go to a web site or take some other action before they can make and receive calls.

This solution will work for many users in this situation, provided that you are using the iptables firewall. Again, the goal is to keep all your ports closed to outsiders, except for your authorized users. But if you can get each user to set up a Dynamic DNS account and then set their router to do the Dynamic DNS updates (as described here for DD-WRT users), OR failing that if you can get them to install a software Dynamic DNS client on their computer (which is a poorer choice because the computer has to be on for updates to occur), then you can run a script on your Asterisk box every five minutes to check to see if their IP address has changed, and if so, update iptables. I have one script that is called as a cron job every five minutes, and looks like this:

#!/bin/bash
/root/firewall-dynhosts.sh someaddress.afraid.org
/root/firewall-dynhosts.sh someotheraddress.afraid.org
/root/firewall-dynhosts.sh someaddress.no-ip.com

In other words it has one line for each Dynamic DNS host I want to check. For each host it calls a script named firewall-dynhosts.sh which in turn contains this:

#!/bin/bash
# filename: firewall-dynhosts.sh
#
# A script to update iptable records for dynamic dns hosts.
# Written by: Dave Horner (http://dave.thehorners.com)
# Released into public domain.
#
# Run this script in your cron table to update ips.
#
# You might want to put all your dynamic hosts in a sep. chain.
# That way you can easily see what dynamic hosts are trusted.
#
# create the chain in iptables.
# /sbin/iptables -N dynamichosts
# insert the chain into the input chain @ the head of the list.
# /sbin/iptables -I INPUT 1 -j dynamichosts
# flush all the rules in the chain
# /sbin/iptables -F dynamichosts

HOST=$1
HOSTFILE=”/root/dynhosts/host-$HOST”
CHAIN=”dynamichosts” # change this to whatever chain you want.
IPTABLES=”/sbin/iptables”

# check to make sure we have enough args passed.
if [ “${#@}” -ne “1” ]; then
echo “$0 hostname”
echo “You must supply a hostname to update in iptables.”
exit
fi

# lookup host name from dns tables
IP=`/usr/bin/dig +short $HOST | /usr/bin/tail -n 1`
if [ “${#IP}” = “0” ]; then
echo “Couldn’t lookup hostname for $HOST, failed.”
exit
fi

if [ ! `expr “$IP” : ‘([1-9])’` ]; then
echo “Did not return valid IP address, failed.”
exit
fi

OLDIP=””
if [ -a $HOSTFILE ]; then
OLDIP=`cat $HOSTFILE`
# echo “CAT returned: $?”
fi

# has address changed?
if [ “$OLDIP” == “$IP” ]; then
echo “Old and new IP addresses match.”
exit
fi

# save off new ip.
echo $IP>$HOSTFILE

echo “Updating $HOST in iptables.”
if [ “${#OLDIP}” != “0” ]; then
echo “Removing old rule ($OLDIP)”
`$IPTABLES -D $CHAIN -s $OLDIP/32 -j ACCEPT`
fi
echo “Inserting new rule ($IP)”
`$IPTABLES -A $CHAIN -s $IP/32 -j ACCEPT`

echo “Changing rule in /etc/sysconfig/iptables”
sed -i “0,/-A\sdynamichosts\s-s\s$OLDIP\s-j\sACCEPT/s//-A dynamichosts -s $IP -j ACCEPT/” /etc/sysconfig/iptables
# sed -i “s/-A\sdynamichosts\s-s\s$OLDIP\s-j\sACCEPT/-A dynamichosts -s $IP -j ACCEPT/g” /etc/sysconfig/iptables

echo “Sending e-mail notification”
`echo “This is an automated message – please do not reply. The address of dynamic host $HOST has been changed from $OLDIP to $IP. You may need to change the dynamichosts chain in Webmin’s Linux Firewall configuration.” | mail -s “IP address of dynamic host changed on machine name recipient@someaddress.com,anotherrecipient@someaddress.net`

As always, copy and paste the above script, so you can see where the line breaks are really supposed to be (the last line in particular is quite long, and will likely be broken up into four or five lines on the screen). Also, beware of WordPress or other software changing the single or double quotation marks to “prettified” versions — only the plain text normal quotation marks will work.

Note that prior to the first run of the script you will need to run the three commented-out commands shown near the top of the script, right after “create the chain in iptables”, to create the chain. For your convenience here they all are in one place, without the interleaved comment lines:

/sbin/iptables -N dynamichosts
/sbin/iptables -I INPUT 1 -j dynamichosts
/sbin/iptables -F dynamichosts

The lines in blue in firewall-dynhosts.sh are custom additions by me. Just in case something goes wrong, I suggest you make a backup copy of /etc/sysconfig/iptables in a safe place before running this script.  My first addition checks the first character of the string returned in $IP to make sure it is actually a number.  This was a quick and dirty addition to keep it from trying to use a string like ;; connection timed out; no servers could be reached as a valid IP address (yes, it really did that).  I’m sure that the test there could be improved upon (for example, to do a full check for a valid IP address rather than just checking the first digit) but as I say this was a quick and dirty fix.  If you have any suggestions on how to improve it, please leave a comment.  I did find this article, Validating an IP Address in a Bash Script, but it seemed like a bit of overkill considering that in this case what I’m really trying to do is simply weed out error messages.

The second set of additions change the address in the dynamichosts chain of /etc/sysconfig/iptables. Please note that this file may be at a different location in some versions of Linux (such as /etc/iptables.up.rules), if so you will need to change this accordingly. This is particularly important if you run both Webmin and fail2ban. If fail2ban is running it will add some lines to the in-memory version of iptables, so you don’t want to do a simple commit to save the in-memory version back to the iptables file. But at the same time, if you use Webmin’s “Linux Firewall” module to maintain iptables, you want any changes in IP addresses to show up the next time you call up Webmin’s Linux Firewall page. So this simply does a search and replace in /etc/sysconfig/iptables on the rule containing the old IP address, and replaces it with the new one. There are two lines in that section that contain the sed command, the first one will replace only the first instance of the old IP address if it’s in iptables more than once, while the second (which is commented out) would replace all instances of the old IP address. Uncomment whichever you prefer and leave the other commented out, but bear in mind that if two or more of your remote extensions might ever be at the same IP address at the same time, you want the first version (the one that is uncommented above) so that when one of those extensions moves to a different IP address it doesn’t change the IP address for all of the extensions.

Note there’s still a possibility of missing a change if you are actually working in Webmin when a change occurs (since you’ll already have loaded a copy of iptables, and if you then make changes and save it out it could overwrite any change made by the script). But, the last two lines of the script send you an e-mail to alert you to that possibility. If you don’t use Webmin and don’t need or want an e-mail notification for some other reason, you can omit those last two lines, otherwise change the parts in red text to sane values for your situation. While editing, pay attention to the backtick at the end of the line (it’s easy to accidentally delete it when editing an e-mail address — don’t do that!).

When you’re all finished, make sure both scripts are executable and the permissions are correct, then create a cron job to call the first script every five minutes.

The only slight drawback to this method is that when an IP address changes it can take up to ten minutes to update (five for the Dynamic DNS to pick it up, and five more for the cron job to fire that gets it from the Dynamic DNS). Fortunately, most ISP’s tend to change IP address assignments in the middle of the night. Note that using the wrong DNS servers can cause the updates to take significantly longer; I set my computers to use Google’s DNS (8.8.8.8 and 8.8.4.4) and that works fairly well. Note that if ALL your Dynamic DNS addresses are from freedns.afraid.org then you may want to change one line in the above script, from

IP=`/usr/bin/dig +short $HOST | /usr/bin/tail -n 1`

to

IP=`/usr/bin/dig +short @ns1.afraid.org $HOST | /usr/bin/tail -n 1`

This change will specify that the afraid.org DNS server is to be used for these lookups (and ONLY for these lookups, not for every DNS request your system makes – don’t want to overload the servers of this free service!). This may be particularly important if the DNS server you normally use is a caching server that doesn’t always do real-time lookups for each DNS request (for example, if you have installed the BIND DNS Server on your system). If some of the Dynamic DNS addresses come from other services then you could use a similar modification that checks a public DNS service that does not cache entries for long periods of time; as I write this Google’s DNS servers seem to update in near real time.

One thing some may not like is that this script basically hands the “keys to the kingdom” to your authorized users, by giving them access to all ports, or at least all ports not explicitly denied by rules higher in priority. It would be easy enough to change the rule that is written to iptables, or even add additional ones, in the above script, so that you could specify access to individual ports. The other problem is it works great for those external users at fixed locations that don’t move around a lot. It might not work quite as well as well for softphone users on laptops due to the delay between the time they turn on the laptop and the time your Asterisk server picks up the new address.

This has actually worked the best for me of anything I’ve tried so far because once you get the external user’s router set up to do the Dynamic DNS updates, they don’t have to think about doing anything else prior to making a call.

EDIT (December, 2015): If it is not possible or appropriate to update the dynamic DNS automatically from the users’ router, there may be another option. If any of your users have Obihai devices (or possibly another brand of VoIP device that includes an accessible “Auto Provisioning” feature that is not currently being utilized), you may want to know that they do not need to run a separate client to update their dynu.com or freedns.afraid.org dynamic IP address, because an Obihai device (and possibly some other brands of VoIP devices) can do that automatically. This is NOT a recommendation for Obihai devices, but if you or one of your users happens to already have one, here is the information as originally found in this thread on the Obihai forum, posted by user giqcass, who wrote:

Rough Draft for hackish DNS updates:

This hack will let your OBi update Dynamic DNS. It isn’t perfect but it works very well. It’s as simple as calling a url to update the DNS at afraid.org. I believe it would be a simple task to add this feature to the OBi firmware directly. So please add this OBiHai. Pretty please. Until then here you go.

Set up a Dynamic DNS host at http://freedns.afraid.org/
Go to the Dynamic DNS tab.
Copy the “direct” update url link.
Open your Obi admin page.
Click the System management page.
Click Auto Provisioning.
Under “ITSP Provisioning” Change the following.
Method = Periodically
Interval = This setting must be greater then 400 so not to over use resources. I use 3667.
ConfigURL = Paste the update link you got from afraid.org (use http://… not https://…)

Press Submit at the bottom of the page. Restart you OBi.

If you use choose to use dynu.com instead of freedns.afraid.org (which you might because dynu.com doesn’t force you to visit their web site periodically to keep your domain), the procedure is the same (after the first line), except that for the ConfigURL you would use:

http://api.dynu.com/nic/update?hostname=YOUR_DYNU_DYNAMIC_DNS&username=YOUR_DYNU_USERNAME&password=MD5_HASH_OF_PASSWORD

Replace YOUR_DYNU_DYNAMIC_DNS with your dynamic DNS domain name, YOUR_DYNU_USERNAME with the username you use to log into your dynu.com account, and MD5_HASH_OF_PASSWORD with the MD5 hash of your dynu.com password OR your IP Update Password if you have set one (which is recommended). To get the MD5 hash of the password you can enter it on this page. To set or update your IP Update Password, use this page.

The advantage of this is that if one of your users travels and takes their VoIP device with them, it would be able to change the dynamic DNS each time they plug in at a new location (not immediately, but after several minutes at most), so that if you use the technique outlined in this article your server will recognize their current address and permit access. Remember that it’s okay to use more than one Dynamic DNS service simultaneously, in case you or your user are already using a different one that doesn’t provide a simple update URL like dynu.com and freedns.afraid.org do. Other brands of VoIP adapters that have a similar “Auto Provisioning” feature may be able to do this as well, but we don’t have specific information for any of them. If you do, please feel free to add that information in a comment.

Note that we are not recommending any particular free dynamic DNS service. If you want to know what your options are, there is an article on the Best Free Dynamic DNS Services that will show you some options. You want one that is reliable and that will not disappear in a few months, but since we don’t have a crystal ball, we can’t tell you which ones might fit that criteria.

Do you use Webmin to configure iptables and also run fail2ban? Don’t forget to do this!

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

For many Linux users this will be a “Thank you, Captain Obvious” type of post, but it’s one of those things that some Webmin users might not realize.  If you use Webmin’s “Linux Firewall” configuration page to configure the iptables firewall in Linux, and you click “Apply Configuration”, it will remove fail2ban‘s rules from your active iptables configuration.  So, you must go to a Linux command prompt and enter service fail2ban restart — UNLESS you make a small change in the Webmin “Linux Firewall” configuration.

From the Webmin “Linux Firewall” main page, click Module Config, then on the configuration page, in the “Configurable options” section, look for the line “Command to run after applying configuration.” Click the button next to the text box on that line, and in the text box enter service fail2ban restart and then click the Save button at the bottom of the page. That’s all you need — now every time you make a firewall change and click “Apply Configuration”, it will automatically restart fail2ban for you.

Fixing Midnight Commander’s unreadable dropdown menus

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

If you’ve installed Midnight Commander and haven’t changed the default colors, when you try to access a dropdown menu you may see this:

Midnight Commander — Original Colors

REALLY hard to read that menu, isn’t it? Wouldn’t you rather see this?

Midnight Commander — Changed Colors

To fix the unreadable menus, just make sure Midnight Commander is not open, then use any text editor (such as nano) to open ~/.mc/ini:

nano ~/.mc/ini

Assuming that there is no existing [Colors] section in the file, just add this at the bottom of the file (if the second line exceeds the blog column width, just use copy and paste to get it all):

[Colors] base_color=default,default:menu=black,cyan:menuhot=brightmagenta,cyan:menusel=white,blue:menuhotsel=brightmagenta,blue

If there is an existing [Colors] section, you can try tweaking it using the parameters shown above. If you have a very recent version of Midnight Commander (which you probably will have if you are running Ubuntu), then instead of menu= you’ll need to use menunormal=, as shown here:

[Colors] base_color=default,default:menunormal=black,cyan:menuhot=brightmagenta,cyan:menusel=white,blue:menuhotsel=brightmagenta,blue

Note that for some reason the base_color parameter must appear, or the other items are ignored. Save the change, exit the editor, and open Midnight Commander. If you then close Midnight Commander, you may find that the position of the [Colors] section has moved within the ini file — apparently Midnight Commander rewrites the file when you close it — but if you don’t like the changes you can remove the [Colors] section to reverse the change.

I figured out how to do this after reading this blog post:
Ajnasz Blog – Midnight Commander colors and themes
Another source of information is:
Zagura’s blog – Midnight Commander Color Themes

A Perl script to send Caller ID popups from Asterisk to computers running Notify OSD (such as Ubuntu Linux) or any command-line invoked notification system

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

This is basically an update to my article, A Perl script to send Caller ID popups from Asterisk to computers running Growl under OS X on a Mac or Growl for Windows, and you should still use that article if you are sending notifications to a computer on your local network that runs Growl or Growl for Windows as the notification system.

I wanted to find a way to send Caller ID popups to a Ubuntu Linux box, and in the process I discovered a different method of sending such notifications.  There are pros and cons to using the new method, so let me explain those first:

Pros:

  • Can send notifications to any computer that supports command line generated notifications (so it could also be used with Growl, if you can use growlnotify from a command prompt to generate a notification).
  • Can send notifications to any computer that you can SSH into, provided you have it set up to use public/private key authentication rather than password authentication.

Cons:

  • Notifications typically display a couple of seconds later than under the previous method.  I suspect this is due to the SSH authentication taking a second or two.
  • It’s a little bit more complicated to set this up, though not horribly so.
  • Because this uses SSH and requires that Asterisk be granted permission to establish an SSH connection as the super user (by using sudo), there may be unforeseen security risks.

Read that last point again, and please understand that as with all projects on this site, I offer this for experimental purposes only.  I explicitly do not warrant this method as being 100% secure, nor will I tell you that it could not be exploited to do bad things on your system.  I don’t think it can (and feel free to leave a comment if you think I’m wrong), but I just don’t know that for sure.  So, if you decide to use anything in this article, you agree to assume all risks. If you’re the type that likes to sue other people when something goes wrong, then you do not have permission to use this code.  We’re all experimenters here, so no guarantees!

As with the previous method, you must have the Perl language installed on your Asterisk server, and you must have the Asterisk::AGI module installed (I’m going to assume you know how to install a Perl module from the CPAN repository – if you have Webmin installed, it can be done from within Webmin). Chances are you already have Asterisk::AGI installed, unless you built your Asterisk server “from scratch” and never installed it.

There’s one additional thing you must do on the Asterisk server before this will run, and that’s allow Asterisk to run the ssh command as root. So, add this to your /etc/sudoers file (probably at the very end, but in any case it should be obvious where to add this because it will be in a section where Asterisk is granted similar privileges with regard to other programs):

asterisk ALL = NOPASSWD: /usr/bin/ssh

Next you want to copy and paste the following Perl script to the filename /var/lib/asterisk/agi-bin/notifysend.agi on your Asterisk server (to create a non-existent file, you can use the touch command, and after that you can edit it in Midnight Commander or by using the text editor of your choice). If this code looks somewhat familiar, it’s because it’s adapted from some code that originally appeared in a FreePBX How-To, which I have modified.

#!/usr/bin/perl
use strict;
use warnings;
use Asterisk::AGI;
my $agi = new Asterisk::AGI;
my %input = $agi->ReadParse();

# Next two lines fork the process so Asterisk can get on with handling the call
open STDOUT, '>/dev/null';
fork and exit;

my $num = $input{'callerid'};
my $name = $input{'calleridname'};
my $ext = $input{'extension'};
my $user = $ARGV[0];
my $ip = $ARGV[1];

if ( $ip =~ /^([0-9a-f]{2}(:|$)){6}$/i ) {
    $ip = $agi->database_get('growlsend',uc($ip));
}

# OMIT this section if you don't want IP address
# checking (e.g. you want to use foo.bar.com)
unless ( $ip =~ /^(d+).(d+).(d+).(d+)$/ ) {
    exit;
}

if ( $ARGV[2] ne "" ) {
 $ext = $ARGV[2];
}

my @months = (
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
);
my @weekdays = (
    "Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"
);
my (
    $sec,  $min,  $hour, $mday, $mon,
    $year, $wday, $yday, $isdst
) = localtime(time);
my $ampm = "AM";
if ( $hour > 12 ) {
    $ampm = "PM";
    $hour = ( $hour - 12 );
}
elsif ( $hour eq 12 ) { $ampm = "PM"; }
elsif ( $hour eq 0 )  { $hour = "12"; }
if ( $min < 10 ) { $min = "0" . $min; }
$year += 1900;
my $fulldate =
"$hour:$min $ampm on $weekdays[$wday], $months[$mon] $mday, $year";

# Next two lines normalize NANP numbers, probably not wanted outside of U.S.A./Canada/other NANP places
$num =~ s/^([2-9])(d{2})([2-9])(d{2})(d{4})$/$1$2-$3$4-$5/;
$num =~ s/^(1)([2-9])(d{2})([2-9])(d{2})(d{4})$/$1-$2$3-$4$5-$6/;

my $cmd = qq(./remotenotify.sh "$name" "$num calling $ext at $fulldate");
$cmd = "sudo ssh $user@$ip '$cmd'";
exec "$cmd";

Also, if you want to be able to specify computers that you wish to send notifications to using MAC addresses rather than IP addresses (in case computers on your network get their addresses via DHCP, and therefore the IP address of the target computer can change from time to time), then you must in addition install the following Perl script (if you have not already done so when using the previous method). Note that if you have a mix of computers on your network and you are using both the new and old methods, you only need to do this once — it works with both methods (hence the reference to “growlsend” in the database and “gshelper” as the name of this script). Call it /var/lib/asterisk/agi-bin/gshelper.agi and note that there is a line within it that you may need to change to reflect the scope of your local network:

#!/usr/bin/perl
use strict;
use warnings;
my ($prev, @mac, @ip);
# Change the 192.168.0.0/24 in the following line to reflect the scope of your local network, if necessary
my @nmap = `nmap -sP 192.168.0.0/24|grep -B 1 MAC`;
foreach (@nmap) {
    if (index($_, "MAC Address:") >= 0) {
        @mac = split(" ");
        @ip = split(" ",$prev);
        `/usr/sbin/asterisk -rx "database put growlsend $mac[2] $ip[1]"`;
    }
    $prev=$_;
}

Make sure to modify the permissions on both scripts to make them the same as other scripts in that directory (owner and group should be asterisk, and the file should be executable), and if you use the gshelper script, make sure to set up a cron job to run it every so often (I would suggest once per hour, but it’s up to you).

Now go to this page and search for the paragraph starting with, “After you have created that file, check the ownership and permissions” (it’s right under a code block, just a bit more than halfway down the page) and if you are using FreePBX follow the instructions from there on out (if you are not using FreePBX then just read that section of the page so you understand how this works, and in any case ignore the top half of the page, it’s talking about a different notification system entirely). However, note that the syntax used in extensions_custom.conf differs from what is shown there, depending on whether you are specifying an IP address or a MAC address to identify the target computer.

First, if you are specifying the IP address of the target computer, then instead of using this syntax:

exten => ****525,1,AGI(growlsend.agi,192.168.0.123,GrowlPassWord,525)

You will need to use this:

exten => ****525,1,AGI(notifysend.agi,username,192.168.0.123,525)

Note that username is the account name you use when doing an ssh login into the destination system, and it should also be the desktop user on the system (not root!). Let’s say that the system is currently at IP address 192.168.0.123. In order for this to work, you need to be able to ssh into your Ubuntu box from your Asterisk server, using the following command from the Asterisk server’s command line:

ssh username@192.168.0.123

If it asks for a password, then you need to follow the instructions at Stop entering passwords: How to set up ssh public/private key authentication for connections to a remote server, and get it set up so that it will not ask for a password (if you don’t like my article, maybe this one will make it clearer).

It’s probably easiest to configure each computer that is to receive notifications to use a static IP address. But note that if you use the above code and have the gshelper.agi program running as a cron job, then after the first time it has run while the computer to receive the notifications is online you should be able to use a computer’s MAC address instead of the IP address. This only works if you’ve used the modified script on this page, not the one shown in the FreePBX How-To. As an example, instead of

exten => ****525,1,AGI(growlsend.agi,192.168.0.123,GrowlPassWord,525)

as shown in the example there, you could use

exten => ****525,1,AGI(notifysend.agi,username,01:23:45:AB:CD:EF,525)

(the above is all one line) where 01:23:45:AB:CD:EF is the MAC address of the computer you want to send the notification to. Once again, just in case you missed it the first time I said it, this won’t work until the gshelper.agi script has been run at least once while the computer to receive the notifications was online. If for some reason it still doesn’t appear to work, run the nmap command (from gshelper.agi) including everything between the two backticks (`) directly from a Linux command prompt and see if it’s finding the computer (depending on the size of your network, it might be several seconds before you see any output, which is why I don’t try to run this in real time while a call is coming in).

If you are NOT running FreePBX, but instead writing your Asterisk dial plans by hand, then you will have to insert a line similar to one of the above examples into your dial plan, except that you don’t need the four asterisks (****) in front of the extension number, and if it’s not the first line in the context, you’ll probably want to use n rather than 1 for the line designator (and, you won’t be putting the line into extensions_custom.conf because you probably don’t have such a file; instead you’ll just put it right in the appropriate section of your dial plan). In other words, something like this (using extension 525 as an example):

exten => 525,n,AGI(notifysend.agi,username,192.168.0.123,525)

This line should go before the line that actually connects the call through to extension 525. I do not write Asterisk dial plans by hand, so that’s about all the help I can give you. And if you don’t write your dial plans by hand, but you aren’t using FreePBX, then I’m afraid you’ll have to ask for help in whatever forum you use for advice on the particular software that you do use to generate dial plans, because I can’t tell you how to insert the above line (or something like it) into your dial plan.

Now is where it gets just a bit more complicated than in the original method. If you have followed the above instructions, you’ll be able to send the notifications to the remote system using SSH, but there will be nothing there to receive them. So we have to create a small script on the receiving system to do something with the received notifications. That script will vary depending on the receiving system, but it must be named remotenotify.sh and it must be placed in the destination user’s home directory, and don’t forget to make it executable! Here’s one that will work in most Ubuntu installations that have Notify OSD installed:

export DISPLAY=:0
notify-send --urgency="critical" --icon="phone" "$1" "$2"

Those two lines are all you need. On a different type of system (or if you have multiple displays) you may need to or wish to do something different. For example, as I mentioned above, if the destination system is running Growl then your remotenotify.sh script will need to call growlnotify, but beyond that I wouldn’t know what to use there (EDIT: But if the target system is a Mac that is running OS X, a pretty good guess would probably be that you’d only need one line, something like this:

growlnotify -s -p 1 -a Telephone -m "$2" $1

In this case it should make the notification sticky until dismissed by the user, give it a priority of 1 — the default is 0 — and use the application icon from the “Telephone” application if you have it installed. Instead of -a to specify an application’s icon you could use -I followed by a path to an .icns file that contains an icon you want to use.  Type growlnotify –help to see all the growlnotify options.  Oh, and before you can make an SSH connection to a Mac you have to go into System Preferences | Sharing and turn on Remote Login).

The beauty of this approach is that you can make the remotenotify.sh script as simple or as complicated as you need — you could even make it forward a notification to other devices if you wish, but figuring out how to do that is up to you (if you come up with something good, please leave a comment and tell us about it!).

If you’re running Ubuntu on the target system, here’s a few articles you may wish to use to help you get your notifications to look the way you want them to appear:

Tweak The NotifyOSD Notifications In Ubuntu 10.10 Maverick Meerkat [Patched NotifyOSD PPA Updated]
Get Notifications With A Close Button In Ubuntu
Configurable NotifyOSD Bubbles For Ubuntu 11.04: Move, Close On Click, Change Colors And More

If you want to be able to review missed notifications, you may be able to use this (as a side note, why don’t they have something like this for Growl?):

Never Miss A NotifyOSD Notification With “Recent Notifications” GNOME Applet

The idea behind the shell script that runs on the target system was found in a comment on the following article, which may be of special interest to MythTV users:

Send OSD notification messages to all systems on a network

There are links to other original sources throughout the article, so feel free to follow those if you want more in-depth commentary.

Why your brand new router may cause your VoIP to stop working

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.
I quote directly from Voip-Info.org:

Many of today’s commercial routers implement SIP ALG (Application-level gateway), coming with this feature enabled by default. While ALG could help in solving NAT related problems, the fact is that many routers’ ALG implementations are wrong and break SIP.

The article goes on to explain why the implementation is broken, and how to disable it in several brands of routers.  Certain VoIP adapter manufacturers also recommend disabling this feature if you are having problems with SIP registration, not being able to receive a call or one-way audio.  But note that this issue can affect any type of SIP-based communications, regardless of hardware or software used.

EDIT (May, 2018): For information on another issue that may cause problems when you switch routers, see this DSLReports thread: SIP registration times.

How to export Outbound Route Dial Patterns and Trunk Dialed Number Manipulation Rules to a CSV file in FreePBX

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

If you use a recent version of FreePBX, you are familiar with the new and tedious method of entering Outbound Route Dial Patterns and Trunk Dialed Number Manipulation Rules.  Fortunately, version 2.9 and above offer a way to import a list of patterns from a CSV file (there’s a way to patch FreePBX 2.8 to get this functionality as well — see Ticket #4691).

What they don’t give you is a way to export a list of patterns once you have them installed.  So if you want to clone a route and you’ve lost your original CSV file (or never had one to begin with because FreePBX converted your existing routes and trunks when you upgraded from version 2.7), what do you do?  Fear not, because it actually is possible, if not exactly the most straightforward process.

EDIT: Now there is an easy way around all this — see this thread on the FreePBX Swiss Army Knife Module.  If you use that module, you don’t need to read the rest of this article (although, you might be interested in the part about editing CSV files). Unfortunately, it is reported that the module does not work with FreePBX 2.10 or above, and the author has said he will not fix it to work with newer versions. It is possible that the ability to export outbound route and trunk data to a CSV file may be present in the newest version(s) of FreePBX.

EDIT: Steps 1 and 2 involve using a Database editor module to export the data to a CSV file.  Unfortunately, one commenter says that this module no longer works with FreePBX 2.9.  There are other ways to accomplish the same thing — see the edit at the end of this article to use Webmin or phpMyAdmin instead of the Database editor module.  If you export the data using one of those other programs, then skip to step 3 below.

Step 1: Go to the FreePBX bug tracker and look for Ticket #4793 — Database editor module (like phpMyAdmin for FreePBX).  On that page you’ll find a download link for dbeditor-1.0.tgz which (at the time of this writing) is the only version of this software available. Download and install it as you would any third-party module (download it to your computer, then in FreePBX’s GUI navigate to Module Admin and then click the “Upload Module” link, then upload the module and follow the directions to complete the install).

Step 2: Once you have the Database Editor installed, it will appear under the FreePBX “Tools” tab, in the “System Administration” section. Click on the “Database Editor” link, and you should see a list of database tables used by FreePBX. The two you are interested in are called outbound_route_patterns and trunk_dialpatterns. Near each pattern name you will see two links for “Export” and “Drop” — do not click either of those (especially be careful not to click drop!), because the “Export” here will export the table in MySQL format, which is not what you want. Instead, click on the name of the table (that is, click on either outbound_route_patterns or trunk_dialpatterns) and a new page will open. Near the top of the page you will see a place where it says, “Export to CSV: pipe – tab – comma – semicolon” — click on comma and it should bring up a file save dialog that will let you save the file to your system.

Step 3. Load the downloaded file into any text editor that can deal with Linux/Unix-style line endings and not change them (so, don’t use Notepad!), or better yet, use a CSV editor if you have one (an excellent free one is CSVed, which runs under Windows but will also install and run under CodeWeavers’ CrossOver on a Mac, which tends to make me think it would probably also run under WINE on a Linux or Mac OS X computer). I do NOT recommend opening the file in a spreadsheet application such as Excel, because if you have any patterns that start with one or more leading zeroes, those might be removed, and it’s also possible that any non-numeric characters may be misinterpreted or removed.

The first number in each line is associated with a particular outbound route or trunk, so, you want to cut out the lines not applicable to the route or trunk you want to keep. Don’t erase the top (header) line. If you have many routes or trunks, it may be a bit tricky to figure out which is which, since the numbers don’t tell you the name of the route or trunk they are associated with.

Deleting columns using CSVed

After you do that, you also have to get rid if the first column in each line. So let’s say you are using route 3, and each line starts with 3,. What you want to do is a search and replace on <newline>3, (or expressed as a regular expression: n3,) and replace it with a newline only (n as a regular expression). In a CSV editor you may be able to just delete the first column. For a trunk, the principle is the same except that you will need to remove the first AND last columns, leaving only the middle three.

While you’re at it, it’s also possible to use search and replace in other ways. For example, if you are duplicating list of outbound route patterns but need to change the extension field pattern in all lines, you could do that using search and replace, if you understand what you’re doing.

Step 4. Once you have edited out all the lines except the ones pertaining to the route or trunk you want, you need to change the header line at the top. It’s important to get this right. For an outbound route you want to change it from this:

route_id,match_pattern_prefix,match_pattern_pass,match_cid,prepend_digits

(Note that the route_id may be missing after the previous edit) to this:

prefix,match pattern,callerid,prepend

Visually inspect the lines following the header to make sure you have four fields separated by exactly three commas.

For a trunk, you will need to change the first header line from this:

trunkid,match_pattern_prefix,match_pattern_pass,prepend_digits,seq

(Note that the trunkid and seq may be missing after the previous edit) to this:

prefix,match pattern,prepend

Visually inspect the lines following the header to make sure you have three fields separated by exactly two commas. Also, and this applies to trunks only, if it is important that trunk dial patterns be in a particular order then you will want to check to make sure they are in the correct order in the CSV file, since the “seq” column is not preserved. In many situations this is not an issue but in certain special cases the order of trunk dial patterns can make a difference in how they are processed.

Step 5: Save the modified file to a file with the .csv extension (if using a CSV editor make sure you are saving in comma-delimited format). Again, try to make sure your editor doesn’t change the line endings – I don’t know for certain that it would make a difference, but it might.

Step 6: Now you can create a new route or trunk, and in the “Dial patterns wizards” or “Dial Rules Wizards” dropdown select “Upload from CSV” and select your file to upload. Note that if you are using a beta version of FreePBX 2.9, it may complain if you try to submit an outbound route with no patterns, even if you are uploading a CSV file. In that case, just put a single “X” in the “match pattern” field. After you submit changes, be sure to scroll through the patterns to make sure they appear to be correct. In particular, make sure that all values are in the correct fields.

There are probably other ways to accomplish this, and maybe eventually the FreePBX developers will add an export function on the route and trunk pages (obviously, it would probably not be a good idea for me to request it, and besides, it appears that someone already has).

EDIT:  Here is a way to export the data using Webmin or phpMyAdmin (replacing steps 1 and 2 above).  Use Webmin if you have it, because it produces cleaner output:

If using Webmin, from the main Webmin page, go to “Servers”, then “MySQL Database Server.”  Under “MySQL Databases”, click on “asterisk”, and it should take you to the “Edit Database” page (be very careful from here on out because if you do the wrong thing you could really mess up your system).  In the “Edit table” dropdown, select either outbound_route_patterns or trunk_dialpatterns, depending on which you want to work with.  That should take you to an “Edit table” page, but at the bottom of that page you should see a button labeled “Export as CSV.” Click on that button, and it will take you to a “CSV export options” page.  You want to select the following:

  • CSV with quotes
  • Yes to “Include column names in CSV?”
  • For export destination, use whichever is more convenient for you (note that if you “Save to file” it will be placed in a directory on your server, so you might find it easier to display it in a browser window and then save it from there).
  • Export all rows
  • Leave all columns selected in “Columns to include in CSV” (you’ll discard the first column in step 3, but you’ll still need it to allow you to determine which rows to keep for each route or trunk)

Then click the “Export Now” button.  If you exported to a browser window, use Ctrl-A to select all the lines, and Ctrl-C to copy them (⌘A and ⌘C on a Mac), then proceed with Step 3 above (except use Ctrl-V or ⌘V to paste the lines into the text editor). Or, if you prefer to use a CSV editor, then in your browser simply go to File | Save Page As… and save the entire page as a plain text file with a .csv extension to your local machine, and then proceed with Step 3 above.

If using phpMyAdmin, from the main page select “asterisk” in the left-hand column, then (still in the left-hand column) either outbound_route_patterns or trunk_dialpatterns, depending on which you want to work with. Then click the “Export” tab in the main window, and then under “View dump (schema) of table”, in the “Export” section select CSV.  The view should change to show an “Options” section, and there you want to change “Fields terminated by:” from a semicolon to a comma, and then check the “Put fields names in the first row” checkbox.   Then click the “Go” button and it should display the data in a format that can be copied and pasted into a text editor. Sorry, that’s the best I can advise you with regard to phpMyAdmin, since I seldom use that program (and I may have an older version, so things might have changed slightly).

Link: Monit: Disk space monitoring

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

This article was originally posted in February, 2011 and may be out of date. You may also wish to read Link: How to Install and Setup Monit (Linux Process and Services Monitoring) Program.

A hard disk drive with the platters and motor ...
Image via Wikipedia

Here’s an article that will be helpful to may of you who are running PBX servers under CentOS, especially (but not limited to) those running on virtual machines with low disk storage space.  Note that if you installed from an “all-in-one” distribution ISO, this possibly might already be installed, but may still need to be configured.

One thing you definitely don’t want to happen to your server is for it to run out of disk space, especially the root partition.

There are lots of pieces of open source monitoring software, a popular one being monit.

Below is a quick guide to installing monit and generating alert e-mails for disk space and cpu/memory usage. The installation was done on a SysAdminMan VPS running CentOS 5.5

Full article here (SysAdminMan)

The instructions should work for any system running CentOS 5.5.  You might be tempted to take a shortcut and just do “yum install monit” but please be aware that (at least as of the day I’m writing this) it will get you a much older version of the software, so I suggest you stick with the instructions in the article.  I have just now installed this on one system and have not fully tested it, but it did send an e-mail confirming that it had started.

This is just another tool you can use to make your life a little easier and help you avoid a problem before it becomes a major headache!

Link: How to update Webmin’s dated look

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

Found a great post on the PBX in a Flash forum that I’d like to pass along to those of you that use Webmin:

If you use Webmin regularly, you’ve probably noticed that it is starting to look pretty dated. There is a solution and that is to change the theme to the new Stressfree theme. It is a much nicer design and doesn’t affect any of the applications associated with Webmin – just the look and arrangement.

Stressfree theme for Webmin

Go to the full post with installation instructions.

 

Running Asterisk 1.8 and Fail2Ban? You need a new configuration file…

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

… And Ward Mundy of Nerd Vittles and PBX in a Flash has one for you. The explanation and instructions are here, and the file is here.

(And for all you people who say my articles are too verbose, take THAT!) 🙂

A couple of links for those using a Google Voice number attached to their primary Gmail account, especially Asterisk users

 

Important
This is an edited version of a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Comments dated before the year 2013 were originally posted to his blog.

This article was originally posted in January, 2011 and may contain outdated information.

If, despite all the advice you’ve read here and elsewhere, you’ve not created a separate Gmail account to use with your Google Voice service (using this form to attempt to get your existing number transferred to the new account, if that’s your desire), then these links are for you:

1.  Asterisk hack: make your Google Talk client invisible:

It’s been a too-busy-to-write week, but I found some time the last few evenings to brush up my C coding (only hacking at this point, really) to make Asterisk 1.8 do something I’ve wanted from the beginning: Google Talk’s invisible mode for the Google Voice integration. ….. You might want to use this feature if, like me, your Google Voice number is attached to your main GMail account. I don’t use the chat features but I appear online to anyone who has me in their contact list, as long as Asterisk is logged in, and that has the potential to draw unwanted instant messages (that will never get answered).

Full article here.

2. Avoiding the problem of missing calls when you are logged into your Gmail account:

NOTE: Also see: Not receiving some incoming Google Voice calls? Try increasing the priority.

This is posted on the OBiTALK forum, but likely applies to Asterisk users as well.  I specifically suggest that you read the third and fifth posts in the thread (posted by user “Agate”).

Link to thread on OBiTALK forum.

By the way, something I’ve been looking for, for those who use Asterisk 1.8+ with Google Voice but prefer to use the Google Voice voicemail instead of Asterisk’s, is an easy way to get a count of new voicemail messages in a specific Google Voice account. This information could then be used in some type of notification system.  What I’m specifically NOT looking for is something that requires the use of pygooglevoice — since all we want is a voicemail count, that’s overkill.  I’d also prefer a solution that doesn’t require downloading a huge XML file just to extract a voicemail count (since this is something you’d check rather frequently, pulling down about 10,000% more data than you really want just doesn’t cut it).  If anyone know of an elegant way to do this, I’d love to hear it.