Last active
February 11, 2023 02:12
-
-
Save ae-s/781962e2e2d3ae3c5543f5ee84e9b334 to your computer and use it in GitHub Desktop.
nsupdate $(ip neigh list)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Tiny tool to run as a cronjob, which will update | |
# (using nsupdate) your zone files to include dhcp- | |
# and statelessly-assigned addresses. | |
# Space-separated list of address-to-name resolution methods to try. | |
# They'll be tried in the order listed here. | |
METHODS="hostfile avahi localdns" | |
# Zone to update for each type of IP address. In my home network, | |
# ipv4 is natted but ipv6 is globally reachable. So I only publish | |
# records for ipv6 addresses. | |
ZONE4= | |
ZONE4KEY= | |
ZONE6=lab.xrtc.net. | |
ZONE6KEY=/config/Klab.xrtc.net.private | |
# Subnets to restrict query to. In my home network, 192.168.0.0/24 is | |
# available for guest use, while 22.2.3.0/24 is hosts that I actually | |
# care about. | |
# | |
# Restricting NET6 to 2000::/3 will only publish globally reachable | |
# IPv6 addresses. | |
NET4=22.2.3.0/24 | |
NET6=2000::/3 | |
IF4=br0 | |
IF6=br0 | |
zeroize_macaddrs () | |
{ | |
sed -e 's/\(\s\)\([0-9a-f]\):/\10\2:/' -e 's/\([^0-9a-f]\)\([0-9a-f]\):/\10\2:/g' -e 's/:\([0-9a-f]\)$/:0\1/' | |
} | |
lowercase () | |
{ | |
tr A-Z a-z | |
} | |
# Some DHCP servers can be configured to update the /etc/hosts file | |
# with the MAC address. If yours does this, the records it puts in | |
# will be useful for other address families too! | |
# | |
# If your DHCP server does this but treats leading zeros in MAC | |
# addresses differently than 'ip', then, well, you're intermittently | |
# fucked. | |
resolve_hostfile () | |
{ | |
local ip mac name_ip_raw name_ip name_mac_raw name_mac | |
ip="$1" | |
mac="$2" | |
name_ip_raw=$( fgrep -i "$ip" /etc/hosts | lowercase | cut -f2 ) | |
# Remove domain name, if present | |
name_ip=${name_ip_raw%%.*} | |
name_mac_raw=$( cat /etc/hosts | lowercase | zeroize_macaddrs | fgrep -i "$mac" | cut -f2 ) | |
# Remove domain name, if present | |
name_mac=${name_mac_raw%%.*} | |
# Prefer the IP-matched name, but also accept MAC-matched name. | |
echo ${name_ip:-$name_mac} | |
} | |
# nope | |
resolve_avahi () | |
{ | |
echo | |
} | |
# Maybe localhost has a DNS server that knows things! | |
resolve_localdns () | |
{ | |
local ip name_raw name | |
ip="$1" | |
name_raw=$( host "$ip" localhost | tail -n 1 | cut -d\ -f5 ) | |
name=${name_raw%%.*} | |
echo $name | |
} | |
list4 () | |
{ | |
ip neigh show ${IF4:+dev $IF4} to ${NET4:-0/0} |\ | |
lowercase |\ | |
grep lladdr |\ | |
zeroize_macaddrs |\ | |
cut -d\ -f1,3 | |
} | |
list6 () | |
{ | |
ip neigh show ${IF6:+dev $IF6} to ${NET6:-::/0} |\ | |
lowercase |\ | |
grep lladdr |\ | |
zeroize_macaddrs |\ | |
cut -d\ -f1,3 | |
} | |
do_resolve () | |
{ | |
local method name addr mac | |
addr="$1" | |
mac="$2" | |
unset name | |
# try, in order, all the configured resolution methods | |
for method in $METHODS ; do | |
name=$( resolve_$method $addr $mac ) | |
# if we got a name that's nonempty, that's a winner! | |
if [ x"$name" != "x" ] ; then | |
#echo found $addr as $name using $method >&2 | |
break | |
fi | |
done | |
echo "$name" | |
} | |
do_update () | |
{ | |
# Remove any old record and add the new one | |
echo update delete $2 $3 | |
echo update add $2 30 $3 $1 | |
} | |
do_entry () | |
{ | |
local addr mac zone name | |
addr="$1" | |
mac="$2" | |
zone="$3" | |
type="$4" | |
name=$( do_resolve $addr $mac ) | |
# no name for this address, sorry bub | |
if [ x"$name" == "x" ] ; then return ; fi | |
if [ x"$name" == "x3(NXDOMAIN)" ] ; then return ; fi | |
#echo do_update addr =$addr name =$name zone =$zone | |
do_update $addr $name.$zone $type | |
} | |
if [ x"$ZONE4" != "x" ] ; then | |
( echo zone $ZONE4 | |
list4 | while read addr mac ; do | |
do_entry $addr $mac $ZONE4 A | |
done | |
echo send | |
echo show | |
) | nsupdate -k "$ZONE4KEY" | |
fi | |
if [ x"$ZONE6" != "x" ] ; then | |
( echo zone $ZONE6 | |
#echo update delete | |
list6 | while read addr mac ; do | |
do_entry $addr $mac $ZONE6 AAAA | |
done | |
echo show | |
echo send | |
) | nsupdate -k "$ZONE6KEY" | |
fi | |
# Now, after we've added all these, flush the cache so that only new | |
# addresses are added in the future. This is sub-optimal because it | |
# will cause requests for neighbors to be reissued before necessary, | |
# but ... whatever. Computers can deal and I'm not running a very big | |
# network. | |
ip neigh flush dev $IF4 | |
ip neigh flush dev $IF6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment