Tracking IPs on remote machines without DDNS

If you've ever set up a server at home, you'll know what I'm talking about. I've done this a couple of ways over the years. Of course, you can use dynamic DNS (DDNS) services (I have), but some of them require special applications. Before I knew about DDNS services, I once wrote a rule for my mail client that would watch for specially crafted emails so that I could send emails to myself asking for my IP. The mail client would then run a script which would fetch my current IP and dump it in a file which would get attached to an email that got sent to my email account. I could then simply wait and watch for my email to come in.

Syncthing + cron (in Linux)

Most recently, I decided to use Syncthing and cron jobs in Linux to accomplish this task. Syncthing is a P2P file syncing service. Basically, you can create a folder on your computer and share it with other computers that are also running Syncthing. When a file gets added, changed, or removed in one system, these changes propagate to the other systems using a P2P file-sharing mechanism. It is important to note here that these files do not end up on a cloud server, so if you want to machines to synchronize, they must both be turned on and connected to the Internet at the same time.
As an added perk, if your systems using Syncthing can connect directly to each other (don't need to use a relay server), Syncthing will show you the remote IP addresses of systems you sync with.

The Breakdown

My implementation of this is still evolving, but here's what I'm working with so far (note that I'm using Linux and bash scripts, but these could be converted to work on a Windows machine as well):
  • get-ip.sh: This is a script that I call with a cron job at regular intervals to fetch and log external IP changes. It can also be used in an interactive mode to test all of the urls in ip-fetch_server-list.txt or to check for compatibility of a new url that you are considering adding to ip-fetch_server-list.txt. To run in this mode, pass "check" as the first argument.
  • get-ip.sh.sig: This is important! My get-ip.sh file is in a Syncthing folder which means it's shared, and if its somehow modified without my approval, whoever modified it could potentially run arbitrary code on any of my systems every 30 minutes. While this isn't likely to happen, I decided to protect against such a possibility. I used gpg2 to create a detached signature of my get-ip.sh file so that I can check to make sure that no unauthorized modifications have taken place before running get-ip.sh.
  • ip-fetch_server-list.txt: This file lists one web address per line (without leading http(s):// ). These are addresses to sites that return a caller's external IP. This list is used by get-ip.sh when attempting to discover a system's external IP using curl.
  • ip-to-clipboard.sh: This is a script that can be used to fetch the most recently recorded IP address for any system that tracks its own IP. It can be called with an IP log file (named as [hostname].ip) for incorporation in scripts to fetch the current IP address of a given system.
  • [hostname].ip*: A file with a name fitting this pattern represents an IP log file for the system with a matching hostname. Each line in such a file records a timestamp, the most recently discovered external IP address for that system, and the site used to determine the external IP. It is only updated when a change is detected by get-ip.sh.
  • error.log*: This file is modified anytime get-ip.sh has trouble fetching the external IP from a given source. Each line records a timestamp, the host name of the machine that experienced the issue, and a description of the issue.
 * These files are generated and populated by get-ip.sh.

The Scripts

Rather than put the scripts up here (get-ip.sh is a little lengthy), I've posted them on GitHub. That way, should I make any changes, the most current version will be available without having to come back and edit this post.

Setting It Up

If you'd like to give this a go, here's what you'll want to do:
  1. Pick a file synchronization platform. I used Syncthing but other services like SpiderOak One or Dropbox would work too. 
  2. Whichever service you go with, install it on all machines you want to be able to view and/or track external IPs on, and share a folder between all of these machines.
  3. Copy the get-ip.sh and ip-fetch_server-list.txt files from my GitHub into this folder. The ip-to-clipboard.sh is optional. I use it in other scripts I have. This step need only be completed on one host. Your synchronization platform should propagate it to the other systems.
  4. Only perform this step on computers that will log their IPs and skip if you will only use a given machine to view IPs of other systems
    The get-ip.sh script will attempt to use dig to find your external IP first. If dig is not installed, it will try curl. Make sure you have at least one of these programs installed.
    sudo apt-get install dig
    
    # or 
    sudo apt-get install curl
    
    # or 
    sudo apt-get install dig curl
  5. Make sure any scripts you plan to use are set as executable
    chmod +x /path/to/script
  6. Only perform this step on computers that will log their IPs and skip if you will only use this machine to view IPs of other systems
    Set up a cron job to run get-ip.sh every 30 minutes (of course you can change the frequency). Run crontab -e and add the following line, replacing /path/to/get-ip.sh with the actual path to get-ip.sh.
    */30 * * * *        /bin/bash /path/to/get-ip.sh 
  7. If it is possible that someone else may have opportunity to modify the get-ip.sh file (or any other script file you have in your shared folder) on any one of your machines, use GnuPG to sign your file(s), and modify your cron job in step 5 to only run get-ip.sh if the signature is good. 
That's it. Now, any system configured to run get-ip.sh with cron will check the external IP at the specified interval, and if the IP returned does not match the last recorded IP in the log file for that host, the current IP will be appended to the log file for that host. The synchronization platform you chose to implement should then take care of synchronizing the changes in the log file over to your other systems for viewing on those systems.

Comments

Popular posts from this blog

Encrypted Ubuntu Installation with "Manual" Partitioning

Router Firmware -- Dumping and Flashing

DIY lefty USB hub with fingerprint reader for about $5