Dynamic DNS—an Object Lesson in Problem Solving
Let's Never Do This Again
It's not that I don't love texting my wife, it's just that hoping someone is home to check an IP address is not the best way to roll your own DNS. There's also the possibility that whatever Dynamic DNS solution I dream up might fail, and I want to make sure I always can figure out my home IP address.
There are a couple different ways I considered for making my IP address
always accessible. The simplest was to set up a cron job to
upload regularly the results of my PHP script to my Raspberry Pi or to one
of my Web hosts. In order to do that, I'd simply have to set up SSH
keys so my home server could upload a file without any interactive
authentication. This is, in fact, what I recommend. As it happens,
however, I'm lazy. What I actually did was set up a cron job that
copied my IP address into a text file inside my Dropbox folder. It's
not a better solution than
scp-ing, but the end result is the same.
Here's what my cron job looks like:
1 * * * * /usr/bin/wget -r --quiet -O ~/Dropbox/Public/IP.txt ↪'http://snar.co/ip'
It basically updates my Dropbox folder every hour with my current home IP address. Because Dropbox syncs onto every device and computer I own, it's always readily accessible.
But That's Still Not DNS
Now things get a little complicated. Because I have a full-blown server and a handful of domains to use, it would make sense to set up BIND and serve out a subdomain. BIND does have the ability to change a host entry with a remote update command. It requires setting up encryption keys, and of course, the BIND dæmon has to be configured properly. Remember when I said I was lazy? It's still true. Because all I wanted to do was serve up a single domain name for my home IP address, I opted for something simpler.
DNSMasq is a very simple dæmon that runs on my Linux-based home routers. It handles both DHCP services and DNS resolution. In both cases, the services are very stripped down and simplistic, but if all you need is simple DNS resolution, it doesn't get simpler than DNSMasq. It will look at the server's /etc/hosts file and serve out those entries when queried. All I had to do was get my home IP address into my server's /etc/hosts file, and regularly send DNSMasq the HUP signal to reload its files. A simplistic DNS server was the final piece to the puzzle. Next came implementation.
Putting It All Together
The first step was to create a DNS entry that I could update with DNSMasq. This is simpler than most people realize. I just added an NS record pointing to my Linux server. So basically, I have an entry that looks like this:
home.mydomain.org. IN NS server.mydomain.org.
That means, "when resolving home.mydomain.org, or any subdomain of it, ask server.mydomain.org for the address." This is exactly what I want, because then any time I (or anyone else) tries to access home.mydomain.org, it will ask my server to resolve the name. The only thing left to do is to get my server, which is running DNSMasq, to respond with the proper IP address. That means a couple more cron jobs.
Remember my cool little IP.txt file I keep in my Dropbox? Well, in order to hack together the /etc/hosts file on my server, I had to modify my PHP script a little. In order to create an output compatible with /etc/hosts, I changed it to:
<?php // Save the IP to a variable $ip_address = $_SERVER['REMOTE_ADDR']; // To display the IP: echo $ip_address; echo " home.mydomain.org"; ?>
Note the space before "home". Now the file in my Public Dropbox folder is a properly formatted /etc/hosts line. In order to combine that with my original hosts file, I created a folder /etc/hosts.d/ on my server, and copied /etc/hosts to /etc/hosts.d/00-original.
Still with me? The last step is to run the following script on the server. I do this script every hour, so if my IP address changes, it should take at the most an hour before it's corrected. Here is the server script:
#!/bin/bash /usr/bin/wget -r --quiet -O /etc/hosts.d/home ↪'https://dl.dropbox.com/xxx/IP.txt' cat /etc/hosts.d/* > /etc/hosts killall -SIGHUP dnsmasq
The first line retrieves the current IP address stored in my Dropbox Public folder. The second line creates a new /etc/hosts file by concatenating all the files in /etc/hosts.d/. Then finally, I send the SIGHUP signal to dnsmasq, so it will reload the /etc/hosts file.
The thing I really like about this example as a way to demonstrate problem solving is that there are so many different ways to accomplish the same results. My solution is far from the best. Off the top of my head:
I could have the script on my home server check for a change in IP address rather than just constantly updating. If there was a change, it could start the update process on my remote server rather than updating the hosts file every hour whether it needs it or not.
Depending on what DNS hosting company you use, it's probably possible to change an address with a remote command. It's also possible there are free DNS servers out there directly supported by a client like ddclient.
Because my solution requires a remote Linux server with a static IP, it makes my specific solution inaccessible to many people. That just means you need to think harder in order to dream up a solution!
Where to Go from Here
It seems apropos to make my disclaimer again: the process I just explained is not the most efficient way to solve the problem of changing IP addresses. My methods are crude, my scripts are simplistic, and I haven't included any error correcting whatsoever. (What happens if I can't download the file from Dropbox? Will my script fail? Probably!) The purpose of this article is to make you think. Linux gives us tools that are powerful, flexible and above all else, useful. Sometimes you need to create a little digital duct tape and solve a problem on the fly.
What if you can't seem to come up with a solution to your particular problem? That's where the Linux community really shines. Stop in at the #linuxjournal channel, or attend a local LUG meeting. Folks there are much like me and are eager to help solve problems. Everyone loves a puzzle, and when you get to solve it with Linux? Awesome!
|Privacy Is Personal||Jul 02, 2015|
|July 2015 Issue of Linux Journal: Mobile||Jul 01, 2015|
|July 2015 Video Preview||Jul 01, 2015|
|PHP for Non-Developers||Jun 30, 2015|
|A Code Boot Camp for Underprivileged Kids||Jun 30, 2015|
|Comprehensive Identity Management and Audit for Red Hat Enterprise Linux||Jun 29, 2015|
- Privacy Is Personal
- PHP for Non-Developers
- Secure Server Deployments in Hostile Territory
- Linux Kernel 4.1 Released
- July 2015 Issue of Linux Journal: Mobile
- Django Templates
- Comprehensive Identity Management and Audit for Red Hat Enterprise Linux
- A Code Boot Camp for Underprivileged Kids
- Attack of the Drones
- diff -u: What's New in Kernel Development