How to install the BIND DNS Server using Webmin, so Asterisk extensions (hopefully) will work even when your Internet connection fails

 

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 run Asterisk you may have encountered this issue: Your Internet connection goes down, and so does your ability to call from extension to extension, even between extensions on your local network. This is a long-standing bug in Asterisk (exactly the sort of bug that drives people to try alternatives such as FreeSWITCH) but let’s say that for whatever reason you need to stick with Asterisk, so you’d like to find a way to make that bug go away.  Without going into all the technical details, the reason that calls fail is that Asterisk can’t access a DNS server.  I’ve read several reports that say the easiest solution is to install the BIND DNS server  on the same machine as your Asterisk server.  If you are also running Webmin on the server, installing and configuring BIND is a relative piece of cake.  So here’s how it’s done.  Please note that most of the images below can be enlarged by clicking on them, and that I have installed the StressFree theme in Webmin, so if it looks a little different from what you’re used to seeing, that’s probably why.

To start with, log into Webmin, click on “Servers”, then click on “BIND DNS Server” (if you don’t find it there, try looking in “Un-used Modules”):

Webmin Servers page — click on "BIND DNS Server"

Assuming you have not previously installed BIND, you’ll get a screen like this.  Just click where it says “Click here”:

Webmin BIND DNS Server error page — click where it says "Click here"

You will then see this screen come up as BIND is installed. Just let it run to completion and (assuming it installs successfully) click on “Return to BIND DNS Server” at the bottom of the page:

Webmin "Install Package" page — click on "Return to BIND DNS Server"

Next, because you don’t yet have an /etc/named.conf file, you’ll see this page.  Click the button for “Setup nameserver for internal non-internet use only” (don’t worry, we’ll fix it in the next steps), then click the bar that says “Create Primary Configuration File and Start Nameserver”:

Webmin — click "Setup nameserver for internal non-internet use only"

At this point BIND is installed and running, but it probably isn’t doing what you want it to, and your system isn’t using it. So the first thing we need to do is tell it where to go when it needs to do a DNS lookup. You should be seeing a page that looks like this — click on “Forwarding and Transfers”:

Webmin BIND DNS Server page — click on "Forwarding and Transfers"

When you get to the following screen, check “Yes” next to “Lookup directly if forwarders cannot?”  You also need to enter one or more addresses of DNS servers that BIND can access when it needs to pull a DNS record.  You might want to give some thought to which DNS servers you want to use, and in what order, before you start entering them. You can enter up to three IP addresses of DNS servers, and then click “Save”. This will throw you out to the previous screen, and if by some chance you want to enter even more DNS servers, you can click on “Forwarding and Transfers” again to come back and enter up to three more servers, until you are finished.  In this example, I have already entered the IP addresses of my router’s DNS Server as the top priority pick,  followed by two Google DNS Server addresses.

Webmin — BIND DNS Server — Forwarding and Transfers page

Once you have done this, you are through configuring BIND directly, but there are two more things we need to do. The first is to make sure that the BIND server starts each time we restart the machine. To do that, go to Webmin’s “System” page and then click on “Bootup and Shutdown”:

Webmin System page — click on "Bootup and Shutdown"

This is a long page so I’m not showing all of it — what you have to do is find the entry for named and check the box next to it:

Webmin Bootup and Shutdown page — check the box next to "named"

Then go to the bottom of the page and click “Start on Boot”:

Bottom of Webmin Bootup and Shutdown page — click "Start on Boot"

At this point BIND is running, and should be using the correct DNS servers, and is set to start at bootup, but your server still isn’t using it for its DNS queries. To get it to do that, go to Webmin’s “Networking” page and click on “Network Configuration”:

Webmin Networking page — click on "Network Configuration"

Once on the Network Configuration page, click on “Hostname and DNS Client”:

Webmin Network Configuration page — click on "Hostname and DNS Client"

