Mobile Device Web Site Testing? Try Dynamic DNS
If you’re developing responsive web sites and applications these days, I’d guess you’re familiar with the little niggles involved in getting mobile devices to connect to your development machine. If you use a desktop machine to host your development system then you might assign it a static IP address and access it that way, but if you develop on a laptop you need to deal with the possibility of your laptop’s IP address changing as you move from network to network (e.g. from home to work and back again).
This is where services like xip.io come in. If you know the IP address that your laptop currently has, you can use a URL with a xip.io domain name to connect to your web server over the local network. The approach is baked-in to pow - it automatically creates xip.io aliases for the virtual hosts for each of your applications.
One minor annoyance with this approach is the need to change the URL when you move from one network to another. If you pack up and head home halfway through a debugging session you’ll find all the pages you have opened on your mobile devices stop working when you’re on a different network and your laptop has a different IP address.
And what if you don’t use pow?
I build Ruby on Rails applications on a laptop running Ubuntu,
where pow won’t run.
Instead I use Phusion Passenger
to manage my local applications under development,
using the default Ubuntu Apache 2 packages as a basis.
For each application that I’m working on I create an Apache configuration file
in /etc/apache2/sites-available
,
usually by copying an existing one from a similar application.
To use xip.io I’d need to update these files
whenever the IP address allocated to my laptop changed.
It’s Just Dynamic DNS, Really
What xip.io provides is a mapping from a known hostname in DNS to the IP address for your laptop, albeit with the unfortunate side-effect of needing a different hostname when you move network. But there’s another well-known service out there that has been doing pretty much the same thing for years: Dynamic DNS.
Dynamic DNS is used to give a fixed hostname to a network device with a dynamically allocated address; its most common use these days is probably on consumer broadband connections where you want to be able to access some computer or service at home while you’re out and about. I use the Free DNS service from afraid.org for just this purpose.
But we can also use the same service to give a name to our development laptop’s (dynamic) network connection. If we arrange for our laptop to update a dynamic DNS entry with its address on the local network, then we can use that hostname on our mobile devices. Even better, the hostname won’t change when we move between networks.
System Administration is (sometimes) Debugging
I knew from past forays into the Ubuntu networking system that
the system will run scripts in
/etc/network/if-up.d
when a network interface comes up,
so I knew I probably just needed to add a script to update
the IP address for a dynamic DNS entry.
What I didn’t know was what information was made available to the script
when it runs,
and a couple of minutes of searching didn’t turn up the documentation.
But one of the nice things about a Unix system is that you can sometimes
treat system administration as a debugging problem,
and apply tools and techniques from that domain.
Here’s my first attempt at a dynamic DNS update script:
The first couple of lines I copied from the other scripts in the directory:
set -e
causes the script to exit immediately if any command fails.
The exec
line redirects the output and error streams for the script to
a file so we can see what’s going on -
print debugging
for Unix scripts.
I put this in /etc/network/if-up.d/dynamic-dns-update
and
cycled the wireless network connection using NetworkManager
(clicking on the currently active wireless network will force
a disconnect and then a reconnect).
After this, /tmp/ddu.log
contained the following, amongst other things:
This told me a few things:
- NetworkManager is hooked up to the standard Debian networking scripts
sufficiently to get an
if-up.d
script to run. - The environment contains exactly the information I’d need to update the Dynamic DNS service, including the IP address.
- There were no command line arguments passed to the script, because the
file only contained lines that looked like they came from
env
. I initially thought that the IP address might be passed as a command line argument, but this experiment showed it was in the environment instead.
Hooking Things Together
My next step was to create a new dynamic DNS update candidate hostname here and change the script to make a request to Free DNS:
The id
value is the one that you find embedded in the ‘Direct URL’ link
on the dynamic DNS page.
It’s a unique id that is specific to the hostname you’re updating.
I also add the IP address for the laptop to the request,
otherwise the service will use the IP address that it sees the request
coming from -
probably the Internet side of your router if you are behind a NAT
firewall, and not what we want here.
I left the exec
line in so I could check for errors if things didn’t work,
but happily they did -
my new domain name was updated correctly,
taking the address of my laptop on the private network.
But What If It Goes Wrong?
The script was working, but it needed a bit of tidying up before I could leave it:
firstly, I wanted to tighten the script up a bit so it only did the update if it was
really the wireless interface coming up.
Secondly, it was dumping debugging information into /tmp
-
status messages in the system log would be cleaner.
I changed the exec
line to the following to check whether any output
redirection or logging was provided to the script:
After cycling the wireless connection again the output in /tmp/ddu.log
was:
which tells us that whatever runs our script is going sending any output it produces
to /dev/null
(i.e. throwing it away).
Adding entries to the system log is pretty easy though:
the logger
command will do it for us.
Here’s the final version of the script:
Here we’re checking that the script is being executed because the wireless connection
is coming up,
and we send the output from curl
to the system log, where it comes out like this:
Success!