This was originally posted in August, 2011. Unless you are deeply in love with Perl, I suggest you also take a look at the newer article, A Bash script to rewrite the "static" IP address in the FreePBX Asterisk SIP Settings when it is changed by your ISP. Although it is still considered experimental, it is simpler than the script shown here, does not require the installation of additional modules, and the text has been updated somewhat to reflect the changes in FreePBX since this article was written.
This post is going to be a bit long because I first need to explain the “why” behind this script, then how to obtain the prerequisite Perl modules, then the script itself and how to test it after installation.
If you are using a recent version of Asterisk and FreePBX you may be using the Asterisk SIP Settings module (under the “Tools” tab) to automatically set various SIP parameters. This module is a great help to those who don’t know what they are doing, but there is a trap for the unwary (and in this case it’s NOT the fault of FreePBX – it’s a longstanding bug in Asterisk that’s the problem).
At the top of the Asterisk SIP Settings configuration page, in the NAT Settings section, there are two options that can be set. The first is NAT and there are four possible choices:
- yes = Always ignore info and assume NAT
- no = Use NAT mode only according to RFC3581
- never = Never attempt NAT mode or RFC3581
- route = Assume NAT, don’t send rport
In theory, if you have a fixed IP address AND your Asterisk server is not behind an external router that does NAT translation, you should use “no” (and most of the rest of this article will not be relevant to you). This article is intended more for home and SOHO users that both have their Asterisk server behind a hardware router of some kind, and that get their broadband service from a company that occasionally changes their IP address without warning. For such users, the preferred setting is “yes”. I’m not enough of a networking guru to tell you under what circumstances one of the other settings might be appropriate (if you understand this stuff, feel free to leave a comment and enlighten us).
It’s the next set of settings that can get us into trouble. This is the IP Configuration and there are three possible choices:
- Public IP
- Static IP
- Dynamic IP
If your IP address never changes AND you aren’t behind a hardware firewall then you can usually just set this to “Public IP” and let it go at that. You will not be asked to fill in any other values. But most users that are not in that situation will pick one of the other two choices, and this is where the problem arises. Conventional wisdom has it that if your ISP ever changes your IP address without advance warning (which is the case for most cable broadband and DSL users), you should use the Dynamic IP setting. In this case there is an auto-configure button that will fill out the fields for you, although you may need to fill in the Dynamic Host field yourself. This is the “External FQDN as seen on the WAN side of the router and updated dynamically, e.g. mydomain.dyndns.com” (as explained if you mouse over the words “Dynamic Host”). You can use a DynDNS address (or an address from a similar service) or an address you have purchased. But the problem is that for some users, THIS METHOD SIMPLY DOES NOT WORK.
If you try to use Dynamic IP and it won’t work for you, what happens is you will get all sorts of weird errors. You may get one way audio, some calls may disconnect for no apparent reason after about five seconds, and you will see other weird errors in your CLI. If you change this setting to “Static IP” and click the auto-configure button and then submit the changes, the problems magically go away – UNTIL your ISP changes your IP address, at which point you suddenly have no connectivity to the outside world. If you ask for help, everybody and their brother will tell you to use the Dynamic IP setting, and the minute you try that you’ll get all the weird errors again.
So if that’s your situation, you need this Perl script. Coupled with a cron job, it goes out and checks your IP address every five minutes and if it notices it has changed, it changes it in the MySQL database (same as if you entered it into the External IP text box on the Asterisk SIP Settings configuration page) and then reloads Asterisk. Therefore, you can use the Static IP method and it hopefully it will work reliably. If and when your IP address changes, you should only be down for about five to ten minutes at most (hopefully your broadband provider usually does such changes in the middle of the night!).
Prerequisites:
You still have to use a Dynamic DNS service to keep track of your IP address if you want external extensions to be able to find your server on the Internet. It’s not required for this script to work, though, so I won’t say any more about that except to note that if you use a recent vintage hardware router, it probably has DDNS support built in.
You may have to install some Perl modules on your system. This script uses two or three: WWW::Mechanize (only if you use the first variation of the script shown below), Data::Validate::IP, and DBD::mysql. There are typically two ways to install any missing Perl modules on your system. One is to do this from the Linux command prompt:
perl -MCPAN -e shell
This will put you into a Perl CPAN shell and if it’s the very first time you’ve ever run this, it may ask you to do some configuration first. Go ahead and do it. If you don’t know how to answer a particular question, accepting the default is usually a pretty safe bet (if you disagree with me on this, then you know enough to know how to answer the questions, so you don’t need my help). However there are a couple questions related to buffers where you have the option to not create one, and I usually don’t because I don’t spend much time in the Perl shell. Just read the questions and either use the default answer, or another suggested answer that fits your preferences. When it comes time to pick servers (from which you will download modules), just pick two or three that are close to you.
After you’ve done the configuration, just install each module (if you already have it, it may say “nothing to do” and stop). Alternately, if you configured Perl to ask before downloading dependencies, you may need to answer “yes” a few times to allow dependencies to be downloaded and installed. To install the required modules from within the CPAN shell, just do these, one at a time:
install WWW::Mechanize (only if you use the first variation of the script)
install Data::Validate::IP
install DBD::mysql (you might already have this).
To quit the CPAN shell, just type quit and press Enter.
Alternately, in some distributions you can get certain Perl modules from the distribution’s repository. For example, in Centos you may be able to use:
yum install perl-WWW-Mechanize.noarch (only if you use the first variation of the script)
yum install perl-Data-Validate-IP.noarch
yum install perl-DBD-MySQL.noarch
Or in any Debian-based Linux, including Ubuntu Server, try these:
sudo apt install libwww-mechanize-perl (only if you use the first variation of the script)
sudo apt install libdata-validate-ip-perl
sudo apt install libdbd-mysql-perl
It’s likely you already have the Mysql module. Depending on your distro you may have to leave off the .noarch, or find a specific version in an appropriate repository. Installing from the CPAN shell make take a bit more time for the initial configuration, and some people find the CPAN shell difficult to use, but you will always get the correct version of the module.
Note that if you use Webmin, there is a third way – you can install modules from the Other | Perl Modules | Install Module page. BUT, that may not work correctly until you have configured CPAN as mentioned above. Don’t let that stop you from trying it, though!
The Script:
There are now two versions of this script. One uses WWW::Mechanize to get your IP address from a web site that returns only your IP address, while the second uses a dig command to get your IP address. We recommend the second one, since public sites that return only your IP address have a nasty habit of disappearing. Note that as always, these WILL overflow the lines in WordPress, so you will want to cut and paste your preferred script into a text editor. Also note that WordPress MAY change apostrophes and quotes into “prettified” versions, and if it does that will totally mess up Perl. I’m going to put this in a preformatted text block so hopefully WordPress won’t change anything (it doesn’t appear that it has), but you never know. One final note, don’t confuse backticks (`) with apostrophes (‘) – backticks are used to run a command that would normally be run from a Linux command prompt.
These scripts were written for use with FreePBX 2.11; there are a couple of lines that need to be changed for FreePBX 12 and above which will be posted below the main scripts:
#!/usr/bin/perl # This program gets the current IP address (as assigned by the ISP) from # a web page and modifies the FreePBX Asterisk SIP settings if the # external IP address has changed. Invoke it as cron job that runs every 5 minutes. use strict; use warnings; use WWW::Mechanize; use Data::Validate::IP qw(is_public_ipv4); # GET CURRENT IP ADDRESS my $mech = WWW::Mechanize->new( autocheck => 1 ); # NOTE THE http QUERY IN THE NEXT LINE - PLEASE PASTE THIS INTO YOUR WEB # BROWSER AND MAKE SURE IT RETURNS YOUR IP ADDRESS AND NOTHING ELSE. $mech->get('http://some_web_site_that_returns_your_IP_address'); $mech->success or die 'Cannot connect to web site'; my ($ip) = ($mech->content() =~ /(d+.d+.d+.d+)/); # VALIDATE RESULT RECEIVED if (is_public_ipv4($ip)) { # SET UP TO CONNECT TO MySQL DATABASE use DBI(); # CONNECT TO DATABASE my $connect = DBI->connect("DBI:mysql:database=asterisk;host=localhost", "user", "pw", {'RaiseError' => 1}); # GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT data FROM sipsettings WHERE keyword like ?", undef, "externip_val"); # COMPARE IP ADDRESSES if ($externip ne $ip) { # WAIT 5 SECONDS AND RECHECK IP TO AVOID FALSE POSITIVES sleep 5; $mech->get('http://some_web_site_that_returns_your_IP_address'); $mech->success or die 'Cannot connect to web site'; my ($ip) = ($mech->content() =~ /(d+.d+.d+.d+)/); if ($externip ne $ip) { # IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE sipsettings SET data = ? WHERE keyword = ?", undef, "$ip", "externip_val"); # WRITE CONFIG FILES AND RELOAD ASTERISK `/var/lib/asterisk/bin/module_admin reload`; # OPTIONAL SEND EMAIL TO SYSTEM ADMINISTRATOR(S) # my $mailstring = 'echo "This is an automated message - please do not reply. Either we had a power or Internet outage (in which case there is a slight chance you may receive this message even if our IP address is unchanged), or our Internet Service Provider has changed the IP address of our phone server to ' . $ip . '" | mail -s "ISP may have changed our IP address" someaddress@gmail.com,anotheraddress@somewhere.com'; # system($mailstring); }; }; };
Variation #2 (recommended) – note, do NOT confuse backticks and apostrophes, since both are used in this script and they are NOT interchangeable!
#!/usr/bin/perl # This program gets the current IP address (as assigned by the ISP) from # OpenDNS and modifies the FreePBX Asterisk SIP settings if the external IP # address has changed. Invoke it as cron job that runs every 5 minutes. use strict; use warnings; use Data::Validate::IP qw(is_public_ipv4); my $dig = 'dig +short myip.opendns.com @resolver1.opendns.com'; my $ip=`$dig`; chomp $ip; if ($ip=~/((\d){1,3}\.){3}(\d){1,3}/) { if (is_public_ipv4($ip)) { # SET UP TO CONNECT TO MySQL DATABASE use DBI(); # CONNECT TO DATABASE my $connect = DBI->connect("DBI:mysql:database=asterisk;host=localhost", "user", "pw", {'RaiseError' => 1}); # GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT data FROM sipsettings WHERE keyword like ?", undef, "externip_val"); # COMPARE IP ADDRESSES if ($externip ne $ip) { # WAIT 5 SECONDS AND RECHECK IP TO AVOID FALSE POSITIVES sleep 5; $ip=`$dig`; chomp $ip; if ($ip=~/((\d){1,3}\.){3}(\d){1,3}/) { if (is_public_ipv4($ip)) { if ($externip ne $ip) { # IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE sipsettings SET data = ? WHERE keyword = ?", undef, "$ip", "externip_val"); # WRITE CONFIG FILES AND RELOAD ASTERISK `/var/lib/asterisk/bin/module_admin reload`; # OPTIONAL SEND EMAIL TO SYSTEM ADMINISTRATOR(S) # my $mailstring = 'echo "This is an automated message - please do not reply. Either we had a power or Internet outage (in which case there is a slight chance you may receive this message even if our IP address is unchanged), or our Internet Service Provider has changed the IP address of our phone server to ' . $ip . '" | mail -s "ISP may have changed our IP address" someaddress@gmail.com,anotheraddress@somewhere.com'; # system($mailstring); }; }; }; }; }; };
NOTES on the above scripts, including THINGS YOU MUST CHANGE:
In the first script, change both occurrences of http://some_web_site_that_returns_your_IP_address to a web address that returns only your IP address and nothing else. Enter the link into a web browser to make sure you get the expected result β it should show your external IP address and nothing else. These services tend to come and go, and you’ll need to find one that returns your IP address, and ONLY your IP address, with no extraneous HTML formatting or text. If you don’t know of such a source, then try the second variation.
These rest of this applies to both scripts:
Note the two bolded variables user and pw. These must be changed to the correct values for YOUR system. You will usually find these in one of two places. You can look in /etc/amportal.conf and look for the variables AMPDBUSER and AMPDBPASS β these will usually be near the bottom of the file in newer installs, in a “— CATEGORY: Bootstrapped or Legacy Settings —” section, but they can be anywhere in the file.
Another place they may be found is in the file /etc/freepbx.conf β in that file, look for lines similar to:
$amp_conf[‘AMPDBUSER’] = ‘freepbxuser’;
$amp_conf[‘AMPDBPASS’] = ‘password’;
Those will give you the values to insert into the user and pw variables in the script. YOU MUST INSERT THE CORRECT VALUES OR THE SCRIPT WILL NOT WORK! By the way, if you have both of the above-mentioned files, make sure that the AMPDBUSER and AMPDBPASS variables are set to the same respective values in both files, otherwise your CDR Reports page may not work.
Finally, if you want an e-mail notification when your IP address has changed, uncomment the two lines under “# OPTIONAL SEND EMAIL TO SYSTEM ADMINISTRATOR(S)” and modify the first line appropriately (make sure you use one or more valid e-mail addresses!). BE CAREFUL NOT TO DELETE THE TRAILING APOSTROPHE (just before the semicolon). Yeah, I did that once. π
IF YOUR ARE RUNNING FREEPBX 12 (NOT FreePBX 14, see below), it appears they have changed the location where the IP address is stored in the database. In that case, two sections of the script need to be changed:
Change this:
# GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT data FROM sipsettings WHERE keyword like ?", undef, "externip_val");
To this:
# GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT val FROM kvstore WHERE `key` = ?", undef, "externip");
Change this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE sipsettings SET data = ? WHERE keyword = ?", undef, "$ip", "externip_val");
To this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE kvstore SET val = ? WHERE `key` = ?", undef, "$ip", "externip");
IF YOU ARE RUNNING FREEPBX 14, it appears they have changed the location again where the IP address is stored in the database. In that case, two sections of the script need to be changed:
Change this:
# GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT data FROM sipsettings WHERE keyword like ?", undef, "externip_val");
To this:
# GET IP ADDRESS FROM DATABASE my ($externip) = $connect->selectrow_array("SELECT val FROM kvstore_Sipsettings WHERE `key` = ?", undef, "externip");
Change this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE sipsettings SET data = ? WHERE keyword = ?", undef, "$ip", "externip_val");
To this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE $connect->do("UPDATE kvstore_Sipsettings SET val = ? WHERE `key` = ?", undef, "$ip", "externip");
(Thanks to “Tony” for posing the FreePBX 14 changes in the comment section.)
Regardless of which version you are running (12 or 14), BE CAREFUL, in both of the above lines the word keyword (without quotes) is changed to `key` (with backtick quotes). If you leave out the backticks, or change them to something else such as apostrophes, IT WILL NOT WORK.
Save your script to either the /root directory or the /var/lib/asterisk/agi-bin directory, or to another location of your choosing. I named it checkip.pl, solely because that was the name of a previous script I had run and I had already created a cron job for it. You must make the script executable, for example:
chmod u+rx /var/lib/asterisk/agi-bin/checkip.pl
Of course you will specify the correct filename and directory. Now it’s time to test the script. From the Linux command prompt, navigate to the directory where you stored the script:
cd /var/lib/asterisk/agi-bin
Now run the script from the command prompt:
./checkip.pl
Hopefully you won’t see any error messages. Remember it’s going out to do a query to get your external IP address, so don’t get concerned if it takes a second or two. If you had an incorrect address stored in your FreePBX Asterisk SIP Settings configuration, it will take longer because it will reload the FreePBX configuration. The script has a couple of different checks to make sure it only stores a real IP address (and not something invalid like an error message) in the database, so if it appears to not be working, make sure the underlying call to the web server or the dig command (depending on which variation you use) is returning a valid IP address.
Usually if you do see errors they will fall into one of two categories. The first is a missing Perl module, which you will need to obtain as described above. The second is a syntax error, which you should not get if you cut and pasted the script, and made the changes noted above. If you get a permissions error, you probably forgot to make the script executable!
Setting up a cron job:
Once it runs without errors, you will want to create a cron job so it runs automatically every five minutes. Do NOT run it more often than that, or the lookup service may ban your IP address, and you don’t want that to happen (whatismyip.com would do that, which is another reason not to use them), and besides, it’s not polite to hog the resources of someone else’s server! And if you are running it on multiple servers at the same IP address, then adjust the polling speed so that the total polling from all servers doesn’t exceed once every five minutes. An occasional additional test is probably not an issue, but if you try to poll every minute you just might get banned!
The usual way to add a cron job is to run this command:
crontab -e
(If you’re not currently running as root use sudo crontab -e instead)
This will open a text editor showing your current cron jobs. Just add a new line to the bottom of the file with your new cron job. To run the script every five minutes, you could use something like this:
*/5 * * * * /var/lib/asterisk/agi-bin/checkip.pl
Or to be more specific as to when the script runs (this will run it exactly on the hour, at five minutes after the hour, at ten minutes after the hour, and so on):
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /var/lib/asterisk/agi-bin/checkip.pl
Just save the changed file when you are finished. The alternate method is to use Webmin’s System | Scheduled Cron Jobs module to set up your cron job.
Final testing:
The easiest way to test to make sure this is all working is to wait until a time that there are no active calls on the system, then go to the Asterisk SIP Settings configuration page and change the External IP address to something invalid (just change the last digit of the current address and Submit Changes, then do the usual orange bar reload). On the next five minute interval, the script should detect that the external IP address doesn’t match the one stored in the database, and it will write the correct value to the database and reload Asterisk. If you watch the Asterisk CLI during this time, you should actually see the reload take place. After that, if you go back to the Asterisk SIP Settings configuration page, the correct IP address should be there. To be extra safe, you should also view the contents of the file /etc/asterisk/sip_general_additional.conf and make sure that the externip= line shows the correct IP address.
Now you don’t have to worry about frantic calls from users at inopportune times because your ISP changed your IP address and none of the phones are working, and you also won’t have any of the problems associated with the Dynamic IP method!
I want to thank Moshe Brevda for giving me the information I needed to do the MySQL database write, after a particularly frustrating middle of the night session (not helped by bumping into a truly arrogant bastard on an IRC channel), and also for one correction to this article (see my comment in the comments section below). If any “Perl purists” are reading this and you want to offer a constructive comment without giving me any attitude, I’m fine with that. But if you are like some of your I-know-it-all-and-your-coding-sucks brethren in the IRC channel, don’t even waste your time posting a comment, because I won’t approve it. No, you really DON’T need to use any other Perl database modules to do this simple task, and no, I DON’T want to learn your philosophy of writing Perl code (there are some really sucky mom’s-basement-dwellers inhabiting the #perl IRC channel β some of those folks really need to get professional help, and that is all I will say about that). EDIT: Credit to the article Quickly Get an External IP Address from the Command Line (OS X Daily) for revealing the method of using dig with OpenDNS to get your IP address.
NOTE: As usual, there are no warranties β we’re experimenters here, and sometimes we don’t catch all the bugs, especially on the first go around! However, I would assume that anyone who is running a “professional” installation would pay their ISP for a true static IP address (one that never changes), and therefore wouldn’t need one of these scripts in the first place.
As I screw this up all the time, I always like to remind those unfamiliar with perl that when writing email from perl, always either put the email addresses in single quotes, or escape the at sign with a backslash like nobody\@uu.net or ‘nobody@uu.net’
@ is an array identifier, and when in double quotes it will be evaluated in context. So your email address would become nobody.net, as . is not valid in a variable name and would mark the end of “@uu”, a (probably) uninitialized array.
Thanks for that reminder. In this case the entire string
'" | mail -s "ISP may have changed our IP address" someaddress@gmail.com,anotheraddress@somewhere.com'
is encapsulated within single quotes so the problem is averted, but if I recall it took me a while to figure out how to do that (the mail lines were carried over from a different Perl script I used on our old system). The thing I do remember doing was accidentally deleting the ending single quote and not noticing β it took me MUCH too long to figure that one out!The nat= setting describes peer situation not yours. No reason to set it to yes. Starting with 1.8 asterisk can use STUN, so your workaround is not necessary. Check http://forums.digium.com/viewtopic.php?t=74252
First of all, we’re working in FreePBX, NOT raw Asterisk here, and as far as I know FreePBX doesn’t offer STUN support. Second, there is usually no reason NOT to set it to yes, and sometimes it turns out to be necessary. Third, my objection to the use of STUN servers is that you are putting your phone traffic at the mercy of a third party that in most cases you don’t know from Adam. Some STUN servers might be very reliable, but I don’t know that, and I don’t know which ones are and which are not. So if I can get the system to work WITHOUT using a STUN server, I’m doggone well going to do it. And finally, that page you linked to was useless in that it gave no clue how to actually use STUN in Asterisk, even assuming I wanted to go outside the FreePBX interface.
If you want to send me a link to a document, find me one that is written so that the non-technical person can understand it, and that explains exactly under which circumstances you’d use each of the various options of the nat= setting. It’s wonderful that Asterisk gives you so many options, but what’s not wonderful is that they provide virtually no decent online documentation (don’t even THINK of telling me to read that damn book β this is the information age, we don’t read books just to find out how to set one setting). Most of the time when I am trying to find information on Asterisk settings, Google refers me to voip-info.org which is a GREAT resource, but many of their pages haven’t been updated since sometime around Asterisk 1.2. So here you come talking about a new feature in Asterisk when my article was clearly intended for FreePBX users, and you don’t even give me a link to real documentation (and even if you had, would I be able to understand it?). Don’t mean to jump all over you, my real frustration is with the Asterisk folks who make a bunch of changes in each new version, but don’t bother to provide user-friendly online documentation for any of them (either that, or they keep it very well hidden from Google).
Sorry for dumping too much info on you. You missed the part about nat= describing the peer, not asterisk. Most VoIP providers run their own stun servers which is better than putting yourself at mercy of whatismyip.org ( or com) The .org server is notoriously flakey, the .com changed the automation URL twice in the last 18 months:
from http://whatismyip.com/automation/n09230945.asp to
http://www.whatismyip.com/automation/n09230945.asp to
http://automation.whatismyip.com/n09230945.asp
Btw: the nat options in 1.8 have changed, the new keywords are no,yes, force_rport and comedia.
The only options that should be used are “no” and “comedia”(previously known as “route”) Comedia/route is for remote extensions behind NAT w/o port forwarding for RTP.
obeliks, I appreciate the information BUT you seem to miss the point that we are running FreePBX, not raw Asterisk. I don’t know if FreePBX writes different NAT options if it detects that Asterisk 1.8 is in use but frankly I don’t have a problem with using “nat=yes” (and please don’t tell me I shouldn’t do that unless you can point me to online documentation from Digium that CLEARLY and UNAMBIGUOUSLY says I shouldn’t do that). I already explained my objection to STUN servers. If whatismyip.com goes down, nothing bad happens to my system until the next time the ISP changes my IP address, and in that case I’m no worse off than I was before I started using the script. If I rely on a STUN server and it goes down, calls may stop flowing IMMEDIATELY, and what’s worse is that I’d have no idea why.
What MIGHT cause me to reconsider my position on STUN is if ALL THREE of the following were true:
1) FreePBX has to support it (well, I suppose I could work around that, but I’m not really inclined to).
2) Asterisk must allow the use of MULTIPLE STUN servers, and automatically check the next in line if the first one fails.
3) And, either Digium should run their own ultra-reliable STUN server, or someone like Google should, or as a last resort, someone should publish a list of the most reliable STUN servers (ones with the lowest downtime) so we are not just taking pot shots in the dark as to which ones to use.
I WOULD like to find another service similar to whatismyip.com that would do exactly the same thing, but reliably and without switching IP addresses (EDIT: It appears my wish has been granted β see the comment by Rob Thomas below). I’m hoping they’ll stay put at the current address for a long time, but from what you are saying it sounds like that’s not the trend. If I were really a Perl programmer I might include some code to e-mail the administrator if whatismyip.com doesn’t return a valid IP address after several tries, but since I’m not that would be a bit more than I’d want to get into right at the moment.
For any “early birds” that grabbed this script in the first three or four hours after it was originally posted, I just wanted to let you know that I heard from Moshe Brevda, who pointed out one error in my script. He said, “While the db will be updated, reloading asterisk wont pull the fresh ip address. Instead, you need to reload FreePBX:”
/var/lib/asterisk/bin/module_admin reload
So, I made that change in the script. This means that early users should change this:
# RELOAD ASTERISK
`/usr/sbin/asterisk -rx “core reload”`;
to this:
# WRITE CONFIG FILES AND RELOAD ASTERISK
`/var/lib/asterisk/bin/module_admin reload`;
Sorry about that, but I don’t think I’ve ever published an article of this type where at least one bug of this type hasn’t been discovered in the first day or two. I REALLY appreciate Moshe pointing this out, and letting me know the correct way to do it.
A script to update externip has been published on FreePBX docs site in 2009:
http://www.freepbx.org/support/documentation/howtos/howto-resolving-audio-problems
Okay, obeliks, just so you know, you’re about to reach your comment limit for today. But funny you should mention that script. I’ll bet you can’t guess who wrote it in the first place (back when I knew a bit less about what I was doing, and long before FreePBX included the Asterisk SIP Settings configuration page). π I’m not saying how it wound up on that page, but I definitely knew about it. And if you have a newer version of FreePBX that has the Asterisk SIP Settings configuration page, you should NOT use that script, you should use the one on this page instead.
If you do not want to use the stun server provided by your VSP, here is a list of publicly available stun servers (including Google’s)
http://code.google.com/p/natvpn/source/browse/trunk/stun_server_list
That might be useful to someone for some reason, but it is not at all useful for FreePBX users (because, as I’ve already pointed out FreePBX doesn’t support STUN, and you still haven’t provided any easily-understandable documentation, or indeed, ANY documentation for using it with Asterisk).
It does surprise me that Google provides STUN servers, though. I wonder what inspired them to do that?
They’ve heard about a very hard to please dweller in the northern part of the country and decided to implement it π His love/hate relationship with FreePBX is legendary.
The stun docs are in res_stun_monitor.conf.sample as in http://svnview.digium.com/svn/asterisk/trunk/configs/res_stun_monitor.conf.sample .
You should also check sip.conf.sample
http://svnview.digium.com/svn/asterisk/trunk/configs/sip.conf.sample
First of all, if you are alluding to me in your first sentence, I want to make it clear that I DID NOT ask for anything related to STUN. If you will re-read my previous comments, my attitude toward it could be described as apathetic at best. So please do NOT try to make it sound like I was displeased with the fact that FreePBX doesn’t include STUN support because honestly, I can take it or leave it.
I would like to know where you saw this information or where it was discussed, if in some online forum.
Thanks for the links to the documents (finally), at least this gives enough information that someone that wanted to use STUN could do it. That said, would the use of STUN make it any less important to have an accurate Static IP address in the SIP configuration?
After reading the sample configuration file, I see one glaring problem β it apparently only supports ONE STUN server. If, for some reason, it can’t connect with that server, there’s no way to specify a “fallback” server (similar to how you can specify multiple DNS servers in your network configuration). How hard would it have been to make this module work through a list of STUN servers until they find one that’s working? So, I am still quite uninterested in this.
Look, something ELSE I can comment on! Rather than using a random dyndns host, use http://hipbx.org/myip.php — that’ll be there forever. I use it for a pile of things, and it’s not like it’s a secret!
Great, I’d much rather use that than whatismyip.com, given their record of changing addresses without warning. So to anyone who has already installed this script and would like to make this change, just change the two instances of http://automation.whatismyip.com/n09230945.asp in the script and replace them with the link Rob provided. I’ve already made the changes in the original article and script. Thanks, Rob!
Turns out that “forever” really meant “less than two years.” That is why the article has been updated to allow use of a dig command with OpenDNS, which hopefully will be around somewhat longer.
Sadly, I lost all the data on that machine, and all the backups too. Sigh. I’ve kinda sorta temporarily abandoned the project in dismay.
However, I was just looking through the logs and went ‘argh’. I’ve put it back now. Sorry 8-(
I follow all your steps but I keep getting an error…
BEGIN failed–compilation aborted at ./checkip.pl line 9.
What do I need to do
Thanks
Sorry, Fernando, I have no idea β usually Perl error messages are a bit more informative than that. It sounds like something may not have copied correctly, or you may have inadvertently saved the file with the wrong line endings for your system. If running it on a Linux box try doing:
dos2unix checkip.pl
in the same directory as the script.
Line 9 is about where the Perl modules are loaded, so it’s remotely possible that one of those is missing or corrupted, but typically if it’s a module issue Perl will tell you exactly which module it’s complaining about. Try reinstalling the modules anyway, just to be safe (one of them may not have installed completely). If all else fails, try going into one of the Perl help groups and asking what might cause such a message (and if you actually show them the code, be prepared to hear from the resident assholes who don’t like the fact that I didn’t use a much more complicated and totally unnecessary method of accessing the MySQL database β just ignore them, or tell them to eat some more prunes and fiber with breakfast, and get on with life β THAT is not the issue here). If you figure it out, I’d appreciate it if you’d post back here and let us know what the problem was.
Thank you for the info… actually i do not worry too much since my firewall can do the job for me… but thank you one more time because this issue was making me crazy for about a moth !!! and not too many people knows about this problem, I just make the changes that you mention and bingo everything it’s working nice
Instead of the perl script on Asterisk …
DynDNS.org/com (and I suspect others) don’t like a bunch of servers on the same place pinging their box to update too often.
So since I already have pfSense set up to update my DNS status, in
FreePBX/Tools/AsteriskSipSettings/ I put
Nat=yes
IP Config=Static (dynamic didn’t seem to fix the ‘no audio’ problem for me)
External IP=mydns.fromdyndns.com
Local Net=192.168.0.0/255.255.0.0 (I have a couple of subnets that need to be included so you might want to narrow yours as done in the post).
I made these changes and am still testing. Problem for me is a bunch of calls will work (yea I fixed it! Only to have a call then fail and with stooped shoulders go back to googlin’). Seems ok for now.
J S, what does this have to do with ANYTHING in this article? This is NOT a DynDNS update script, and it does NOT ping any DynDNS servers EVER. I think you have totally misunderstood the purpose of this script, or at least how it operates. EDIT: And also, DynDNS has pretty much dropped their free service, so we don’t recommend using them.
Any idea on why I would be getting this error? “Number found where operator expected at ./checkip.pl line 7”
Nope. Sorry.
I changed 5 to five and now this error is showing, “”use” not allowed in expression at ./checkip.pl line 9, at end of line
syntax error at ./checkip.pl line 9, near “use strict”
“
I haven’t had a chance to absorb everything here, but what I have read looks really fantastic. Nice clean perl script too. While reading some of your comments about whatismyip being unreliable, it made me wonder how they go about getting your IP in the first place. Well, it didn’t take me long to find this link: http://ipaddr.es/how-does-it-work/index.php
Since the contents are pretty short, I’ve included them below. So I guess anyone running a web server can stick the below code into their web server and get their own IP. Presumably if you run a web server you know how to do that. Hope this is helpful.
How does “What is my IP” work?
When you browse to a webpage, your computer tells the webpage server what your IP address is so the server can send you the HTML, graphics, and other elements of the webpage. The “What is my IP” page takes this information and displays it to you.
Our website uses PHP, a dynamic scripting language that powers thousands of websites across the internet. In PHP you can get the visitor’s IP address with this snippet of code:
1 /* This code is public domain */
2 /* Source: http://ipaddr.es */
3
4 // Save the IP to a variable
5 $ip_address = $_SERVER[‘REMOTE_ADDR’];
6
7 // To display the IP:
8 echo $ip_address;
Last updated: February 3, 2012 (1:17 AM GMT)
[Editor’s note: I tested the above, without the line numbers but with added tags, and it worked for me, but keep in mind that to be useful it has to be on a publicly accessible server that’s open to everyone. If you put it on the same server as your PBX and then you firewall any addresses that aren’t allowed to communicate with it from the outside, that won’t work because when you really need it you’ll be firewalled out! Also, here’s what I found would actually work, without the line numbers:
<?php
/* This code is public domain */
/* Source: http://ipaddr.es */
// Save the IP to a variable
$ip_address = $_SERVER[‘REMOTE_ADDR’];
// To display the IP:
echo $ip_address;
?>
Note the added tags on the first and last lines.]
NOTICE: All comments above this one were imported from the original Michigan Telephone Blog and may or may not be relevant to the edited article above.
Note in freepbx 14 the table isn’t kvstore, it’s kvstore_Sipsettings. The following has been edited for Freepbx 14:
IF YOU ARE RUNNING FREEPBX 14, it appears they have changed the location again where the IP address is stored in the database. In that case, two sections of the script need to be changed:
Change this:
# GET IP ADDRESS FROM DATABASE
my ($externip) = $connect->selectrow_array("SELECT data FROM sipsettings WHERE keyword like ?", undef, "externip_val");
To this:
# GET IP ADDRESS FROM DATABASE
my ($externip) = $connect->selectrow_array("SELECT val FROM kvstore_Sipsettings WHERE `key` = ?", undef, "externip");
Change this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE
$connect->do("UPDATE sipsettings SET data = ? WHERE keyword = ?", undef, "$ip", "externip_val");
To this:
# IP HAS CHANGED SO UPDATE IP ADDRESS IN DATABASE
$connect->do("UPDATE kvstore_Sipsettings SET val = ? WHERE `key` = ?", undef, "$ip", "externip");