2018-09-19

How to Set Up Dynamic DNS with OpenWrt and Gandi LiveDNS

OpenWrt supports quite a few dynamic DNS providers in its very nice ddns-scripts package. Many of them are free, but if you already pay for a domain name and DNS hosting at Gandi.net why not just use that? Unfortunately Gandi is not a supported provider, but it's fairly straightforward to get it working with a custom update script.

I should note that Gandi has not one but two DNS platforms. This post is written for their new LiveDNS platform and will NOT work if your domain is still using their old DNS platform. Also I'm using OpenWrt 18.06.1, the latest release as of the writing of this post. Finally, this is a very technical article, and assumes you are already familiar with every step involved in setting up dynamic DNS on OpenWrt except for how to get it working with Gandi.

First, log in to your OpenWrt router and install the prerequisite packages:

root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg install curl ddns-scripts luci-app-ddns

Gandi LiveDNS sports a RESTful HTTP API that we'll be using to make our DNS updates. So copy the custom update script below to /etc/ddns/update_gandi_net.sh:

#!/bin/sh

local __TTL=600
local __RRTYPE
local __ENDPOINT="https://dns.api.gandi.net/api/v5"

[ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing subdomain as 'username'"
[ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing API Key as 'password'"

[ $use_ipv6 -ne 0 ] && __RRTYPE="AAAA" || __RRTYPE="A"

curl -s -X PUT "$__ENDPOINT/domains/$domain/records/$username/$__RRTYPE" \
    -H "X-Api-Key: $password" \
    -H "Content-Type: application/json" \
    -d "{\"rrset_ttl\": $__TTL, \"rrset_values\": [\"$__IP\"]}" >$DATFILE

write_log 7 "gandi.net answered: $(cat $DATFILE)"

return 0

Make it executable and add it to sysupgrade.conf so that it persists after system upgrades.

root@OpenWrt:~# chmod +x /etc/ddns/update_gandi_net.sh
root@OpenWrt:~# echo /etc/ddns/update_gandi_net.sh >>/etc/sysupgrade.conf

OpenWrt's ddns service handles all the logic of scheduling updates and getting our current IP address. The seemingly unset variables above ($username, $password, $domain, $__IP etc.) will be set by ddns once everything else is configured.

Now you can configure ddns (almost) like you normally would, either from the luci web interface or with UCI on the console. Though the meaning of some of the configuration variables is probably not obvious unless you read the script above very closely.

You want to select a custom script as the ddns provider and set it to /etc/ddns/update_gandi_net.sh. The domain should be the name of the domain you registered with Gandi, and shouldn't include any subdomains. The username should actually be set to the subdomain you want to update. The password should be your LiveDNS API Key rather than your Gandi password. You can retrieve it in the security section of your Gandi account admin panel.

A complete /etc/config/ddns might look like this:

config ddns 'global'
    option ddns_dateformat '%F %R'
    option ddns_loglines '250'
    option upd_privateip '0'

config service 'gandi_ipv4'
    option lookup_host 'subdomain.example.com'
    option update_script '/etc/ddns/update_gandi_net.sh'
    option domain 'example.com'
    option username 'subdomain'
    option password 'your-apikey'
    option dns_server 'ns-98-a.gandi.net'
    option enabled '1'

config service 'gandi_ipv6'
    option lookup_host 'subdomain.example.com'
    option use_ipv6 '1'
    option update_script '/etc/ddns/update_gandi_net.sh'
    option domain 'example.com'
    option username 'subdomain'
    option password 'your-apikey'
    option dns_server 'ns-98-a.gandi.net'
    option enabled '1'