#!/usr/bin/env bash
set -euo pipefail

TABLE="spotproxy"
REDSOCKS_PORT=12345

usage() {
    echo "Usage:"
    echo "  sudo $0 enable USERNAME"
    echo "  sudo $0 disable USERNAME"
    echo "  sudo $0 status"
    exit 1
}

[[ $EUID -eq 0 ]] || {
    echo "Must run as root."
    exit 1
}

ACTION="${1:-}"
USERNAME="${2:-}"

enable_user() {
    id "$USERNAME" >/dev/null 2>&1 || {
        echo "Unknown user: $USERNAME"
        exit 1
    }

    UID_NUM="$(id -u "$USERNAME")"

    # Recreate our tables from a known state.
    nft delete table ip "$TABLE" 2>/dev/null || true
    nft delete table ip6 "$TABLE" 2>/dev/null || true

    # IPv4: transparently redirect HTTP/HTTPS to redsocks.
    nft add table ip "$TABLE"
    nft "add chain ip $TABLE output {
        type nat hook output priority -100;
        policy accept;
    }"

    nft add rule ip "$TABLE" output \
        meta skuid "$UID_NUM" \
        ip daddr != 127.0.0.0/8 \
        tcp dport '{ 80, 443 }' \
        redirect to :"$REDSOCKS_PORT"

    # IPv6: prevent HTTP/HTTPS from bypassing the IPv4 proxy.
    nft add table ip6 "$TABLE"
    nft "add chain ip6 $TABLE output {
        type filter hook output priority 0;
        policy accept;
    }"

    nft add rule ip6 "$TABLE" output \
        meta skuid "$UID_NUM" \
        tcp dport '{ 80, 443 }' \
        reject

    echo "SpotProxy enabled for:"
    echo "  User: $USERNAME"
    echo "  UID:  $UID_NUM"
    echo
    echo "IPv4 TCP 80/443 -> redsocks :$REDSOCKS_PORT"
    echo "IPv6 TCP 80/443 -> REJECT"
}

disable_user() {
    # Prototype currently has one proxied user at a time.
    nft delete table ip "$TABLE" 2>/dev/null || true
    nft delete table ip6 "$TABLE" 2>/dev/null || true

    echo "SpotProxy routing disabled."
}

status() {
    echo "=== IPv4 ==="
    nft list table ip "$TABLE" 2>/dev/null ||
        echo "Not enabled"

    echo
    echo "=== IPv6 ==="
    nft list table ip6 "$TABLE" 2>/dev/null ||
        echo "Not enabled"
}

case "$ACTION" in
    enable)
        [[ -n "$USERNAME" ]] || usage
        enable_user
        ;;
    disable)
        disable_user
        ;;
    status)
        status
        ;;
    *)
        usage
        ;;
esac