Once on the Hostname and DNS Client page, what you need to do is make the first entry in the DNS Servers list 127.0.0.1. If you trust BIND to always be operating, that’s the only entry you need. I didn’t quite trust BIND that much (actually, what I didn’t trust was my ability to set this up correctly) so I set the DNS server in the router as the secondary DNS address. You could use any DNS server as the secondary, or you could choose to just enter the 127.0.0.1 address to use BIND and let it go at that. Personally, I feel a lot more comfortable having a “fallback” DNS. Don’t forget to click “Save” when you are finished making changes here:

Webmin Hostname and DNS Client page - 127.0.0.1 must be first DNS server

That’s all there is to it, as far as I know (if you think I’ve missed anything or done something wrong, the comment section is open!). If you’re like me, the next question you will have is, “How do I know it’s working?” And the easiest way to do that is to go to a Linux command prompt and “dig” some site you have not been to recently twice in a row. Here’s an example, using cnn.com — the part we are interested in is in red:

dig cnn.com

; <<>> DiG 9.3.6-P1-RedHat-9.3.6-4.P1.el5_5.3 <<>> cnn.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8274
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 13, ADDITIONAL: 9

;; QUESTION SECTION:
;cnn.com.                       IN      A

;; ANSWER SECTION:
cnn.com.                287     IN      A       157.166.224.25
cnn.com.                287     IN      A       157.166.224.26
cnn.com.                287     IN      A       157.166.226.25
cnn.com.                287     IN      A       157.166.226.26
cnn.com.                287     IN      A       157.166.255.18
cnn.com.                287     IN      A       157.166.255.19

;; AUTHORITY SECTION:
.                       76691   IN      NS      i.root-servers.net.
.                       76691   IN      NS      j.root-servers.net.
.                       76691   IN      NS      k.root-servers.net.
.                       76691   IN      NS      l.root-servers.net.
.                       76691   IN      NS      m.root-servers.net.
.                       76691   IN      NS      a.root-servers.net.
.                       76691   IN      NS      b.root-servers.net.
.                       76691   IN      NS      c.root-servers.net.
.                       76691   IN      NS      d.root-servers.net.
.                       76691   IN      NS      e.root-servers.net.
.                       76691   IN      NS      f.root-servers.net.
.                       76691   IN      NS      g.root-servers.net.
.                       76691   IN      NS      h.root-servers.net.

;; ADDITIONAL SECTION:
b.root-servers.net.     386178  IN      A       192.228.79.201
d.root-servers.net.     402826  IN      A       128.8.10.90
d.root-servers.net.     230000  IN      AAAA    2001:500:2d::d
f.root-servers.net.     370827  IN      A       192.5.5.241
g.root-servers.net.     463754  IN      A       192.112.36.4
h.root-servers.net.     374116  IN      A       128.63.2.53
h.root-servers.net.     517382  IN      AAAA    2001:500:1::803f:235
j.root-servers.net.     185528  IN      A       192.58.128.30
j.root-servers.net.     578747  IN      AAAA    2001:503:c27::2:30

;; Query time: 26 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Sep 16 12:45:41 2011
;; MSG SIZE  rcvd: 512

# dig cnn.com

; <<>> DiG 9.3.6-P1-RedHat-9.3.6-4.P1.el5_5.3 <<>> cnn.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8277
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 13, ADDITIONAL: 9

;; QUESTION SECTION:
;cnn.com.                       IN      A

;; ANSWER SECTION:
cnn.com.                223     IN      A       157.166.255.19
cnn.com.                223     IN      A       157.166.224.25
cnn.com.                223     IN      A       157.166.224.26
cnn.com.                223     IN      A       157.166.226.25
cnn.com.                223     IN      A       157.166.226.26
cnn.com.                223     IN      A       157.166.255.18

;; AUTHORITY SECTION:
.                       76627   IN      NS      c.root-servers.net.
.                       76627   IN      NS      d.root-servers.net.
.                       76627   IN      NS      e.root-servers.net.
.                       76627   IN      NS      f.root-servers.net.
.                       76627   IN      NS      g.root-servers.net.
.                       76627   IN      NS      h.root-servers.net.
.                       76627   IN      NS      i.root-servers.net.
.                       76627   IN      NS      j.root-servers.net.
.                       76627   IN      NS      k.root-servers.net.
.                       76627   IN      NS      l.root-servers.net.
.                       76627   IN      NS      m.root-servers.net.
.                       76627   IN      NS      a.root-servers.net.
.                       76627   IN      NS      b.root-servers.net.

