How to run a sub-domain of CLUG.Org

Why?

Because DNS is a great enabler!

Let’s say you want to share some information with the world but you have a regular, dynamic xDSL Internet connection. You start up a web server, open port 80 on your router, find your IP address is 72.49.120.103, then call some friends to let them know that address. All is amazing and wonderful. Every so often though, your IP address will change, and then you become lost to the world. You need to find out what your IP address is, then call those you want to share with and tell them your new address, it’s tedious and you have to wait for them to find a pen.

Enter Dynamic DNS!

Dynamic DNS allows you to associate a host name with an IP address which changes, such as one assigned to a dial-up intenet connection or a cable modem.

Instead of 72.49.120.103, you can be amy.clug.org! Even I can remember that.

How?

Step zero is to send an e-mail to president@clug.org, requesting a sub-domain, and it must include a phone number, I will not set up someone until I’ve talked to them! You can call me if you want, I have a Cincinnati number, Six Zero Four-5916.

Step one is to set up a service on your server, it can be SSH, HTTP, FTP, FreeCiv or anything else you like, but not Telnet, telnet is bad. A note on security, if you aren’t sure of the security implications of the software you want to run, at a minimum, do a Google search like “Linux howto secure ipp” beforehand, and no, there isn’t a space between how and to. Figure out what port or ports your service runs on, you can look in /etc/services or the man page, or use sudo nmap -sS 192.168.1.2 (where that last part is the LAN address of your server). Make sure that you can get to that service from another machine on your local network and that it gives back sane responses.

sudo nmap -sS 192.168.1.2

