Skip to content

Instantly share code, notes, and snippets.

@NickLaMuro
Last active June 28, 2018 10:56
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save NickLaMuro/4969479 to your computer and use it in GitHub Desktop.
Save NickLaMuro/4969479 to your computer and use it in GitHub Desktop.
Dealing with Dynamic IP's with a home server and DNSimple

The Problem

Currently, I have a internet provider that seems to change my IP quite frequently, and with a home server that I like to ssh into, store music/movies/files on, and do other fun/hacky things with, it is been a pain to not have a way to access it consistently.

The Solution

Thankfully, I have bought my domain names through dnsimple, and they have an API that you are able to access, edit, and create records with that works quite nicely. This is by no means a perfect/preferred solution (I don't really like relying on a seperate service just to find out what my public IP address is, nor do I like saving the last know IP address in a "dot file"), but this does the trick for the moment.

Notes

Just a few things explainations and ramblings on why I did some of things the way I did:

  1. logging

I wasn't too confident in my ability write decent shell scripts, I made sure to log as much as I could, and surpress what I didn't need. A lot of tips came from googling "linux" stuff, but most of it can be summed up in the "cron setup" link in the Credits section below.

  1. curl -s -S

curl has the annoying tendency to spit out garbage like this when it is piped or pushed into a log file:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10660    0 10660    0     0  21873      0 --:--:-- --:--:-- --:--:-- 88099

This clutters up a log file and has no useful purpose when digging through a log, so when I was using curl, I made sure to use the -s and -S options together. -s (or --silent) suppresses errors and almost all output from curl, which is nice, except when stuff breaks. Thankfully, if you use -S along with it (or --show-errors), it will redisplay those errors when you need them.

Credits

Like usual, I didn't pioneer this idea, so here is where I got some help:

#!/bin/bash
EMAIL="your_email@example.com"
API_TOKEN="API_TOKEN"
DOMAIN_ID="your_domain.com"
RECORDS=(123456 234567 345678) # Replace with the Record ID
IP="`curl -s -S http://v4.ident.me`"
STORED_IP_ADDRESS_FILENAME="$HOME/.current_external_ip_address"
# Loop through each record id in the array
function update_a_records {
echo "Updating $STORED_IP_ADDRESS_FILENAME ..."
echo "$IP" > $STORED_IP_ADDRESS_FILENAME
echo "Updating all DNS Records ..."
for record_id in "${RECORDS[@]}"; do
curl -H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-DNSimple-Token: $EMAIL:$API_TOKEN" \
-X "PUT" \
-d "{\"record\":{\"content\":\"$IP\"}}" \
--silent --show-error \
"https://dnsimple.com/domains/$DOMAIN_ID/records/$record_id"
echo
done
echo "Finished updating records"
}
# Check to see if we have a file to save the current IP the last time we
# checked our current IP
echo "`date` - Starting Update DNS Script..."
if [[ -f $STORED_IP_ADDRESS_FILENAME ]]; then
# If the file exists, check what the IP is
PREVIOUS_IP="`cat $STORED_IP_ADDRESS_FILENAME`"
# If the new IP differs from the one we have saved, run the update_a_records
# function to update the DNS records as well as update the file
if [[ $PREVIOUS_IP != $IP ]]; then
#if [[ $IP =~ "\A(\d{1,3}\.){3}\d{1,3}\z" ]]; then
if [[ `echo $IP | grep "\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}"` ]]; then
echo "Current IP and Stored IP differ!"
echo " current ip address: $IP"
echo " previous ip address: $PREVIOUS_IP"
update_a_records
else
echo "New IP Address cameback malformed! Not changing..."
echo "'$IP'"
echo "'$PREVIOUS_IP'"
fi
else
echo "Current IP is the same as stored IP. No action necessary"
fi
else
# If there is not saved IP address, create write a file with the current IP
# address, and update the DNS records with the current IP... just to be safe
echo "No previous IP address found!"
update_a_records
fi
# m h dom mon dow command
*/15 * * * * /usr/local/bin/check_and_change_dns >> /home/your_username/log/check_and_change_dns.log 2>&1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment