Detect IPv6 address change to run a shell script

I have an openwrt router running with below dhcp reservation done in /etc/config/dhcp,

config host
        option dns '1'
        option name 'pinas'
        option mac 'xxxx'
        option ip '192.168.0.195'
        option leasetime '6h'
        option duid 'xxxx'
        option hostid '95'

config host
        option dns '1'
        option name 'raspberrypi'
        option mac 'xxxx'
        option ip '192.168.0.6'
        option leasetime '6h'
        option duid 'xxxxxx'
        option hostid '06'

I self host a website by using ddns and IPv6 (only)

My IPv6 address is not static but not changing so frequent (so far its been 3 days and IPv6 address not changed). If Router is restarted I will get a new IPv6 address.

Currently I am running a custom ddns update shell script on the clients every 5 minutes to check for IPv6 address changes, and if changed update it.

As I found out IPv6 address is not changing frequently, I was thinking if there is any other trigger I can setup to run these scripts. Such as, whenever IPv6 address changes on router, run these script. Any thoughts?

Note: I would like to avoid hitting ddns servers' API unnecessarily.

https://openwrt.org/docs/guide-user/base-system/hotplug

you can make use the dhcp or neigh trigger in openwrt using hotplug scripts.

Thank you
I will read through.

You don't need to hit the http API. Just check the record and if the wan address is different, only then init an update via the API.

1 Like

That exactly I am doing, but to check the record, I need to hit the api (--request GET --url https://dynv6.com/api/v2/zones/$dynv6_zoneid/records)

Edit - or are you suggesting use something like nslookup to get the ipaddress of dnsname?

Why not use dig from the bind-dig package?

2 Likes

Got it.
so do dig +short <my dns> AAAA

1 Like

You are using dynv6 they allow to only update the IPv6 prefix by specificing the ipv6prefix value.

With this you can update all hosts when you detect a change of prefix. As the host DUID is statically defined by your dhcp server.

Some hints:
https://community.dynv6.com/t/can-openwrt-update-ipv6-prefix-automatically/1906

https://embeng.dynv6.net/dynamic-dns-on-openwrt-by-nsupdate

Thank you for that tip.
The first link you put is not opening.
I am currently using a custom shell script that calls dynv6 api (I some how prefer that over the openwrt ddns app)

Currently I use below call to update the main zone IP,

curl --request PATCH \
  --url https://dynv6.com/api/v2/zones/<MY_ZONE_ID> \
  --header 'Authorization: Bearer <API_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "ipv6prefix": "xxxx:xxxx:xx:xxxxx::6"
}'

and below to update the record,

curl --request PATCH \
  --url https://dynv6.com/api/v2/zones/<MY_ZONE_ID>/records/<RECORD_ID> \
  --header 'Authorization: Bearer <API_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "website",
  "priority": 65535,
  "port": 65535,
  "weight": 65535,
  "flags": 0,
  "tag": "issue",
  "data": "xxxx:xxxx:xx:xxxx::6",
  "expandedData": "string",
  "id": <RECORD_ID>,
  "zoneID": 0,
  "type": "AAAA"
}'

I have to make two API calls. One to update main, and another to update record.
Is that the same you are saying?

You should not need two API calls. As you are updating an address in the first example and not only the prefix.

:man_facepalming:

Don't ask me, but I totally missed that...

root@cpe:~# cat /usr/local/sbin/update-dynv6.sh
#!/bin/sh

hostname="example.dynv6.net"
token="XXX"

ipv4="$( ip -4 -j addr show dev pppoe-wan | jq -r '.[] | .addr_info[] | .local' )"
ipv6="$( ip -6 -j addr show dev pppoe-wan | jq -r '.[] | .addr_info[] | select( .scope | inside("global") ) | .local' )"

test "${ipv4}" != "$( dig @ns1.dynv6.com. +short -t A "${hostname}" )" \
&& {
    curl "http://dynv6.com/api/update?hostname=${hostname}&token=${token}&ipv4=${ipv4}"; echo
}

test "${ipv6}" != "$( dig @ns1.dynv6.com. +short -t AAAA "${hostname}" )" \
&& {
    curl "http://dynv6.com/api/update?hostname=${hostname}&token=${token}&ipv6=${ipv6}/128"; echo
}

exit 0
root@cpe:~# cat /etc/crontabs/root
*/5     *       *       *       *       /usr/local/sbin/update-dynv6.sh

But this only sets the wan-interface GUA. I use that only for a dial-in point for wireguard.
In your case, where is your web-server running? (If its a host inside your local network, this script should run on the server; for IPv6.)

I have made several bash scripts for IPv6 to do the same thing for my ddns - https://saudiqbal.github.io

As you can see below, I have a main domain (zone) and subdomain (AAAA records)

The prefix address for main domain and subdomains will be same, however the suffix(hostid) will be different.

That's why I am running two curls, one for main and one for records.

Works only for the main zone dns name update.
For records update, its a different call.

1 Like

Ah ok ... Good to know.