Starting Nmap 5.21 ( http://nmap.org ) at 2013-10-27 11:03 EDT
Nmap scan report for 192.168.1.2
Host is up (0.0000090s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
631/tcp open ipp
2222/tcp open unknown

Nmap done: 1 IP address (1 host up) scanned in 0.25 seconds

Step two is to set up your router, this is pretty much beyond the scope of this little howto, as there are a zillion different routers out there, and some of them can be a pain to set up in what the original builders think might be insecure (Apple Airport, I’m looking at you!). What you want to do is find an entry like “Port Forwarding” or “Game Access” in some cases, this is done by connecting to the built-in web-server that runs on the router itself, usually at http://192.168.1.1/ and looking through the menus you find there, after you change the password to something secure resembling ho3r0cqh@m – and no, that isn’t my password. In my case, I wanted to open access to SSH on the non-default port of 2222, so I forward port 2222 through 2222 to 192.168.1.2, port 2222. The port xx through yy is for a contiguous range of ports, the destination port is the lowest port in the range. Not all routers do this kind of range, but it is the most confusing of the ones I’ve found.

Step three is to figure out what your external IP address is. The script at the end of this article reads the address from my gateway router, however there are plenty of places on the Internet that can give you this information, for instance;

links -dump http://www.ipchicken.com/ | grep -oP "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

and

links -dump http://www.cmyip.com/ | grep -oP "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

In both of these, I’m using links, but you can use elinks, w3m, wget, lynx or anything else that returns a page on the command line. The pipe to grep takes the output before and returns only (o) the match for the perl (P) expression that matches an IPv4 address (Okay, it doesn’t, but it’s good enough).

My opinion is that reading the router is the better idea as it’s on the end of a very fast wire that doesn’t slow down my surfing speed.

Step four is to request a dynamic update of your hostname from http://freedns.afraid.org/dynamic/update.php with an argument of the SecretString that I provide you with. Each sub-domain has a unique SecretString, so these can be distributed easily, and used on a router if it runs dd-wrt or Tomato. As soon as you run;

SecretString="BgyVtp45gfnMrrd0n3D5GHns4b79saAKpTMAtv=="
wget -q --read-timeout=0.0 --waitretry=5 --tries=400 -O- \
http://freedns.afraid.org/dynamic/update.php?${SecretString}

your sub-domain should be active, a ping sent to clug.org should give my address, one sent to you.clug.org should give your ip address (They may or not succeed, but the addresses should be correct. Also, it doesn’t need to be run from your server, any machine that uses the same gateway router will work, though I can’t come up with a good reason to do this. One of the interesting things about this method is that it doesn’t need to be run as root, any user can run the script below.

You could just run the wget line above as a cron job, but please don’t, it puts an excessive load on the machines at Afraid.org and that irritates Joshua Anderson, the owner of Afraid.org.

Step five is to set up a cron job to do this work while you sleep,

crontab -l
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0-7) (Sun=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * command to be executed
*/10 * * * * ~/bin/Afraid.org.update.sh

The script looks up your external address, compares it to whatever it had been, and if it changes, requests an update. Save the script below as ~/bin/Afraid.org.update.sh and change the SecretString variable in line nine, replace the value shown with the one I give you. Don’t forget to make it executable!

#!/bin/sh
# Run me to set the external address up
#
# This script only tries to update if there is a change in our IP address
# or we loose the connection to the World Wide Web.

Logfile=${HOME}/.Afraid.org.log

SecretString="BgyVtp45gfnMrrd0n3D5GHns4b79saAKpTMAtv=="

# The lines below gets our IP address from the crappy little CBT Wireless
# router at home.
# They need to be modified if that router changes, or we use another service.
Current=`
links -source http://192.168.1.1/htmlV_Generic/home_Connect.asp \
| grep WanIPRoutingState_WanIPAddress \
| grep -oP "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
`

# Present the date in an easily grepable fashion.
Date=`
date +"%Y-%m-%d+%H:%M"
`

# If the Logfile doesn't exist, create it with a known IP address.
if [ ! -f $Logfile ] ; then
echo "$Date 0.0.0.0" >> $Logfile
fi

# If the Logfile still does not exist, something is wrong, cry for help.
if [ ! -f $Logfile ] ; then
echo "Cannot create $Logfile - check directory permissions"
exit 1
fi

Last=`
cat $Logfile | tail -1 | cut -d " " -f 2
`

if [ "$Current" = "$Last" ] ; then # No update is required, silently exit.
exit 0
fi

echo "Update of external IP address needed."
echo "$Date $Current" >> $Logfile
# The line below is from afraid.org and is what actually sets the DNS entries
# for the domain.
wget -q --read-timeout=0.0 --waitretry=5 --tries=400 -O- \
http://freedns.afraid.org/dynamic/update.php?${SecretString}

Step six, why didn’t it work?

It probably did work, you just can’t see the forest through the trees. Say you are on a machine with IP of 192.168.1.100, and your server is at 192.168.1.2, with the router at 192.168.1.1, your external address is 40.30.20.10, and port 80 is forwarded to the server.

When I try to connect from my machine at my house, everything works properly, DNS resolves your external address and I see the web page on your machine because your router forwards my request to your server.

When you try to connect, you resolve your external address, send the request out your router, which doesn’t understand why an internal address is trying to connect to another internal address through the router, so it drops the packet.

Before you spend hours trying to figure out what is going on, call somebody and ask if they can see your page, if they can, you’re golden.

To fix things so they work properly inside as well, add your server to your /etc/hosts file ( %SystemRoot%\system32\drivers\etc\hosts on Windows, /lib/ndb/hosts on Plan 9), and everything is good, unless you are on a laptop. If you are using a laptop and take the laptop to a friends house, when you try to connect, you resolve 192.168.1.2 which won’t work. It wouldn’t be difficult to write a script that looks at the name of your access point and modifies the hosts file if you are home, but your access point would need a unique name.

The proper way to fix this is to run your own internal DNS server, either on your router or on your server. The advantage of the router is that it’s pretty simple and you don’t need to worry about it once everything is set up, the advantage of the server is that you can do more with it, but you need to do more with it.

If you run dd-wrt, you can fix this by enabling dnsmasq, then adding your hostname to the Additional DNSMasq Options

expand-hosts
address=/www/192.168.1.2
address=/mail/192.168.1.2
address=/amy.clug.org/192.168.1.2

Free DNS from Afraid.Org