#!/bin/bash
#
# SOCKS proxy startup. Configures routing + DNS for the chosen vantage,
# then exec's dante-server. Requires --cap-add NET_ADMIN on `docker run`
# so we can rewrite the routing table.
set -e

VANTAGE="${VANTAGE:-isp-external}"

case "$VANTAGE" in
  isp-external)
    # Residential-user view. Default route via fw-ext (.101) which DNATs
    # public-internet traffic into the dmz (caddy at 10.226.10.10). DNS via
    # comcast-resolver (.1) which walks the root → TLD → namecheap chain.
    GATEWAY="203.0.113.101"
    NAMESERVER="203.0.113.1"
    ;;
  internal)
    # Operator-on-LAN view. Default route via fw-isp (.1); split-horizon
    # resolver at .10 returns the firewall's same-subnet NAT IP for the
    # test domain, which DNATs to caddy.
    GATEWAY="10.226.1.1"
    NAMESERVER="10.226.1.10"
    ;;
  *)
    echo "Unknown VANTAGE: $VANTAGE (expected isp-external or internal)" >&2
    exit 1
    ;;
esac

# Replace docker's IPAM-default gateway (which has no router listening)
# with the actual zone gateway. del-then-add is idempotent against a
# possibly-missing prior default route.
ip route del default 2>/dev/null || true
ip route add default via "$GATEWAY"

# An explicit resolver from the caller wins over the vantage default. The proxy
# is what resolves names for a SOCKS5 client — a browser hands it the hostname
# and never resolves it itself — so a test driving a browser at a name only the
# fleet's own resolver knows has to say so here. Modelling a real device: one
# on the internal zone is handed the fleet's resolver, not a fixed stub.
NAMESERVER="${NAMESERVER_OVERRIDE:-$NAMESERVER}"

# Bypass docker's embedded resolver — point directly at the in-network
# DNS so split-horizon and the namecheap simulator both behave correctly.
echo "nameserver $NAMESERVER" > /etc/resolv.conf

echo "socks-proxy ready: vantage=$VANTAGE gateway=$GATEWAY dns=$NAMESERVER" >&2

# TEACH DANTE ABOUT THE TUNNEL ONCE IT EXISTS.
#
# danted.conf names `external: eth0`, the interface dante binds OUTBOUND
# connections to. That is correct at startup and wrong the moment a test brings
# up a WireGuard tunnel: a destination routed over wg0 is then dialled from
# eth0's address, and the far side drops it. The symptom is that a client INSIDE
# this container reaches the target fine (ordinary routing picks wg0) while the
# same target through the SOCKS port times out — so the proxy looks up, the
# tunnel looks up, and only the relay fails.
#
# Measured 2026-09-26 (celilo#1438): celilo-web-console-oidc stage 6 passed
# (its curl runs inside the container) and stage 7 failed with
# `net::ERR_TIMED_OUT` on the identical URL through the proxy. From the host:
# inside=302, via-socks=000.
#
# wg0 does not exist when danted starts, so it cannot simply be listed. This
# watches for it, adds it, and reloads — and VERIFIES the config first, because
# a danted that dies on a bad reload takes the proxy out for every suite.
(
  while :; do
    if ip link show wg0 >/dev/null 2>&1; then
      if ! grep -q '^external: wg0' /etc/danted.conf; then
        cp /etc/danted.conf /tmp/danted.conf.pre-wg0
        sed -i 's|^external: eth0$|external: eth0\nexternal: wg0\nexternal.rotation: route|' /etc/danted.conf
        # READ THE OUTPUT, NOT THE EXIT CODE. `danted -V` exits 0 even on a
        # config it refuses outright — measured 2026-09-26: a config naming a
        # nonexistent interface logged `error: ... could not resolve hostname`
        # and `alert: mother[1/1]: shutting down`, and still returned 0. A guard
        # keyed on the status would have HUPped a config danted cannot load and
        # killed the proxy for every suite, which is the thing it exists to stop.
        /usr/sbin/danted -V -f /etc/danted.conf >/tmp/danted-verify.log 2>&1 || true
        if ! grep -qiE '(^|[^a-z])(error|alert):' /tmp/danted-verify.log; then
          kill -HUP 1 2>/dev/null || true
          echo "socks-proxy: wg0 up, danted now routes outbound by route" >&2
        else
          cp /tmp/danted.conf.pre-wg0 /etc/danted.conf
          echo "socks-proxy: REFUSED to reload danted, config invalid — proxy left on eth0 only:" >&2
          tail -3 /tmp/danted-verify.log >&2
        fi
      fi
      break
    fi
    sleep 1
  done
) &

exec /usr/sbin/danted -f /etc/danted.conf
