Skip to content

Instantly share code, notes, and snippets.

@ankurpandeyvns
Created September 16, 2025 13:56
Show Gist options
  • Select an option

  • Save ankurpandeyvns/0d2256086f94f13808a2f6b70f1dc307 to your computer and use it in GitHub Desktop.

Select an option

Save ankurpandeyvns/0d2256086f94f13808a2f6b70f1dc307 to your computer and use it in GitHub Desktop.
This redirects the traffic on IPv6 for DNS and NTP to respective services
#!/bin/sh
#
# 20-force-dns-ntp6.sh ── Blanket IPv6 DNS + NTP interception on UniFi
# DNS : Any → AdGuard (MAC 02:42:c0:a8:00:02) ➜ port 53
# NTP : Any → unRAID (MAC 48:22:54:42:ba:fc) ➜ port 123
# …but **skip packets whose source MAC is unRAID itself** to avoid
# an endless redirect loop on its outbound NTP queries.
#
# Works on UniFi gateways that honour ip6tables rules (UDM, UCG Ultra, etc.)
# Place in /mnt/data/on_boot.d and make executable so it survives upgrades.
LAN_IF="br0"
# ── Target MACs ─────────────────────────────────────────────────────────────
ADG_MAC="" # AdGuard
URD_MAC="" # unRAID (NTP server & client)
# ── Optional static fall-backs (used only if discovery fails) ───────────────
FALLBACK_ADG="fd00:adg::53"
FALLBACK_URD="fd00:urd::123"
PING_WAIT=6 # seconds to await NDP replies
##############################################################################
# 1. Refresh neighbour table so we see the latest global IPv6 addresses.
##############################################################################
ping6 -c1 -w "$PING_WAIT" ff02::1%"$LAN_IF" >/dev/null 2>&1
lookup_ip6 () {
ip -6 neigh show dev "$LAN_IF" \
| awk -v mac="$1" '$0 ~ mac && $1 !~ /^fe80::/ {print $1; exit}'
}
ADG_IP6="$(lookup_ip6 "$ADG_MAC")"
URD_IP6="$(lookup_ip6 "$URD_MAC")"
[ -z "$ADG_IP6" ] && ADG_IP6="$FALLBACK_ADG"
[ -z "$URD_IP6" ] && URD_IP6="$FALLBACK_URD"
echo "AdGuard IPv6 ➜ $ADG_IP6"
echo "unRAID IPv6 ➜ $URD_IP6"
##############################################################################
# 2. Strip any previous rules we created (dns6-redirect / ntp6-redirect / ntp6-pass)
##############################################################################
for TAG in dns6-redirect ntp6-redirect ntp6-pass; do
ip6tables -t nat -S PREROUTING \
| grep -- "--comment \"$TAG\"" \
| while read -r rule; do
ip6tables -t nat ${rule/-A/-D}
done
done
##############################################################################
# 3. Add PASS-THROUGH for unRAID’s own NTP traffic so it isn’t re-routed.
##############################################################################
for proto in udp tcp; do
ip6tables -t nat -I PREROUTING 1 -i "$LAN_IF" \
-p "$proto" --dport 123 \
-m mac --mac-source "$URD_MAC" \
-m comment --comment "ntp6-pass" \
-j ACCEPT
done
##############################################################################
# 4. Add fresh DNS redirects (port 53) for everyone else → AdGuard.
##############################################################################
for proto in udp tcp; do
ip6tables -t nat -A PREROUTING -i "$LAN_IF" \
-p "$proto" --dport 53 \
-m comment --comment "dns6-redirect" \
-j DNAT --to-destination "$ADG_IP6"
done
##############################################################################
# 5. Add fresh NTP redirects (port 123) for everyone else → unRAID.
# Because the pass-through rule is *first* in the chain, packets from
# unRAID’s MAC never hit these DNAT rules.
##############################################################################
for proto in udp tcp; do
ip6tables -t nat -A PREROUTING -i "$LAN_IF" \
-p "$proto" --dport 123 \
-m mac ! --mac-source "$URD_MAC" \
-m comment --comment "ntp6-redirect" \
-j DNAT --to-destination "$URD_IP6"
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment