So. What I need to do is dynamic DNS updates on an authorative BIND9 DNS server for both IPv4 and IPv6 addresses.
This can be easily done with dhcpd with something like this added to conf:
But dnsmasq doesn't support this. Or if it does I haven't figured out how after spending a lot of time reading documentation
(as I have never worked with it before other than adding it as a caching solution). They really want you to use dnsmasq for DNS
but apparently that's not always wanted or feasible, depending on network topology and what you want to achieve. Frankly since
they do DHCP they should also support updating external DNS.
So apparently the only way to do this is using a script and nsupdate. Good, no problem there. dnsmasq documentation mentions
--dhcp-script= in order to run custom scripts on leases.
I had a /jffs/scripts/dnsmasq.postconf in order to force ipv6 cloudflare DNS to clients instead of the router and I modify it like this.
I noticed, after checking /tmp/etc/dnsmasq.conf, that the firmware already uses the --dhcp-script option so I am highjacking it
and injecting my script in between:
And add /jffs/scripts/dhcp-dnsupdate which is a script I found for nsupdate which I modified for --dhcp-script and
handling both IPv6 and IPv4.:
It works. BUT only for IPv4.
dnsmasq seems to call the script with "arp-add mac:address ip:v6" for IPv6 addresses, obviously because it's not doing leases, which I can't use.
I could if there was a hostname included but there is not.
Also DNSMASQ_SUPPLIED_HOSTNAME variable, that is mentioned in the documentation, is empty.
So the question is, how can I parse IPv6 addresses with a hostname so I can update AAAA records as well?
I can think of keeping a table of mac addresses from the IPv4 leases and cross-reference that with the mac addresses reported in the arp-add calls to the script
but that is very convoluted and hackish. There must be a better, cleaner way to do this.
This can be easily done with dhcpd with something like this added to conf:
Code:
ddns-domainname "domain.com";
ddns-rev-domainname "in-addr.arpa";
ddns-update-style standard;
update-optimization off;
ignore client-updates;
key dnsupdate {
algorithm "hmac-sha512";
secret "key" >
}
zone domain.com. {
primary 10.0.0.1;
key dnsupdate;
}
zone 0.168.192.in-addr.arpa. {
primary 10.0.0.1;
key dnsupdate;
}
But dnsmasq doesn't support this. Or if it does I haven't figured out how after spending a lot of time reading documentation
(as I have never worked with it before other than adding it as a caching solution). They really want you to use dnsmasq for DNS
but apparently that's not always wanted or feasible, depending on network topology and what you want to achieve. Frankly since
they do DHCP they should also support updating external DNS.
So apparently the only way to do this is using a script and nsupdate. Good, no problem there. dnsmasq documentation mentions
--dhcp-script= in order to run custom scripts on leases.
I had a /jffs/scripts/dnsmasq.postconf in order to force ipv6 cloudflare DNS to clients instead of the router and I modify it like this.
I noticed, after checking /tmp/etc/dnsmasq.conf, that the firmware already uses the --dhcp-script option so I am highjacking it
and injecting my script in between:
Code:
#!/bin/sh
CONFIG=$1
source /usr/sbin/helper.sh
pc_replace "dhcp-option=lan,option6:23,[::]" "dhcp-option=lan,option6:23,[2606:4700:4700::1001],[2606:4700:4700::1111]" $CONFIG
pc_replace "dhcp-script=/sbin/dhcp_lease" "dhcp-script=/jffs/scripts/dhcp-dnsupdate" $CONFIG
pc_append "log-dhcp" $CONFIG
And add /jffs/scripts/dhcp-dnsupdate which is a script I found for nsupdate which I modified for --dhcp-script and
handling both IPv6 and IPv4.:
Code:
#!/opt/bin/bash
# A bash script to update BIND9 DDNS using nsupdate and TSIG key
# Tested with bash and bind-client to be installed from entware-ng
# We hijack the dhcp-script option with this and then call what
# was normally called.
# Exit early, for efficiency, if host is not passed.
if [ -z "$4" ]; then
/sbin/dhcpc_lease $@
exit
fi
#User variables - replace with your variables
NS="ns.domain.com"
ZONE="domain.com"
DHOST="$4.domain.com"
TSIGFILE="/jffs/dnsupdate.key"
NSUPDATE=$(which nsupdate)
IP=$3
TYPE="A"
# Check if we have IPv6 address or not.
if [ "$IP" =~ ":" ]; then
TYPE="AAAA"
fi
# Set nsupdate parameters
echo "server $NS" > /tmp/nsupdate
echo "debug yes" >> /tmp/nsupdate
echo "zone $ZONE." >> /tmp/nsupdate
if [ "$1" = "add" ] || [ "$1" = "old" ]; then
echo "update delete $DHOST $TYPE" >> /tmp/nsupdate
echo "update add $DHOST 600 $TYPE $IP" >> /tmp/nsupdate
elif [ "$1" = "del" ]; then
echo "update delete $DHOST $TYPE" >> /tmp/nsupdate
fi
echo "send" >> /tmp/nsupdate
# Call nsupdate
$NSUPDATE -k $TSIGFILE /tmp/nsupdate 2>&1 &
# Uncomment for debugging
#echo "$@" >> /tmp/ddnsupdate_debug
#Proceed with what the firmware normally does.
/sbin/dhcpc_lease $@
It works. BUT only for IPv4.
dnsmasq seems to call the script with "arp-add mac:address ip:v6" for IPv6 addresses, obviously because it's not doing leases, which I can't use.
I could if there was a hostname included but there is not.
Also DNSMASQ_SUPPLIED_HOSTNAME variable, that is mentioned in the documentation, is empty.
So the question is, how can I parse IPv6 addresses with a hostname so I can update AAAA records as well?
I can think of keeping a table of mac addresses from the IPv4 leases and cross-reference that with the mac addresses reported in the arp-add calls to the script
but that is very convoluted and hackish. There must be a better, cleaner way to do this.
Last edited: