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

# Example installer for a clean Ubuntu/Debian VPS.
# This file intentionally contains no real domains, passwords, PSK values or server IPs.
#
# Usage example:
#   export VPN_DOMAIN="vpn.example.com"
#   export VPN_PUBLIC_IP="203.0.113.10"
#   sudo -E bash install-strongswan-hub-example.sh

VPN_DOMAIN="${VPN_DOMAIN:-vpn.example.com}"
VPN_PUBLIC_IP="${VPN_PUBLIC_IP:-203.0.113.10}"
HUB_LAN="${HUB_LAN:-10.0.0.0/24}"

OFFICE1_ID="${OFFICE1_ID:-office1-router}"
OFFICE1_LAN="${OFFICE1_LAN:-192.168.10.0/24}"
OFFICE1_PSK="${OFFICE1_PSK:-CHANGE_ME_OFFICE1_LONG_RANDOM_PSK}"

OFFICE2_ID="${OFFICE2_ID:-office2-router}"
OFFICE2_LAN="${OFFICE2_LAN:-192.168.11.0/24}"
OFFICE2_PSK="${OFFICE2_PSK:-CHANGE_ME_OFFICE2_LONG_RANDOM_PSK}"

OFFICE3_ID="${OFFICE3_ID:-office3-router}"
OFFICE3_LAN="${OFFICE3_LAN:-192.168.12.0/24}"
OFFICE3_PSK="${OFFICE3_PSK:-CHANGE_ME_OFFICE3_LONG_RANDOM_PSK}"

if [[ "${EUID}" -ne 0 ]]; then
  echo "Run as root: sudo -E bash $0" >&2
  exit 1
fi

apt-get update
apt-get install -y strongswan strongswan-swanctl strongswan-pki ufw tcpdump curl ca-certificates

install -d -m 700 /etc/swanctl
install -d -m 700 /etc/swanctl/conf.d

cat >/etc/sysctl.d/99-vpn-forwarding.conf <<SYSCTL
net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
SYSCTL
sysctl --system

ufw allow 22/tcp
ufw allow 500/udp
ufw allow 4500/udp
ufw --force enable

cat >/etc/swanctl/swanctl.conf <<SWANCTL
connections {
  site-office1 {
    version = 2
    local_addrs = %any
    remote_addrs = %any
    proposals = aes256-sha256-modp2048
    local {
      auth = psk
      id = "${VPN_DOMAIN}"
    }
    remote {
      auth = psk
      id = "${OFFICE1_ID}"
    }
    children {
      net {
        local_ts = ${HUB_LAN},${OFFICE2_LAN},${OFFICE3_LAN}
        remote_ts = ${OFFICE1_LAN}
        esp_proposals = aes256-sha256-modp2048
        start_action = trap
        close_action = trap
        dpd_action = restart
      }
    }
  }

  site-office2 {
    version = 2
    local_addrs = %any
    remote_addrs = %any
    proposals = aes256-sha256-modp2048
    local {
      auth = psk
      id = "${VPN_DOMAIN}"
    }
    remote {
      auth = psk
      id = "${OFFICE2_ID}"
    }
    children {
      net {
        local_ts = ${HUB_LAN},${OFFICE1_LAN},${OFFICE3_LAN}
        remote_ts = ${OFFICE2_LAN}
        esp_proposals = aes256-sha256-modp2048
        start_action = trap
        close_action = trap
        dpd_action = restart
      }
    }
  }

  site-office3 {
    version = 2
    local_addrs = %any
    remote_addrs = %any
    proposals = aes256-sha256-modp2048
    local {
      auth = psk
      id = "${VPN_DOMAIN}"
    }
    remote {
      auth = psk
      id = "${OFFICE3_ID}"
    }
    children {
      net {
        local_ts = ${HUB_LAN},${OFFICE1_LAN},${OFFICE2_LAN}
        remote_ts = ${OFFICE3_LAN}
        esp_proposals = aes256-sha256-modp2048
        start_action = trap
        close_action = trap
        dpd_action = restart
      }
    }
  }
}

secrets {
  ike-office1 {
    id = "${OFFICE1_ID}"
    secret = "${OFFICE1_PSK}"
  }
  ike-office2 {
    id = "${OFFICE2_ID}"
    secret = "${OFFICE2_PSK}"
  }
  ike-office3 {
    id = "${OFFICE3_ID}"
    secret = "${OFFICE3_PSK}"
  }
}
SWANCTL

chmod 600 /etc/swanctl/swanctl.conf

for src in "${OFFICE1_LAN}" "${OFFICE2_LAN}" "${OFFICE3_LAN}" "${HUB_LAN}"; do
  for dst in "${OFFICE1_LAN}" "${OFFICE2_LAN}" "${OFFICE3_LAN}" "${HUB_LAN}"; do
    [[ "${src}" == "${dst}" ]] && continue
    ufw route allow from "${src}" to "${dst}" || true
  done
done

systemctl enable --now strongswan || systemctl enable --now strongswan-starter || true
swanctl --load-all || true

cat <<INFO
Done.

VPN public endpoint: ${VPN_PUBLIC_IP}
VPN server ID:       ${VPN_DOMAIN}

Check:
  swanctl --list-conns
  swanctl --list-sas
  journalctl -u strongswan --no-pager -n 100
INFO
