134 lines
5 KiB
Bash
Executable file
134 lines
5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Subscribe the current host to black.lan's LAN DNS.
|
|
#
|
|
# Why this exists:
|
|
# black.lan (10.0.0.11) runs dnsmasq with `address=/black.lan/10.0.0.11`
|
|
# — a wildcard rule that resolves every *.black.lan hostname to black's
|
|
# LAN IP. The DNS server is already reachable because DHCP hands 10.0.0.11
|
|
# out as one of the assigned DNS servers. The piece still missing on
|
|
# Linux hosts with mDNS disabled is a **resolver routing-domain policy**
|
|
# that tells systemd-resolved "forward *.black.lan queries to my DNS
|
|
# servers instead of treating them as mDNS / refusing them."
|
|
#
|
|
# macOS handles this natively via /etc/resolver/black.lan. Linux needs
|
|
# a drop-in file for systemd-resolved.
|
|
#
|
|
# What this does (idempotent — safe to re-run):
|
|
# * Linux + systemd-resolved: writes
|
|
# /etc/systemd/resolved.conf.d/black-local.conf
|
|
# with `Domains=~black.lan` + `DNS=10.0.0.11`, then reloads resolved.
|
|
# * macOS: writes
|
|
# /etc/resolver/black.lan
|
|
# with `nameserver 10.0.0.11` so the macOS resolver routes black.lan
|
|
# lookups to dnsmasq. No daemon reload needed.
|
|
# * Windows / BSD / other: prints a manual remediation hint.
|
|
#
|
|
# Verify after running:
|
|
# getent hosts mc.next.black.lan # Linux
|
|
# scutil --dns | grep -A2 black.lan # macOS
|
|
# curl -sk https://mc.next.black.lan/ -o /dev/null -w '%{http_code}\n'
|
|
#
|
|
# Usage:
|
|
# bash scripts/lan/subscribe-black-dns.sh # locally
|
|
# ssh <host> 'bash -s' < scripts/lan/subscribe-black-dns.sh # remote
|
|
#
|
|
# Re-run any time after black.lan's IP or DNS-server layout changes.
|
|
|
|
set -euo pipefail
|
|
|
|
readonly BLACK_IP='10.0.0.11'
|
|
readonly BLACK_DOMAIN='black.lan'
|
|
readonly RESOLVED_DROP_IN='/etc/systemd/resolved.conf.d/black-local.conf'
|
|
readonly MACOS_RESOLVER_FILE='/etc/resolver/black.lan'
|
|
|
|
log() { printf '\033[0;34m[subscribe-black-dns]\033[0m %s\n' "$*"; }
|
|
ok() { printf '\033[0;32m[subscribe-black-dns] ✓\033[0m %s\n' "$*"; }
|
|
warn() { printf '\033[1;33m[subscribe-black-dns] !\033[0m %s\n' "$*"; }
|
|
fail() { printf '\033[0;31m[subscribe-black-dns] ✗\033[0m %s\n' "$*" >&2; exit 1; }
|
|
|
|
probe_dns() {
|
|
# Return 0 if `mc.next.black.lan` resolves via the host's normal
|
|
# resolver path. macOS's /etc/resolver/ mechanism isn't visible to
|
|
# NSS-based tools (getent / host / nslookup in some configs), so on
|
|
# Darwin we have to use dscacheutil which IS aware of it.
|
|
case "$(uname -s)" in
|
|
Darwin)
|
|
dscacheutil -q host -a name mc.next.black.lan 2>/dev/null \
|
|
| grep -q "^ip_address: "
|
|
;;
|
|
*)
|
|
getent hosts mc.next.black.lan >/dev/null 2>&1 \
|
|
|| host mc.next.black.lan >/dev/null 2>&1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
configure_linux_systemd_resolved() {
|
|
if ! command -v systemctl >/dev/null 2>&1; then
|
|
fail "systemctl not found — this script's Linux branch assumes systemd."
|
|
fi
|
|
if ! systemctl is-active --quiet systemd-resolved; then
|
|
warn "systemd-resolved is not active; skipping routing-domain drop-in."
|
|
warn "Configure your resolver manually: point *.${BLACK_DOMAIN} at ${BLACK_IP}."
|
|
return 0
|
|
fi
|
|
|
|
local payload
|
|
payload="$(cat <<EOF
|
|
# Managed by scripts/lan/subscribe-black-dns.sh — routing-domain override so
|
|
# *.${BLACK_DOMAIN} queries reach black's dnsmasq instead of being refused
|
|
# as mDNS. Regenerate by re-running the script; do not hand-edit.
|
|
|
|
[Resolve]
|
|
DNS=${BLACK_IP}
|
|
Domains=~${BLACK_DOMAIN}
|
|
EOF
|
|
)"
|
|
|
|
if [ -f "$RESOLVED_DROP_IN" ] && [ "$(cat "$RESOLVED_DROP_IN")" = "$payload" ]; then
|
|
ok "already subscribed (${RESOLVED_DROP_IN} up to date)"
|
|
else
|
|
log "writing ${RESOLVED_DROP_IN}"
|
|
sudo mkdir -p "$(dirname "$RESOLVED_DROP_IN")"
|
|
printf '%s\n' "$payload" | sudo tee "$RESOLVED_DROP_IN" >/dev/null
|
|
log "reloading systemd-resolved"
|
|
sudo systemctl reload systemd-resolved
|
|
ok "systemd-resolved reloaded"
|
|
fi
|
|
}
|
|
|
|
configure_macos_resolver() {
|
|
local payload="nameserver ${BLACK_IP}"
|
|
|
|
if [ -f "$MACOS_RESOLVER_FILE" ] && grep -qx "$payload" "$MACOS_RESOLVER_FILE"; then
|
|
ok "already subscribed (${MACOS_RESOLVER_FILE} up to date)"
|
|
return 0
|
|
fi
|
|
|
|
log "writing ${MACOS_RESOLVER_FILE}"
|
|
sudo mkdir -p "$(dirname "$MACOS_RESOLVER_FILE")"
|
|
printf '%s\n' "$payload" | sudo tee "$MACOS_RESOLVER_FILE" >/dev/null
|
|
ok "macOS resolver file installed (no daemon reload needed)"
|
|
}
|
|
|
|
verify() {
|
|
if probe_dns; then
|
|
ok "mc.next.black.lan resolves via this host's resolver"
|
|
else
|
|
warn "mc.next.black.lan still doesn't resolve — check that black (${BLACK_IP}) is reachable:"
|
|
warn " ping -c 1 ${BLACK_IP}"
|
|
warn " dig @${BLACK_IP} mc.${BLACK_DOMAIN}"
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
log "host: $(hostname) · OS: $(uname -s)"
|
|
case "$(uname -s)" in
|
|
Linux) configure_linux_systemd_resolved ;;
|
|
Darwin) configure_macos_resolver ;;
|
|
*) fail "Unsupported OS: $(uname -s). Route *.${BLACK_DOMAIN} to ${BLACK_IP} via your resolver of choice." ;;
|
|
esac
|
|
verify
|
|
}
|
|
|
|
main "$@"
|