;; ADDITIONAL SECTION:
b.root-servers.net.     386114  IN      A       192.228.79.201
d.root-servers.net.     402762  IN      A       128.8.10.90
d.root-servers.net.     229936  IN      AAAA    2001:500:2d::d
f.root-servers.net.     370763  IN      A       192.5.5.241
g.root-servers.net.     463690  IN      A       192.112.36.4
h.root-servers.net.     374052  IN      A       128.63.2.53
h.root-servers.net.     517318  IN      AAAA    2001:500:1::803f:235
j.root-servers.net.     185464  IN      A       192.58.128.30
j.root-servers.net.     578683  IN      AAAA    2001:503:c27::2:30

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Sep 16 12:46:45 2011
;; MSG SIZE  rcvd: 512

Notice how on the first run, it takes 26 msec to do the lookup, because BIND doesn’t have that address cached yet, whereas on the second run it only takes 1 msec to do the lookup!  Could that perhaps improve system performance?  I’ll bet it could! And the SERVER line tells us that it is indeed using our BIND server (127.0.0.1) – if it were using, say, our router’s DNS server then that line would show this:

;; SERVER: 192.168.0.1#53(192.168.0.1)

The idea here is that when your Internet connection takes a dive, Asterisk will still be finding a working DNS server and therefore won’t tank.  That, at least, is the theory I’ve seen on several web sites.  The ONLY thing I am showing here is how to set up BIND using Webmin, and I won’t even guarantee that I’m doing that 100% correctly.  I definitely do not guarantee that it will actually work as intended — you’ll have to test that yourself.  Doing a real test would mean disconnecting your cable or DSL modem, etc. from your router for several hours or days to see if the phones continue to work, and in most households or businesses that idea will go over like a lead balloon.  However, feel free to give it a good test if you like and report the results in the comments.

You may wonder why I selected “Setup nameserver for internal non-internet use only” in the fourth screenshot.  Obviously, that description is not entirely accurate.  The real difference is that if you select that instead of the default “Setup as an internet name server, and download root server information”, it won’t create a “root” DNS zone, which you simply don’t need for this application.  You can use the other option if you want to, but it will download additional information and increase the complexity of your setup.  Either way, you should be able to access the Internet, because we set up DNS forwarding.  If by some chance this BIND server is going to act as a nameserver for your entire network, and you don’t mind the additional traffic and complexity (and it’s the additional traffic that scares me the most, since I have no idea what it’s actually downloading nor how often it’s doing it), then by all means feel free to use the second option.  All I will say is that I used the first. and it works fine, and I’ve seen at least one instance where this same thing is set up using a method other than Webmin, and except for the order of statements it uses an /etc/named.conf file that is identical to what Webmin produces when configured as I have shown here (in other words, no “zones” at all).  I’m just waiting for some Linux purist to say this isn’t the “right” way to do this but keep the goal in mind here — all we are trying to do is work around a bug in Asterisk that should have been fixed years ago, not set up a DNS server to feed an entire subnet.  But again, you can feel free to use whichever of the options you like — it should work either way.

(By the way, if after reading the above you have “setup remorse” — you know, that feeling you get after you’ve installed something that you should have picked a different option — you can get a “do-over” by simply deleting or moving/renaming /etc/named.conf.  If you then exit Webmin’s BIND module and come back in, it should see that named.conf doesn’t exist and start you over at the fourth screen shown above.  Of course, you will lose anything you have already configured from within that module.  If you originally selected the option to download the root server information, I think that’s at least partly stored in the file /etc/db.cache, so you could move or remove that file to make sure it’s not used, however I’m not sure if any other files are or were also downloaded.  That particular file is very small so I’m not worried about that one per se, it’s just that the way things are worded on a couple of pages I read, I don’t know if that’s all it downloads, or if at some point in the middle of the night it rises up and tried to cache all the DNS information for the Internet, or just exactly what it does.  Sometimes I wish people would just give a sentence or two of additional information, so you have a better idea of what’s the right thing to do when you’re setting up something like this.)

