sudo tee /usr/local/bin/nginx_connwatch.sh > /dev/null <<'BASH'
#!/usr/bin/env bash
set -euo pipefail

# ====== Réglages ======
PORT=443
INTERVAL=30                      # secondes entre checks
THRESH_TOTAL=3000                # alerte si total conns > ceci
THRESH_ESTAB=2000                # alerte si estab > ceci
THRESH_TOPIP=200                 # alerte si une IP > ceci
LOG="/var/log/nginx-connwatch.log"
STATE="/var/lib/nginx-connwatch"
MAIL_TO="${MAIL_TO:-}"           # export MAIL_TO="toi@domaine.tld" si tu veux des mails

mkdir -p "$(dirname "$LOG")" "$STATE"

ts() { date '+%F %T'; }

have_cmd() { command -v "$1" >/dev/null 2>&1; }

send_alert() {
  local subject="$1"
  local body="$2"

  echo "[$(ts)] ALERT: $subject" >> "$LOG"
  echo "$body" >> "$LOG"
  echo "-----" >> "$LOG"

  if [[ -n "$MAIL_TO" ]]; then
    if have_cmd mail; then
      echo "$body" | mail -s "$subject" "$MAIL_TO" || true
    elif have_cmd sendmail; then
      {
        echo "Subject: $subject"
        echo "To: $MAIL_TO"
        echo
        echo "$body"
      } | sendmail -t || true
    fi
  fi
}

cooldown_ok() {
  # évite le spam : 1 alerte max par type toutes les 10 min
  local key="$1"
  local now epoch_last
  now="$(date +%s)"
  if [[ -f "$STATE/$key" ]]; then
    epoch_last="$(cat "$STATE/$key" 2>/dev/null || echo 0)"
  else
    epoch_last=0
  fi
  if (( now - epoch_last >= 600 )); then
    echo "$now" > "$STATE/$key"
    return 0
  fi
  return 1
}

snapshot() {
  local total estab synrecv timewait
  total="$(ss -Hant "sport = :$PORT" | wc -l | tr -d ' ')"
  estab="$(ss -Hant state established "sport = :$PORT" | wc -l | tr -d ' ')"
  synrecv="$(ss -Hant state syn-recv "sport = :$PORT" | wc -l | tr -d ' ')"
  timewait="$(ss -Hant state time-wait "sport = :$PORT" | wc -l | tr -d ' ')"

  echo "[$(ts)] total=$total estab=$estab syn-recv=$synrecv time-wait=$timewait" >> "$LOG"

  # Top IPs (top 10)
  local top
  top="$(ss -Hant "sport = :$PORT" | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10 || true)"
  echo "[$(ts)] top_ips:" >> "$LOG"
  echo "$top" >> "$LOG"

  # Alertes seuils
  if (( total > THRESH_TOTAL )) && cooldown_ok "total"; then
    send_alert "[Nginx] Connexions 443 trop élevées: $total" \
"Connexions totales sur :$PORT = $total (seuil $THRESH_TOTAL)
ESTAB=$estab  SYN-RECV=$synrecv  TIME-WAIT=$timewait

Top IPs:
$top"
  fi

  if (( estab > THRESH_ESTAB )) && cooldown_ok "estab"; then
    send_alert "[Nginx] ESTABLISHED 443 trop élevées: $estab" \
"Connexions ESTABLISHED sur :$PORT = $estab (seuil $THRESH_ESTAB)

Top IPs:
$top"
  fi

  # IP > THRESH_TOPIP ?
  local worst_count worst_ip
  worst_count="$(echo "$top" | head -1 | awk '{print $1}' | tr -d ' ' || echo 0)"
  worst_ip="$(echo "$top" | head -1 | awk '{print $2}' || echo "")"
  if [[ -n "$worst_ip" ]] && (( worst_count > THRESH_TOPIP )) && cooldown_ok "topip"; then
    send_alert "[Nginx] Une IP garde trop de connexions: $worst_ip ($worst_count)" \
"IP suspecte: $worst_ip
Connexions: $worst_count (seuil $THRESH_TOPIP)

Top IPs:
$top"
  fi

  # Erreurs Nginx récentes (si logs accessibles)
  local errlog="/var/log/nginx/error.log"
  local acclog="/var/log/nginx/access.log"
  if [[ -r "$errlog" ]]; then
    local recent_err
    recent_err="$(tail -n 200 "$errlog" | egrep -i 'too many|worker_connections|upstream|timeout|reset|limiting|reject|429' || true)"
    if [[ -n "$recent_err" ]] && cooldown_ok "errlog"; then
      send_alert "[Nginx] Signaux error.log" \
"Extraits récents error.log (tail 200 filtré):
$recent_err"
    fi
  fi

  if [[ -r "$acclog" ]]; then
    # codes utiles
    local recent_499 recent_408 recent_429
    recent_499="$(tail -n 500 "$acclog" | awk '{print $9}' | grep -c '^499$' || true)"
    recent_408="$(tail -n 500 "$acclog" | awk '{print $9}' | grep -c '^408$' || true)"
    recent_429="$(tail -n 500 "$acclog" | awk '{print $9}' | grep -c '^429$' || true)"
    echo "[$(ts)] access_tail500: 499=$recent_499 408=$recent_408 429=$recent_429" >> "$LOG"
  fi

  echo "-----" >> "$LOG"
}

echo "[$(ts)] nginx_connwatch started (interval=${INTERVAL}s)" >> "$LOG"
while true; do
  snapshot
  sleep "$INTERVAL"
done
BASH

sudo chmod +x /usr/local/bin/nginx_connwatch.sh
sudo mkdir -p /var/lib/nginx-connwatch
