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

FRP_VERSION="0.69.0"
PUBLIC_BASE_URL="https://filesv.vnstech.cloud/frp"
SERVER_ADDR="103.56.161.160"
SERVER_PORT="7000"
REMOTE_PORT="60022"
LOCAL_PORT="22"
PROXY_URL="${HTTPS_PROXY:-${https_proxy:-${HTTP_PROXY:-${http_proxy:-}}}}"
TOKEN="${FRP_TOKEN:-}"

usage() {
  cat <<'EOF'
Install frpc on an Ubuntu private server and expose its local SSH through frps.

Usage:
  sudo bash install-frpc-ubuntu.sh [options]

Options:
  --proxy-url URL       HTTP proxy used by frpc and installer, e.g. http://proxy.local:3128
  --token TOKEN         Token from the public FRP server
  --server-addr HOST    Public frps host, default: 103.56.161.160
  --server-port PORT    Public frps control port, default: 7000
  --remote-port PORT    Reverse SSH port opened on frps, default: 60022
  --local-port PORT     Local SSH port on this private server, default: 22
  -h, --help            Show help

The HTTP proxy must permit CONNECT to SERVER_ADDR:SERVER_PORT.
EOF
}

die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
while [ "$#" -gt 0 ]; do
  case "$1" in
    --proxy-url) PROXY_URL="$2"; shift 2 ;;
    --token) TOKEN="$2"; shift 2 ;;
    --server-addr) SERVER_ADDR="$2"; shift 2 ;;
    --server-port) SERVER_PORT="$2"; shift 2 ;;
    --remote-port) REMOTE_PORT="$2"; shift 2 ;;
    --local-port) LOCAL_PORT="$2"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    *) die "Unknown option: $1" ;;
  esac
done

[ "$(id -u)" -eq 0 ] || die 'Run this installer with sudo or as root.'
command -v curl >/dev/null 2>&1 || die 'curl is required.'
command -v sha256sum >/dev/null 2>&1 || die 'sha256sum is required.'
command -v tar >/dev/null 2>&1 || die 'tar is required.'
case "$SERVER_PORT:$REMOTE_PORT:$LOCAL_PORT" in *[!0-9:]*) die 'Ports must be numeric.' ;; esac

if [ -z "$TOKEN" ] && [ -t 0 ]; then
  printf 'FRP token: '
  read -r -s TOKEN
  printf '\n'
fi
[ -n "$TOKEN" ] || die 'Missing --token or FRP_TOKEN.'

case "$(uname -m)" in
  x86_64|amd64)
    ARCH="amd64"
    SHA256="6b90d1cd28fc661f170c0de90dde03d2c63e4fd7ce0ae2da2ca1c28014b8146e"
    ;;
  aarch64|arm64)
    ARCH="arm64"
    SHA256="24a4fc82b4c041835103419685ea124c4d6a7dbf83d0425481c5831b4ce4b3a4"
    ;;
  *) die "Unsupported architecture: $(uname -m)" ;;
esac

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
PACKAGE="frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
CURL_ARGS=(-fL --retry 3 --connect-timeout 15)
if [ -n "$PROXY_URL" ]; then CURL_ARGS+=(--proxy "$PROXY_URL"); fi
printf 'Downloading frpc %s for %s...\n' "$FRP_VERSION" "$ARCH"
curl "${CURL_ARGS[@]}" -o "$TMP_DIR/$PACKAGE" "$PUBLIC_BASE_URL/$PACKAGE"
printf '%s  %s\n' "$SHA256" "$TMP_DIR/$PACKAGE" | sha256sum -c -
tar -xzf "$TMP_DIR/$PACKAGE" -C "$TMP_DIR"
install -m 0755 "$TMP_DIR/frp_${FRP_VERSION}_linux_${ARCH}/frpc" /usr/local/bin/frpc

id frp >/dev/null 2>&1 || useradd --system --home /nonexistent --shell /usr/sbin/nologin frp
install -d -m 0750 -o root -g frp /etc/frp
umask 077
cat > /etc/frp/frpc.toml <<EOF
serverAddr = "$SERVER_ADDR"
serverPort = $SERVER_PORT

auth.method = "token"
auth.token = "$TOKEN"

transport.protocol = "tcp"
transport.tls.enable = true
EOF
if [ -n "$PROXY_URL" ]; then
  printf 'transport.proxyURL = "%s"\n' "$PROXY_URL" >> /etc/frp/frpc.toml
fi
cat >> /etc/frp/frpc.toml <<EOF

[[proxies]]
name = "private-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = $LOCAL_PORT
remotePort = $REMOTE_PORT
EOF
chown root:frp /etc/frp/frpc.toml
chmod 640 /etc/frp/frpc.toml

cat > /etc/systemd/system/frpc.service <<'EOF'
[Unit]
Description=FRP private reverse SSH client
After=network-online.target ssh.service
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now frpc
sleep 2
systemctl is-active --quiet frpc || {
  journalctl -u frpc --no-pager -n 30 >&2
  die 'frpc did not start.'
}
printf '\nfrpc is running. Reverse SSH endpoint:\n'
printf '  ssh -p %s PRIVATE_USER@%s\n' "$REMOTE_PORT" "$SERVER_ADDR"
printf '\nStatus commands:\n'
printf '  systemctl status frpc\n'
printf '  journalctl -u frpc -f\n'