Now, if you are a True Linux Geek who somehow stumbled across this article, and are disappointed that it isn’t much more complicated, I’ll refer you to this page.  If you can figure all THAT out, you should be getting paid the big bucks as the networking expert that you are! 🙂

A real help for Linux users with bad memories: Aliaser — take control of your aliases on Linux

 

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.
Tux, the Linux penguin
Image via Wikipedia

Here’s a program that may be useful for those of you who, like me, sometimes find ourselves at a Linux command prompt trying to recall the syntax of a command we use frequently (because, you know, it would never have occurred to the designers of Linux to actually implement commands with names that have a clear meaning in plain English):

Alias are a great tool to help increment your productivity on the terminal with bash (or any shell program you’re using), but usually we are too lazy to think at what are the most common, or long commands that we use frequently and prepare an alias for them.

And so someone has done a small piece of software to do this job: aliaser

Aliaser helps you identify frequently typed commands and creates bash aliases for them. Aliaser analyses your bash history and helps you identify commands that you use frequently.

Full article (with installation instructions) here.

One thing they forgot to mention is that once you’ve added an alias, it won’t actually be available for use until you log out and then log back in.  Also, you can delete the aliaser file and temporary directory from your /tmp directory once installation is complete.  If you ever want to uninstall aliaser, just remove the three lines added to your .bashrc file, remove the ~/.aliaser directory, and remove the /usr/bin/aliaser file.

One way I find this useful is to make commands I can’t remember into ones that that I can remember.  For example, I did this:

aliaser add processes “ps awx”

The Linux purists are probably rushing to comment that I just turned a six character command into a nine character one.  Yes, BUT, I can actually remember the word “processes”, whereas I cannot remember the options I need to use after “ps” to get the output I want. The designers of Linux seem to not realize that some of us users have really bad memories.  Another use for this is turning arcane Linux commands into the equivalent Windows commands that you’re familiar with.  You could do this:

aliaser add dir “ls -al”

So that when you type “dir”, you get a directory listing similar to what you are used to.

If you can’t even remember the aliases you’ve created (yeah, my memory really is that bad some days), just use aliaser show to see all the aliases you’ve added.

The Linux equivalent of Little Snitch, ZoneAlarm, and similar per-application firewalls?

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.

EDIT: This article is very old and outdated. For more current information, see OpenSnitch: The Little Snitch application like firewall tool for Linux.

If you are a Mac user, you’ve probably heard of Little Snitch.  It’s a commercial (as in, not free) program that lets you allow or deny connections to the Internet from individual applications.  One reason for using such a program is to detect software that should have no reason to connect to the Internet nevertheless attempting to do so.  For example, you download a free screensaver (dumb move to start with) and it sends all the personal information it can find on you to some group of hackers on the other side of the world.  A program like Little Snitch would let you know that the screensaver  is trying to connect to the Internet, and allow you to deny that connection.  In the Windows world, I believe that ZoneAlarm has a similar capability, and it’s also a commercial (as in, not free) program.

Leopard Flower personal firewall for Linux OS screenshot
Leopard Flower personal firewall for Linux OS screenshot

It appears that these is a similar program for Linux users, and it IS free!  It’s called Leopard Flower and it’s described as a “Personal firewall for Linux OS (based on libnetfilter_queue) which allows to allow or deny Internet access on a per-application basis rather than on a port/protocol basis.”

Looking at the screenshot it appears to have very much the same per-application blocking functionality you’d get in one of those other programs.  I have not personally tried it yet, but I wanted to create a post about it so if someday in the future I am trying to remember the name of this program, I’ll know where to find it (yes, this blog does sort of serve as my long-term memory!).  🙂

Since this article was originally published, I have been made aware of another similar application called Douane: Linux personal firewall with per application rule controls – here are a couple of screenshots:

Douane personal firewall for GNU/Linux screenshot
Douane personal firewall for GNU/Linux screenshot
Duane configurator screenshot
Duane configurator screenshot

The only downside to this one is that as of this writing the only available package is for Arch Linux but if you want to try to build it for a Ubuntu or Debian system, they provide a page showing the needed dependencies.

There is an older similar program called TuxGuardian but apparently is hasn’t been updated since 2006, so I have no idea if it will even work with current versions of Linux. And as for you Android users, try the NoRoot Firewall app.

If your Linux-based PC with NVIDIA graphics started booting to a black screen or text only, here is the fix — maybe!

 

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.
Image representing NVidia as depicted in Crunc...
Image via CrunchBase

I’ve seen this happen several times now on Ubuntu-Linux based systems that have NVIDIA graphics.  What happens is that “Update Manager” pops up and tell you there are updates for your software, and you accept them.  It then tells you that your system has to be rebooted.  And when you do that, you get no video, or text only.  What probably happened was that the updates you installed included an update to the Linux kernel, and the NVIDIA graphics driver currently installed on the system was compiled against the OLD kernel.

Note that this generally can only happen if you manually updated the NVIDIA graphics driver at some point. If you always installed it from the standard repositories for your distribution, you’ll probably never see this issue. So a word to the wise — when you finally get around to doing an upgrade of your Linux distribution, try to avoid manually installing the NVIDIA graphics driver. Instead, let the distribution pull it from its repository. After that, you should not have this issue in the future. By the way, if you currently are running Ubuntu, we recommend upgrading to Linux Mint rather than a newer version of Ubuntu. Linux Mint is very similar to Ubuntu, but leaves out some of the things that users seem to hate about newer releases of Ubuntu. More to the point, they are not currently talking about switching their base graphics system from the X window server system to a new display manager, which I have a feeling might cause problems for some NVIDIA graphics users.

But if you’re not yet ready to do a full reinstall of Linux, the fix for this problem is easy IF you had the foresight to set up SSH access to your Linux system BEFORE the trouble started.  If you didn’t, and you’re not a true Linux geek, you may be kind of screwed.  So if you’re reading this and your system is working fine, and you haven’t yet set up SSH access, you may want to do that.  There are several sites that tell you how to do that; here are two that I found using Google:

Basic SSH Setup On Ubuntu 10.04 Lucid Lynx Using OpenSSH Server
SSH—OpenSSH—Configuring

If you didn’t do this beforehand, you may still be able to do it if you can get to a command prompt.

Anyway, the actual fix is to (re-)install the latest NVIDIA driver for your system. They will be compiled against the new Linux kernel and then everything should work fine. To find the correct NVIDIA driver, go to the NVIDIA Driver Downloads page, and use the dropdowns to select the correct driver for your system.  Download it to your local system, then upload it to your Linux PC (if you have SSH access working then you can use an SFTP client, such as WinSCP or Transmit, to upload your driver file).  Once you have it on your PC, from a command prompt navigate to the directory where you put the driver and then change the permissions to make it executable:

sudo chmod +x driver_upgrade_script_filename

Now try running the script (it should have a .run extension):

sudo ./driver_upgrade_script_filename

It should not complain that the Gnome Display Manager or KDE Display Manager is running (if it were, you wouldn’t be in a state of near-panic right now), but if you were just doing a regular update you’d have to do this when the GDM/KDM is stopped. For a guide that covers that scenario, see How To Install Official Nvidia Drivers in Linux, or just know that to stop the display manager,

sudo /etc/init.d/gdm stop

should stop the Gnome Display Manager, or if you’re using KDE then the command would be

sudo /etc/init.d/kdm stop

Most sources I’ve seen suggest that you answer yes to any questions the installer may ask. The only one I’d be cautious about is letting it create a new xorg.conf if you are using a customized one (which you may well be if you’ve used any of my previous HTPC-related articles). If you have edited xorg.conf, then I’d make sure you at least have a backup before letting the installer create a new one, so you can revert back to your custom one (or compare the two and insert your customizations into the new one) if necessary.

