Link: Raspberry Pi NAS

Why would you want to run a file server off a Raspberry Pi? Maybe you want a small server that is always on and low voltage. If you need something that you can send and recieve files to and from than this might be your solution. The Raspberry Pi is low voltage running at just 5.0V ±5%. This means that your server will end up costing you around $5 a year.

Full article here:
Raspberry Pi NAS (CMDann.ca)

Links: How To Set Up A Wireless Hotspot (Access Point Mode) That Supports Android In Ubuntu

A wireless hotspot enables a computer to serve as a router over Wi-Fi. Ubuntu lets you easily create a wireless hotspot by using the Network Manager, but it uses an ad hoc network and most Android and Windows Phone devices can’t connect to such networks.
For this reason, I’ve created (in collaboration with Satya) a script called AP-Hotspot that automatically creates an infrastructure (Access Point mode) wireless hotspot in Ubuntu that should work with Android and Windows Phone devices. The script uses hostapd and dnsmasq and it requires Access Point mode support for your wireless card – AP-Hotspot checks for this automatically and won’t run if your wireless card doesn’t support it.

Full article:
How To Set Up A Wireless Hotspot (Access Point Mode) That Supports Android In Ubuntu (Linux A.I)
Alternate location of above article (WebUpd8)

If you don’t feel comfortable running a script, the script is based on these instructions, so if you want you can do it manually:

[GUIDE] Making infrastructure wifi hotspot on ubuntu 12.04/12.10 (xda developers)

Enabling a SOCKS proxy via SSH tunnel in Ubuntu or Mac OS X at startup

There are two ways to enable a SOCKS5 proxy at startup in Ubuntu. For either to work, you must have previously configured ssh public/private key authentication, so make sure that works and that you can do a “normal” ssh login without entering a password. Note that the second method described below is better because it is persistent – if the connection goes down, it will attempt to reconnect automatically.

Method 1 (Ubuntu and similar versions of Linux only):

I’ll briefly show the first method, but keep in mind that if the ssh connection is lost, it will not automatically reconnect.

First install screen from the standard repository if you have not done so already, and change the permissions of /run/screen to 775.

In Ubuntu’s Startup Applications Preferences, add this command, replacing the italicized parts with the correct values:

screen -dmS tunnel ssh username@server_address -D local_socks_proxy_port

tunnel” can be any word you like, “username” is your account name on the remote server, “server_address” is the address of the remote server, and “local_socks_proxy_port” is the port number your local software will use when connecting to the SOCKS proxy (7777 is a frequently-used choice).

Ubuntu Startup Applications Preferences - adding SOCKS proxy
Ubuntu Startup Applications Preferences – adding SOCKS proxy

Method 2:

Ubuntu users, first go into the Ubuntu Software Center and search for autossh (other Linux users, check your repository for the autossh package):

Ububtu Software Center - autossh

If you click “More Info” you can read the description:

Ubuntu Software Center - autossh - details

Go ahead and install it, and after installation it will show you which programs can be run:

Ubuntu Software Center - autossh - installed

Mac OS X users, there is an autossh package for recent versions of OS X among the Rudix packages. Be sure to select your version of OS X in the left-hand sidebar, then download the autossh package for your version of OS X and then click on the downloaded package to run the installer:

Rudix autossh installer

Click Continue and you will see an “Important Information” screen, the text of which is copied to the bottom of this article in case you want to review it. Note that you do NOT need to do the build procedure shown there; you just continue the installation as you would any other OS X software you have downloaded.

Rudix autossh Important Information screen

Whether you are installing in Linux or OS X, after you complete the installation the next thing to do is open a terminal window and run autossh manually one time. Remember, you must have previously configured ssh public/private key authentication for this to work. The reason for running autossh manually the first time is that a window will pop up asking you to approve the connection and accept the RSA key. So open a terminal window and run a line of this form:

Ubuntu: autossh -f -N username@server_address -D local_socks_proxy_port
Mac OS X: autossh -M 0 username@server_address -D local_socks_proxy_port

As in the first method, “username” is your account name on the remote server, “server_address” is the address of the remote server, and “local_socks_proxy_port” is the port number your local software will use when connecting to the SOCKS proxy (7777 is a frequently-used choice, but it can be any unused port numbered 1080 or above). If the popup appears asking you to approve the connection, answer “yes”, and that should be the last time you see that dialog (unless, perhaps, some drastic changes are made at the server).

Note that under OS X, we could not get the -f option to work, even though it’s supposed to. When we tried to use it, no ssh connection was opened (as determined by watching Activity Monitor). So, unfortunately, you will need to leave a terminal or iTerm window open with autossh running in it, unless you can figure out some way to make backgrounding it work. This was in OS X Lion; perhaps the -f option works in other versions. Feel free to experiment.

After running autossh from a terminal window, open your browser and make sure the SOCKS proxy works. How you configure it will vary by browser. For example, under Firefox you’d open the Preferences pane, select Advanced, click the Network tab, and then click the Settings button. In the window that opens you’d select Manual Proxy Configuration, then for SOCKS Host you can use localhost, and for Port the local_socks_proxy_port number you set when you started autossh. Select SOCKS v5 as the proxy type. In the “No Proxy for:” window, enter some sane values for your network — generally these will include your local machine and other addresses on your local network. For example (assuming your local network addresses are in the 192.168.x.x range):

localhost, 127.0.0.1, 192.168.0.0/16

In Google Chrome you can use an extension such as Proxy SwitchySharp to configure your proxy settings.

After saving those settings, go to a site that will show you the IP address that it thinks you are coming in from, such as http://ipchicken.com/ – make sure that the address it shows is that of the system you are using for your proxy, and not your local address.

Once you are sure it is working, in Ubuntu you can open Ubuntu’s Startup Applications Preferences and add the same line you typed in the terminal window.

Add autossh to Startup Applications

Under OS X it’s a little more complicated. If you use iTerm, you could create a Profile (similar to a bookmark) and for the command use the same command you used in the terminal window, but specify the full path to autossh, e.g.:

/usr/local/bin/autossh -M 0 username@server_address -D local_socks_proxy_port

iTerm profile setup for autossh

Name your profile something meaningful, and make sure that when you click on the profile in the sidebar to runs autossh and opens the connection. The use the AppleScript Editor to build a script that will start iTerm and open the profile. Your script could look something like this:

tell application "iTerm"
activate
tell the current terminal
launch session "Profile_name"
delay 3
tell the last session
set name to "Profile_name - SOCKS proxy using autossh"
end tell
end tell
end tell

Creating iTerm launcher script in AppleScript Editor

Substitute the name you gave the profile for the two occurrences of Profile_name in the sample script. Compile the AppleScript and when it compiles with no errors, save it as an Application. Make sure it works as intended (starts up iTerm and loads the Profile that runs autossh), then simply set that application to run at startup (Under System Preferences | Users & Groups | (select current user) | Login Items).

Now your SOCKS5 proxy should start up each time you reboot your system, and if the tunnel goes down it should reconnect within a few minutes. To learn more about autossh, open a terminal window and type man autossh, or see any of these articles (note that some of them overly complicate the process of setting up the tunnel):

Permanent SSH Tunnels with autossh (Linuxaria)
Using SSH for IPv6-enabled HTTP Proxying (see comment below main article – The Daily Build)
SSH Socks proxy with Chromium 18 (krenel.org)
Autossh Startup Script for Multiple Tunnels (Surnia Ulula)

Here is the text from the “Important Information” screen in the Rudix autossh installer;

autossh Version 1.4
-------------------

Building and Installing Autossh
--------------------------------

With version 1.4, autossh now uses autoconf. So the build procedure
is now the well-known:

./configure
make
make install

Look at autossh.host for an example wrapper script.

Usage
-----
autossh -M [:echo_port] [-f] [SSH OPTIONS]

Description
-----------

autossh is a program to start a copy of ssh and monitor it, restarting
it as necessary should it die or stop passing traffic.

The original idea and the mechanism were from rstunnel (Reliable SSH
Tunnel). With version 1.2 the method changed: autossh now uses ssh to
construct a loop of ssh forwardings (one from local to remote, one
from remote to local), and then sends test data that it expects to get
back. (The idea is thanks to Terrence Martin.)

With version 1.3, a new method is added (thanks to Ron Yorston): a
port may be specified for a remote echo service that will echo back
the test data. This avoids the congestion and the aggravation of
making sure all the port numbers on the remote machine do not
collide. The loop-of -forwardings method remains available for
situations where using an echo service may not be possible.

autossh has only three arguments of its own:

-M [:echo_port], to specify the base monitoring port to use, or
alternatively, to specify the monitoring port and echo service
port to use.

