#!/usr/bin/env bash

set -euo pipefail

usage() {
  echo "Usage: $0 {add|del} <target_ip> <start_port-end_port>" >&2
  echo "Example: $0 add 100.123.70.77 20000-20299" >&2
  exit 1
}

if [[ $# -ne 3 ]]; then
  usage
fi

action="$1"
target_ip="$2"
port_range="$3"

if [[ "$action" != "add" && "$action" != "del" ]]; then
  echo "[ERROR] action must be 'add' or 'del'." >&2
  usage
fi

# 简单校验 IP 格式（不做严格校验，只避免明显错误）
if ! [[ "$target_ip" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
  echo "[ERROR] invalid target_ip: $target_ip" >&2
  exit 1
fi

# 解析端口范围: start-end
if ! [[ "$port_range" =~ ^([0-9]+)-([0-9]+)$ ]]; then
  echo "[ERROR] port range must be in format start-end, e.g. 20000-20299" >&2
  exit 1
fi

start_port="${BASH_REMATCH[1]}"
end_port="${BASH_REMATCH[2]}"

if (( start_port <= 0 || start_port > 65535 || end_port <= 0 || end_port > 65535 || start_port > end_port )); then
  echo "[ERROR] invalid port range: $start_port-$end_port" >&2
  exit 1
fi

# 必须用 root 运行
if [[ $EUID -ne 0 ]]; then
  echo "[ERROR] Please run as root, e.g. sudo $0 $action $target_ip $port_range" >&2
  exit 1
fi

# 获取公网 IP（仅用于打印信息，iptables 规则不依赖它）
public_ip="$(curl -s --max-time 5 ifconfig.me || true)"
if [[ -z "$public_ip" ]]; then
  public_ip="UNKNOWN"
fi

# 确保开启 IPv4 转发
if [[ -f /proc/sys/net/ipv4/ip_forward ]]; then
  cur_forward="$(cat /proc/sys/net/ipv4/ip_forward)"
  if [[ "$cur_forward" != "1" ]]; then
    echo "[INFO] Enabling net.ipv4.ip_forward=1"
    sysctl -w net.ipv4.ip_forward=1 >/dev/null
  fi
fi

# 通用规则片段
PREROUTING_TCP=( -t nat -p tcp --dport "${start_port}:${end_port}" -j DNAT --to-destination "${target_ip}:${start_port}-${end_port}" )
PREROUTING_UDP=( -t nat -p udp --dport "${start_port}:${end_port}" -j DNAT --to-destination "${target_ip}:${start_port}-${end_port}" )

FORWARD_TCP=( -p tcp -d "${target_ip}" --dport "${start_port}:${end_port}" -j ACCEPT )
FORWARD_UDP=( -p udp -d "${target_ip}" --dport "${start_port}:${end_port}" -j ACCEPT )

POSTROUTING_TCP=( -t nat -p tcp -d "${target_ip}" --dport "${start_port}:${end_port}" -j MASQUERADE )
POSTROUTING_UDP=( -t nat -p udp -d "${target_ip}" --dport "${start_port}:${end_port}" -j MASQUERADE )

if [[ "$action" == "add" ]]; then
  echo "[INFO] Public IP: $public_ip"
  echo "[INFO] Adding port forwarding: ${public_ip}:${start_port}-${end_port} -> ${target_ip}:${start_port}-${end_port} (TCP+UDP)"

  iptables -A FORWARD "${FORWARD_TCP[@]}"
  iptables -A FORWARD "${FORWARD_UDP[@]}"

  iptables -t nat -A PREROUTING "${PREROUTING_TCP[@]}"
  iptables -t nat -A PREROUTING "${PREROUTING_UDP[@]}"

  iptables -t nat -A POSTROUTING "${POSTROUTING_TCP[@]}"
  iptables -t nat -A POSTROUTING "${POSTROUTING_UDP[@]}"

  echo "[INFO] Rules added. You can check with: iptables -t nat -L -n -v"
else
  echo "[INFO] Public IP: $public_ip"
  echo "[INFO] Deleting port forwarding: ${public_ip}:${start_port}-${end_port} -> ${target_ip}:${start_port}-${end_port} (TCP+UDP)"

  # 删除时顺序与添加时无关，但规则要完全匹配
  iptables -t nat -D PREROUTING "${PREROUTING_TCP[@]}" || true
  iptables -t nat -D PREROUTING "${PREROUTING_UDP[@]}" || true

  iptables -D FORWARD "${FORWARD_TCP[@]}" || true
  iptables -D FORWARD "${FORWARD_UDP[@]}" || true

  iptables -t nat -D POSTROUTING "${POSTROUTING_TCP[@]}" || true
  iptables -t nat -D POSTROUTING "${POSTROUTING_UDP[@]}" || true

  echo "[INFO] Rules deleted (if they existed)."
fi