Under Ubuntu, you may get a message similar to “Provided install script failed”. That will happen every time you update the NVIDIA driver this way and it is normal. Just ignore it and continue the installation. If you get “Error locating kernel source”, run  sudo apt-get install kernel-source  from the command prompt, then run the driver upgrade script again.

When the installer has successfully finished, reboot the system and when it comes back up, hopefully you should be happy again!

Problems you may encounter when attempting to install phpMyAdmin on your Centos server, and how to solve them

 

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 published in August, 2011 and may contain outdated information.

phpMyAdmin logo
Image via Wikipedia

I just spent an interesting couple of hours trying to install phpMyAdmin on an Asterisk server running CentOS 5.5. As I encountered each problem and solved it, I had to wade through a lot of pages that weren’t applicable to my installation, etc. Since many readers of this blog run similar configurations I thought I’d just list the hiccups I encountered, and what I had to do to solve them. Note that some distributions come with phpMyAdmin already installed, so make sure you don’t already have it before you try to install it!

NOTE: Think carefully about whether you really want to follow the instructions below, particularly if it requires adding a repository. If you do that, make sure you only install the software you actually need from that repository, then disable it (set enabled=0). If you don’t do that, you could easily get into a situation where some of your curent software (such as PHP) simply will not upgrade no matter what you do. And if you are running a PBX “install and go” distribution, they may specifically warn you not to add repositories, or it will break your installation, so don’t do it!

If you do anything suggested below, you do it at your own risk!

• yum install phpmyadmin doesn’t work — try using the dag repository — there are several pages on the Web that tell how to do this. Use Google to search for “how to enable the dag repository” (without the quotes) if you need help. The basic idea is you need to create a file called /etc/yum.repos.d/dag.repo (with the proper permissions, ownership, etc.) and put something like this inside:

[dag] name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=1
enabled=1

BUT you also need to install a GPG key, and getting THAT can be a bit of a problem. Some instructions will tell you to do this:

rpm –import http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt

That link no longer works, and you have to do this instead:

rpm –import http://apt.sw.be/RPM-GPG-KEY.dag.txt

But for some people even THAT doesn’t work, in which case it’s suggested you use wget to obtain the file, then import it:

wget http://apt.sw.be/RPM-GPG-KEY.dag.txt
rpm –import RPM-GPG-KEY.dag.txt

I’m being a bit non-specific because the instructions could change, and I’d prefer you find a current reference on how to enable this repository. Also, some may prefer to install RPMforge, which is a collaboration of Dag and other packagers. Regardless of the effort involved, I do suggest you install phpMyAdmin using yum, because it will install everything in the correct locations for CentOS, and you don’t have to compile it or anything like that.

Note that when you do install phpMyAdmin using yum, it may also install required dependencies such as libmcrypt and php-mcrypt (another advantage to using yum).

• You don’t have permission to access /phpmyadmin/ on this server.

Go to /etc/httpd/conf.d/phpmyadmin.conf
Under the line:
Allow from 127.0.0.1
You could add a line to allow access from your local network, for example:
Allow from 192.168.0.0/255.255.255.0
(But use values appropriate to your network).

If you are accessing the box remotely, then add a line allowing access from your IP address. Be VERY careful, because you don’t want to let the entire world into your databases!

• Existing configuration file (./config.inc.php) is not readable.

If you’re doing this on a system running FreePBX, scroll down to where I discuss changing the ownership of all phpMyAdmin-related files and directories to be the same as the MySQL user. Otherwise, the easiest solution (though not necessarily the most secure) is to change the permissions of the file /usr/share/phpmyadmin/config.inc.php from the default of 640 to 644 (add user read permission). If no one can get to your system from outside your local network, this probably isn’t an issue, but if anyone has a better idea on this, feel free to leave a comment.

• “Error
The configuration file now needs a secret passphrase (blowfish_secret).”

Open /usr/share/phpmyadmin/config.inc.php and find this section:

