3 min read

Setting up DuckDNS on OpenBSD

Well, that was easy. I’ve been thinking about setting up WireGuard on my firewall. That will give me ad blocking by default as well as a way into my system when I want to do something. But… that means I need a way to know what my external IP is. Dynamic DNS to the rescue!

I looked around at the providers, and DuckDNS appears to be the one whose ideology aligns most closely to mine. I went to their “Install” page and they don’t have OpenBSD. But they have something close — linux bsd cron. So I adapted their script to use OpenBSD’s ftp (which, despite its name, does https as well) instead of curl, which isn’t in the base OpenBSD distribution.

#!/bin/sh -
# Update the DNS at duckdns.org with my IP

DOMAINS="mydnshost" # comma-separated, just the hostnames, not the FQDNs
TOKEN="badcafe-dead-beef-b001-fa11ca2eba3e" # from DuckDNS

tmpfile=`/usr/bin/mktemp /tmp/duckdns.XXXXXXXXXX`
if [ $? -ne 0 ]; then
    /usr/bin/logger -i -p daemon.err "duckdns update failed, couldn't create temp file"
    exit 1
fi

/usr/bin/ftp -d -o $tmpfile "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}"
return_val=$?
url_out=`/bin/cat $tmpfile`
/bin/rm $tmpfile

if [ $return_val -eq 0 ]; then
    if [ $url_out == "OK" ]; then
        /usr/bin/logger -i -p daemon.info "duckdns update ok"
    else
        /usr/bin/logger -i -p daemon.info "duckdns update failed: $url_out"
    fi
else
    /usr/bin/logger -i -p daemon.err "duckdns update failed, returned: $return_val"
fi

Note that this doesn’t account for multiple external WANs, something I want to do in the future. It also requires IPv4. There are ip= and ipv6= parameters if you want IPv6 or a different address for different WANs.

Then all I had to do was chmod 700 and stick it in a cron file:

crontab -e
~/15 * * * * ~/duckdns/duckdns >/dev/null 2>&1

Now I can get my IP anywhere. (I’m using ~/15 instead of */15 so I don’t get 503s when everyone else decides it’s time to update.)