When no echo service port is specified, this port and the port
immediately above it (port# + 1) should be something nothing
else is using. autossh will send test data on the base monitoring
port, and receive it back on the port above. For example, if you
specify "-M 20000", autossh will set up forwards so that it can
send data on port 20000 and receive it back on 20001.

Alternatively a port for a remote echo service may be
specified. This should be port 7 if you wish to use the
standard inetd echo service. When an echo port is specified,
only the specified monitor port is used, and it carries the
monitor message in both directions.

Many people disable the echo service, or even disable inetd,
so check that this service is available on the remote
machine. Some operating systems allow one to specify that the
service only listen on the localhost (loopback interface),
which would suffice for this use.

The echo service may also be something more complicated:
perhaps a daemon that monitors a group of ssh tunnels.

-M 0 will turn the monitoring off, and autossh will only
restart ssh on ssh exit.

For example, if you are using a recent version of OpenSSH, you
may wish to explore using the ServerAliveInterval and
ServerAliveCountMax options to have the SSH client exit if it
finds itself no longer connected to the server. In many ways
this may be a better solution than the monitoring port.

-f Causes autossh to drop to the background before running ssh. The
-f flag is stripped from arguments passed to ssh. Note that there
is a crucial a difference between the -f with autossh, and -f
with ssh: when used with autossh, ssh will be *unable* to ask for
passwords or passphrases. When -f is used, the "starting gate"
time (see AUTOSSH_GATETIME) will be set to 0.

-V to have autossh display its version and exit.

All other arguments are passed to ssh. There are a number of
other settings, but these are all controlled through environment
variables. ssh seems to be appropriating more and more letters for
options, and this seems the easiest way to avoid collisions.

autossh tries to distinguish the manner of death of the ssh process it
is monitoring and act appropriately. The rules are:

- If the ssh process exited normally (for example, someone typed
"exit" in an interactive session), autossh exits rather than
restarting;
- If autossh itself receives a SIGTERM, SIGINT, or a SIGKILL
signal, it assumes that it was deliberately signalled, and exits
after killing the child ssh process;
- If autossh itself receives a SIGUSR1 signal, it will kill the child
ssh process and start a new one;
- Periodically (by default every 10 minutes), autossh attempts to pass
traffic on the monitor forwarded port. If this fails, autossh will
kill the child ssh process (if it is still running) and start a new
one;
- If the child ssh process dies for any other reason, autossh will
attempt to start a new one.

Startup behaviour:

- If the ssh session fails with an exit status of 1 on the very first
try, autossh will assume that there is some problem with syntax or
the connection setup, and will exit rather than retrying;
- There is now a "starting gate" time. If the first ssh process fails
within the first few seconds of being started, autossh assumes that
it never made it "out of the starting gate", and exits. This is to handle
initial failed authentication, connection, etc. This time is 30 seconds
by default, and can be adjusted (see the AUTOSSH_GATETIME environment
variable below).
- NOTE: If AUTOSSH_GATETIME is set to 0, then BOTH of the above
behaviours are disabled. This is useful for, for example,
having autossh start on boot. The "starting gate" time is
also set to 0 with the -f flag to autossh is used.

Continued failures:

- If the ssh connection fails and attempts to restart it fail in
quick succession, autossh will start delaying its attempts to
restart, gradually backing farther and farther off up to a
maximum interval of the autossh poll time (usually 10 minutes).
autossh can be "prodded" to retry by signalling it, perhaps with
SIGHUP ("kill -HUP").

Connection Setup
----------------

As connections must be established unattended, the use of autossh
requires that some form of automatic authentication be set up. The use
of RSAAuthentication with ssh-agent is the recommended method. The
example wrapper script attempts to check if there is an agent running
for the current environment, and to start one if there isn't.

It cannot be stressed enough that you must make sure ssh works on its
own, that you can set up the session you want before you try to
run it under autossh.

If you are tunnelling and using an older version of ssh that does not
support the -N flag, you should upgrade (your version has security
flaws). If you can't upgrade, you may wish to do as rstunnel does, and
give ssh a command to run, such as "sleep 99999999999".

Disabling connection monitoring
-------------------------------

A monitor port value of "0" ("autossh -M 0") will disable use of
the monitor ports; autossh will then only react to signals and the
death of the ssh process.

Environment Variables
---------------------

The following environment variables can be set:

AUTOSSH_DEBUG - sets logging level to LOG_DEBUG, and if
the operating system supports it, sets
syslog to duplicate log entries to stderr.
AUTOSSH_FIRST_POLL - time to initial poll (default is as
AUTOSSH_POLL below).
AUTOSSH_GATETIME - how long ssh must be up before we consider
it a successful connection. Default is 30
seconds. If set to 0, then this behaviour
is disabled, and as well, autossh will retry
even on failure of first attempt to run ssh.
AUTOSSH_LOGFILE - sets autossh to use the named log file,
rather than syslog.
AUTOSSH_LOGLEVEL - log level, they correspond to the levels
used by syslog; so 0-7 with 7 being the
chattiest.
AUTOSSH_MAXLIFETIME - Sets the maximum number of seconds the process
should live for before killing off the ssh child
and exiting.
AUTOSSH_MAXSTART - specifies how many times ssh should be started.
A negative number means no limit on the number
of times ssh is started. The default value is -1.
AUTOSSH_MESSAGE - append a custom message to the echo string (max 64
bytes).
AUTOSSH_NTSERVICE - when set to "yes" , setup autossh to run as an
NT service under cygrunsrv. This adds the -N flag
for ssh if not already set, sets the log output
to stdout, and changes the behaviour on ssh exit
so that it will restart even on a normal exit.
AUTOSSH_PATH - path to the ssh executable, in case
it is different than that compiled in.
AUTOSSH_PIDFILE - write autossh pid to specified file.
AUTOSSH_POLL - poll time in seconds; default is 600.
If the poll time is less than twice the
network timeouts (default 15 seconds) the
network timeouts will be adjusted downward
to 1/2 the poll time.
AUTOSSH_PORT - set monitor port. Mostly in case ssh
appropriates -M at some time. But because
of this possible use, AUTOSSH_PORT overrides
the -M flag.

Logging and Syslog
------------------

autossh logs to syslog using the LOG_USER facility. Your syslog may
have to be configured to accept messages for this facility. This is
usually done in /etc/syslog.conf.

--
Kudos and raspberries to harding [at] motd.ca

Nomachine NX: An alternative to VNC for using a remote Linux desktop

 

Important
This article includes a small bit of text 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.

If you have ever tried to access a Linux system using VNC, and your host computer wasn’t particularly fast, you may have noticed that things slow down considerably – you definitely know you’re accessing the computer remotely, even if the access is via a local network link. And even if you don’t have that issue, you might want to know about this alternative.

You can install the NX Free Edition server and client from Nomachine and it works great!  Note that NX does not work in precisely the same way as VNC – while VNC lets you take control of the current desktop on the target machine, NX lets each login have its own session and desktop. So you could be using your Linux box and let another family member come into it via NX, and each of you would have your own desktop and session.

The best reasonably current instructions I have found are in this article:
Remote Linux Desktops with NoMachine NX

Those instructions are somewhat geared toward users of Debian-based distributions such a Ubuntu, Linux Mint, etc. but there are also packages available for systems that utilize RPM or compressed TAR packages rather than DEB. Most experienced Linux users should have no problem figuring out how to adjust the instructions for their particular distribution.

DynDNS (mostly) discontinues free DNS service

 

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.

Dynamic DNS service selections in DD-WRTOver the years, many people have used DynDNS as a way to get a free domain name that will “track” their actual IP address, even if their ISP changes it.  Apparently that free ride has all but come to an end.  If you read the instructions that How-To Geek posted in their article How To Easily Access Your Home Network From Anywhere With DDNS, you will note that when you go to the DynDNS site now, it looks nothing like it did then, and the totally free option seems to have disappeared.

Apparently if you have an existing DynDNS account you can keep it as long as you don’t let it expire, but if you do let it expire or if you are trying to set up a new DynDNS account for yourself or someone else, the free option is no longer shown. It appears that now the only way to get a free DynDNS account is to sign up for a 14-day DynDNS Pro Free Trial and then cancel it before the free trial period is up. Then, “You may keep one hostname free of charge for trying the Pro Trial.” The problem with this is that you have to provide a major credit card to sign up for the trial. This will be a show stopper for many users (it definitely takes DynDNS off my list of recommended services).

I had recommended using DynDNS in my article, Using DynDNS to solve the problem of keeping a firewall open to remote users at changeable IP addresses. Now I sort of wish I had recommended someone else.

Some home routers support several Dynamic DNS services, and one of the most popular is No-IP. My guess is that they will be the main beneficiary of the decision by DynDNS to make their free service less accessible. I think they have been around nearly as long as DynDNS (if not longer) and I’ve not heard anything negative about them, so I now recommend you check out No-IP in preference to DynDNS, unless you enjoy having to give up your credit card information and then having to remember to cancel a “free trial” within an allotted timeframe.

To those router manufacturers that only offer DynDNS as a DDNS option, please consider adding No-IP (and maybe a few others) as a DDNS option in your next firmware upgrade.  Those that have replaced their router’s firmware with DD-WRT have the option to use DynDNS.org, freedns.afraid.org, ZoneEdit.com, No-IP.com, 3322.org, easyDNS.com, TZO.com, and DynSIP.org (or you can use another “custom” service). I do not know if all of those have a free service offering but I believe that most of them do. So, commercial router manufacturers could offer options other than DynDNS, and I hope they’ll consider doing so.

 

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! 🙂

How to isolate a second router from the rest of your local network

 

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

I was recently asked how to solve a particular problem and I came up with what I think is an interesting solution, especially given my overall rather limited knowledge of networking.  The issue was this: In the home in question, they have cable broadband and a router that feeds jacks throughout the house.  For security reasons, the homeowner never installed any kind of wireless networking (even though his primary router supports it, he keeps it turned off).  Also his primary router is down in the basement.

Recently he got his wife a Motorola XOOM table computer and wouldn’t you know, it requires Wi-Fi access to connect to the Internet.  In order to extend the range, and so that he or his wife could easily turn off the Wi-Fi when the XOOM isn’t in use, he bought a second Wi-Fi router and put it upstairs.  Note that this router is connected BEHIND the original router in the basement.  In other words, the sequence of connection is as follows:

Cable Modem —> Basement (Primary) Router —> Upstairs (Wi-Fi) Router —> Tablet Computer

Now, as I said, he is very security conscious.  So the question he asked me is, if someone managed to break into his Wi-Fi, is there a way to set it up so that they could ONLY get to the Internet, and not to any other system on his local network.  I said I didn’t know, but to first try accessing other machines on his network (the ones that had web interfaces, anyway) from the XOOM.  Turned out that he could do so without any problem.  Because the Wi-Fi router used a different network segment from the original (addresses in the 192.168.2.x range, whereas the original router handed out address in the 192.168.0.x range), as far as anything connected to the Wi-Fi router was concerned, anything on the primary router might as well have been on the Internet (please forgive the non-technical explanation, I’m probably missing several technical details here, but that’s the gist of the problem).

I didn’t think it would be a good idea to try to make the Wi-Fi router use the same address space for both WAN and LAN, and while I could assign it a static IP address on the WAN side, it had to be able to reach the router/gateway at 192.168.0.1.  So here is what we did.

On the PRIMARY router, we took a look at the LAN settings and found that its DHCP server was assigning addresses starting at 192.168.0.2.  We changed that to start at 192.168.0.5 (probably could have used 192.168.0.4 in retrospect).

This way, we could change the WAN address of the Wi-Fi router to use a STATIC IP address of 192.168.0.2, and (this is the important part) a NETMASK of 255.255.255.252.

This means that as far as the Wi-Fi router is concerned, there are only four valid IP addresses in the 192.168.0.x range:

192.168.0.0 (not used)
192.168.0.1 (primary router/gateway)
192.168.0.2 (Wi-Fi router)
192.168.0.3 (Reserved for “broadcast” as far as Wi-Fi router is concerned)

One thing to remember is that after changing the DHCP assignment on the PRIMARY router is that computers already using IP address 192.168.0.2 and 192.168.0.3 will not automatically vacate those addresses until their DHCP lease comes up for renewal.  So if you change the second router’s WAN address to 192.168.0.2, it may not actually be able to connect until the computer or device currently on 192.168.0.2 “loses its lease”.  Rebooting the primary router may help, but in some cases you may have to track down the computer with the conflicting address and shut it off, or if you know how, renew its IP address assignment (this can usually be done from within the network settings panel).  Eventually, though, it should work, and at that point you should find that devices connected to the secondary router cannot connect to any addresses in the 192.168.0.x range outside the three mentioned above, which means they won’t be able to “see” anything else on your network that’s been assigned a DHCP address.

This tip falls into the category of “it worked in this particular situation, but I don’t guarantee it will work for you”.  So if you try this, be sure to test to make sure that the other machines on your primary network are actually unreachable from the secondary router.

Now let the comments begin, telling me how there’s a better way to do this, or why it won’t work, or something to that effect…

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.

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.