* This is needed for cookie based authentication to encrypt password in
* cookie
*/
$cfg[‘blowfish_secret’] = ‘oh my this is such a wonderful passphrase‘; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */

Insert any phrase you like (within reason) between the second pair of single quotes in the last line shown above (but don’t use ‘oh my this is such a wonderful passphrase‘, I just inserted that as an example.  Be creative!).  Don’t worry, this isn’t something you’ll actually have to type in every time you want to use phpMyAdmin.

– Access denied for user ‘root’@’localhost’ (using password: YES)

You don’t login as root, you use your MySQL username and password. In FreePBX-based systems these can be found in /etc/amportal.conf, in the AMPDBUSER and AMPDBPASS settings. BUT… if you enter a wrong user name before logging in correctly, it may have already set a cookie with that username and password and then you won’t be able to get in even if you DO use the correct username and password. The solution is to clear all browser cookies for the address of your server, then try again — and make sure you get it right this time! 😉

I will note here that you can avoid some of these cookie-related issues, probably including those mentioned above, by going into /usr/share/phpmyadmin/config.inc.php and finding this section:

/* Authentication type */
$cfg[‘Servers’][$i][‘auth_type’] = ‘cookie’;

If your system is behind a hardware firewall or is otherwise VERY secure, you could change the auth_type from ‘cookie’ to something else, such as ‘http’. This will save you a lot of frustration during the login process, but at the possible expense of making your database less secure.  For those concerned about security, a document on the phpMyAdmin wiki advises you to “See the page on Security or the multi–user sub–section of the FAQ for additional information, especially FAQ 4.4.”  I personally found their security documentation rather useless, because they make a lot of suggestions but provide no specific examples of how to implement those suggestions.  Anyway, I personally feel that as long as a system is behind a good firewall that doesn’t permit anyone on the “outside” to access phpMyAdmin, ‘http’ is a good compromise between a security model that might drive you crazy (‘cookie’) and one of the other models that’s fairly insecure, such as ‘config’ (which some consider insecure because it stores your server username and password in plain text).  However, if your system is otherwise VERY secure and you just don’t want to have to enter a password to use phpMyAdmin, then it is possible to change the ‘auth_type’ to ‘config’ and (in the same config file), look for these lines:

/*
 * End of servers configuration
 */

And just above those lines, insert these lines:

$cfg[‘Servers’][$i][‘user’] = ‘mysqluser’;
$cfg[‘Servers’][$i][‘password’] = ‘mysqlpassword’;

Change mysqluser and mysqlpassword to the correct vales for your system (on a FreePBX-based system, these are the values in /etc/amportal.conf mentioned above).  I do not recommend using ‘config’ because it is less secure (be sure to read the page on Security mentioned above), but it’s up to you to decide how secure you want your system to be.

(I’m fully aware that any objections to storing the user and password values in plain text in the phpMyAdmin config.inc.php fall a bit flat when you realize the same values are stored in plain text in amportal.conf, but I also feel as though the fewer places those values are exposed, the better.  Why give potential attackers one more place to find this information?)

• phpMyAdmin – Error
Cannot start session without errors, please check errors given in your PHP and/or webserver log file and configure your PHP installation properly.

Check your /var/log/httpd/error_log – in my case, the first error message of each set contained a phrase like “open(/var/lib/php/session/sess_somerandomstring, O_RDWR) failed: Permission denied (13)” and I figured that the problem was another permissions issue.

On some sites I have found a suggestion that you change the ownership of all phpMyAdmin-related files and directories to be the same as the MySQL user (in the case of an Asterisk/FreePBX system, that would be asterisk:asterisk). On a FreePBX-based system, you could try this (check to make sure these are the correct paths before doing this):

chown asterisk:asterisk /usr/share/phpmyadmin -R
chown asterisk:asterisk /var/lib/php/session -R

If that doesn’t resolve the issue (or you’re doing this on a system that’s not running FreePBX), perhaps the easiest solution (though not necessarily the most secure) is to change the permissions of the offending file. If you have the same issue I had, try changing the permissions of the directory /var/lib/php/session from the default of 770 to 777 (add full user permissions).

