100 lines
3.4 KiB
Bash
100 lines
3.4 KiB
Bash
#!/bin/sh
|
|
# Declarative-ish config for Technitium: ensures the AD conditional
|
|
# forwarder zones exist. Zones that already exist are NOT touched, so
|
|
# manual tweaks in the web console survive re-runs. To re-apply a zone
|
|
# from here, delete it in the console and re-run:
|
|
# docker compose up technitium-init
|
|
set -eu
|
|
|
|
API="http://127.0.0.1:5380/api"
|
|
|
|
: "${TECHNITIUM_ADMIN_PASSWORD:?set in .env}"
|
|
: "${TROCH_DC1_IP:?set in .env}"
|
|
: "${TROCH_DC2_IP:?set in .env}"
|
|
: "${OSWALD_DC_IP:?set in .env}"
|
|
|
|
echo "Waiting for the Technitium API..."
|
|
i=0
|
|
until curl -sf -o /dev/null "$API/user/login" 2>/dev/null; do
|
|
i=$((i + 1))
|
|
[ "$i" -le 60 ] || { echo "ERROR: API not up after 120s" >&2; exit 1; }
|
|
sleep 2
|
|
done
|
|
|
|
TOKEN=$(curl -sf -G "$API/user/login" \
|
|
--data-urlencode "user=admin" \
|
|
--data-urlencode "pass=$TECHNITIUM_ADMIN_PASSWORD" | jq -r '.token // empty')
|
|
[ -n "$TOKEN" ] || { echo "ERROR: login failed — check TECHNITIUM_ADMIN_PASSWORD" >&2; exit 1; }
|
|
AUTH="Authorization: Bearer $TOKEN"
|
|
|
|
ZONES_JSON=$(curl -sf -H "$AUTH" "$API/zones/list?pageNumber=1&zonesPerPage=200")
|
|
|
|
zone_exists() {
|
|
echo "$ZONES_JSON" | jq -e --arg z "$1" \
|
|
'.response.zones[]? | select(.name == $z)' >/dev/null
|
|
}
|
|
|
|
api_ok() { jq -e '.status == "ok"' >/dev/null; }
|
|
|
|
# ensure_fwd_zone <zone> <forwarder> [more forwarders...]
|
|
ensure_fwd_zone() {
|
|
zone=$1; shift
|
|
if zone_exists "$zone"; then
|
|
echo "zone $zone already exists — leaving as-is"
|
|
return 0
|
|
fi
|
|
first=$1; shift
|
|
echo "creating conditional forwarder zone $zone -> $first"
|
|
curl -sf -H "$AUTH" -G "$API/zones/create" \
|
|
--data-urlencode "zone=$zone" \
|
|
--data-urlencode "type=Forwarder" \
|
|
--data-urlencode "initializeForwarder=true" \
|
|
--data-urlencode "protocol=Udp" \
|
|
--data-urlencode "forwarder=$first" \
|
|
--data-urlencode "dnssecValidation=false" | api_ok
|
|
for extra in "$@"; do
|
|
echo " adding forwarder $extra to $zone"
|
|
curl -sf -H "$AUTH" -G "$API/zones/records/add" \
|
|
--data-urlencode "domain=$zone" \
|
|
--data-urlencode "zone=$zone" \
|
|
--data-urlencode "type=FWD" \
|
|
--data-urlencode "protocol=Udp" \
|
|
--data-urlencode "forwarder=$extra" \
|
|
--data-urlencode "dnssecValidation=false" | api_ok
|
|
done
|
|
}
|
|
|
|
# AD forward zones -> DCs over the WireGuard tunnel.
|
|
# ad.atlashorizon.net also covers _msdcs.ad.atlashorizon.net.
|
|
ensure_fwd_zone ad.atlashorizon.net "$TROCH_DC1_IP" "$TROCH_DC2_IP"
|
|
ensure_fwd_zone ad.calliecorner.net "$TROCH_DC1_IP" "$TROCH_DC2_IP"
|
|
ensure_fwd_zone ad.trochalakis.net "$TROCH_DC1_IP" "$TROCH_DC2_IP"
|
|
# Append "$TROCH_DC1_IP" "$TROCH_DC2_IP" here ONLY if this zone replicates
|
|
# forest-wide (ForestDnsZones) to the root DCs:
|
|
ensure_fwd_zone ad.oswaldtheotter.net "$OSWALD_DC_IP"
|
|
|
|
# Reverse zones so PTR lookups for site hosts work
|
|
ensure_fwd_zone 20.168.192.in-addr.arpa "$TROCH_DC1_IP" "$TROCH_DC2_IP"
|
|
ensure_fwd_zone 7.168.192.in-addr.arpa "$OSWALD_DC_IP"
|
|
|
|
# Primary zones for VPN client registration (openvpn learn-address hook
|
|
# writes <username>.$VPN_DNS_ZONE A records + PTRs for 172.31.8.0/24)
|
|
ensure_primary_zone() {
|
|
zone=$1
|
|
if zone_exists "$zone"; then
|
|
echo "zone $zone already exists — leaving as-is"
|
|
return 0
|
|
fi
|
|
echo "creating primary zone $zone"
|
|
curl -sf -H "$AUTH" -G "$API/zones/create" \
|
|
--data-urlencode "zone=$zone" \
|
|
--data-urlencode "type=Primary" | api_ok
|
|
}
|
|
|
|
if [ -n "${VPN_DNS_ZONE:-}" ]; then
|
|
ensure_primary_zone "$VPN_DNS_ZONE"
|
|
ensure_primary_zone "8.31.172.in-addr.arpa"
|
|
fi
|
|
|
|
echo "Technitium AD forwarder zones OK."
|