Create your own dyndns for your home computer

Setup

Some people want to reach their home computer from the internet but find themselves in the following setup:

  • A home computer with a public IP address that can change/is unreliable.
  • A host reachable by a reliable public IP address or even better: a domain name.
  • A router at home that supports port forwarding.
  • No want to register or pay for a dyndns providers.

In such scenarios, we can make the home computer accessible through the public host:

  1. Setup port forwarding on public host so traffic of a port goes to the home computers.
  2. Configure home router to forward traffic of one port to the home computer in the LAN.
  3. Ensure that the system is aware of a public IP address change of the home computer.

Home computer setup

This script is stored on the home computer we want to reach from the public internet, it will update the IP address on the remote computer (which performs the port forwarding).

/home/andre/bin/update-my-ip.sh

#!/bin/bash

# ensures a remote computer gets to know this computer's ip
# to implement an ip forwarding.
#
# this script determines this computer's public ip and compate it
# to an ip address stored in a file on a remote computer.
# if the stored ip is different to the current public ip,
# the new ip will be written into the file on the remote computer.

# configuration of ssh connections to remote host
REMOTE_SSH_USER="remoteUsername"
REMOTE_SSH_PORT="22"
REMOTE_SSH_HOST="example.com"

REMOTE_IP_FILE="ssh-forwarding-ip.txt" # assuming file is in home directory
REMOTE_EXEC="ssh $REMOTE_SSH_USER@$REMOTE_SSH_HOST -p $REMOTE_SSH_PORT"

check_ip() {
    if (echo "$1" | grep -qE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'); then
        return 0
    fi
    echo "ERROR: invalid ip: '$1'"
    return 1
}

# resolve public ip and see what is configured on the remote host:
current_ip="$( dig +short myip.opendns.com @resolver1.opendns.com )"
remote_ip="$( $REMOTE_EXEC "cat ~/$REMOTE_IP_FILE" )"
echo -n "$(date '+%F %T') current_ip: $current_ip remote_ip: $remote_ip "
check_ip $current_ip || exit 10 # quit if ip does not look valid
check_ip $remote_ip || exit 20 # quit if ip does not look valid

# compare ips, quit if no change is necessary:
if [ "$current_ip" = "$remote_ip" ]; then
    echo "Nothing to do, remote IP matches current."
    exit 0
fi

# writing new ip to remote file:
$REMOTE_EXEC "
    cp -v $REMOTE_IP_FILE .$REMOTE_IP_FILE-until-$(date +%F_%T) \
    && echo $current_ip > $REMOTE_IP_FILE \
    && echo $REMOTE_IP_FILE written"

To make sure the IP stored on the remote computer is always up to date,
create a cronjob that invokes the script above once a minute on the home computer:

andre@nairobi ~ % crontab -e
# once per minute: maintain the IP of this computer on bytesare.us, for the port forwarding:
* * * * * bash /home/andre/bin/update-my-ip.sh 2>&1 >> /home/andre/log/update-my-ip.log

Public computer setup