Strangely, this one didn’t show up until after I’d successfully run phpMyAdmin a few times. Go figure. Also, after fixing this, I had to delete cookies again (as mentioned in the previous item) before I could log in, but that was when I still had the ‘auth_type’ set to ‘cookie’ (another reason I decided to change that to ‘http’).

Found and solved any other “gotchas” while installing phpMyAdmin under CentOS? Think I could have solved a problem in a better way? Feel free to share your solutions in the comments.

EDIT: There is one other thing that can happen after you install or update PHP on your system (as might happen if you let a FreePBX-based distribution do an upgrade).  You may start seeing PHP warning messages such as:

PHP Warning:  PHP Startup: mcrypt: Unable to initialize module
Module compiled with module API=20050922, debug=0, thread-safety=0
PHP    compiled with module API=20060613, debug=0, thread-safety=0
These options need to match
 in Unknown on line 0

If that happens try updating the dependencies that came with phpMyAdmin, for example:

yum update libmcrypt
yum update php-mcrypt

It was the second of those two that vanquished the PHP warning messages for me.

And why did I NEED to install phpMyAdmin, you ask?  Well, because someone (ahem) made a slight configuration error and caused an endless loop, that within the space of about ten seconds or so, generated over a THOUSAND bogus records in the ‘asteriskcdr’ (Call Detail) database.  The only easy way to I knew of at the time to clean them out was phpMyAdmin (since I don’t “speak” MySQL), but I don’t recommend you attempt something like that unless you know what you’re doing, because one wrong move and you could delete your entire FreePBX database (trust me, that would be a VERY bad thing!). In retrospect I probably could have used Webmin, since it also has the ability to access the MySQL database, but I didn’t think of that at the time.

A Perl script to rewrite the "static" IP address in the FreePBX Asterisk SIP Settings when it is changed by your ISP

 

Important
This is a heavily 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 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).

FreePBX: Asterisk SIP Settings page, NAT Settings (Public IP Option)

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.

FreePBX: Asterisk SIP Settings page, NAT Settings (Dynamic IP Option)

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.

FreePBX: Asterisk SIP Settings page, NAT Settings (Static IP Option)

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 (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 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.

ASRock Vision 3D or other Home Theater PC and "Sparklies"

 

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.

Just a quick note that may save someone a lot of frustration.  This problem was observed with an ASRock Vision 3D system but could affect other HTPC’s as well.

If you are getting single-color (probably red) “sparklies” (pinpoints of light that don’t belong) in certain scenes, or when viewing certain static images, it may NOT be a software problem.  It seems that on certain systems the HDMI output may be running a little “hot” (not referring to temperature, but rather output levels) and may be overdriving the HDMI input of a connected TV.  To the best of my knowledge, there is absolutely nothing you can do to fix this in software – it’s a hardware problem, perhaps a hardware defect.

But what you can try is attenuating the HDMI signal just a bit.  If you have a HDMI switch (preferably an unamplified one), try making the connection through that instead of directly to the TV.  In at least one case, that solved the problem.  Or, if you have a very long but unamplified HDMI cable handy, you could try that (remember, any additional amplification of the signal will probably only make the problem worse!).

And if you found this article by searching on “ASRock Vision 3D”, I will just say that in my opinion, it’s not worth the price they are currently getting for it.  It’s kind of a hassle to get it working under Ubuntu Linux, and although it costs about two to three times as much as, say, an Acer Asprie Revo, you don’t get two to three times the performance (in my admittedly subjective evaluation), and you might get the HDMI output issue mentioned here.  Whether it works any better under Windows I wouldn’t know – even at the price they charge they don’t supply a copy of Windows, so we opted to use Ubuntu, which worked fine back when we set up the Acer Aspire Revo’s (if we were doing it today, we’d probably choose Linux Mint instead).  In my personal opinion, you might be a lot happier with something else unless you are a real Linux geek and don’t mind tinkering until you can get everything working right, or perhaps if you plan to splurge for a copy of Windows — again, can’t say if that would work any better.

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.