#!/bin/bash
# ==========================================================
# IDEOLAB - Active IP connections analyzer (read-only)
# Usage:
#   ./ideolab_active_ips.sh              (all ports)
#   ./ideolab_active_ips.sh 443          (port 443 only)
#   ./ideolab_active_ips.sh 443 172.31.28.54   (filter dst ip)
# ==========================================================

set -euo pipefail

PORT="${1:-}"
DSTIP="${2:-}"

# Choose best tool available
if command -v ss >/dev/null 2>&1; then
  TOOL="ss"
elif command -v netstat >/dev/null 2>&1; then
  TOOL="netstat"
else
  echo "ERROR: need 'ss' (iproute2) or 'netstat' (net-tools)"
  exit 1
fi

echo "=== IDEOLAB ACTIVE IP ANALYZER ==="
echo "Tool : $TOOL"
[ -n "$PORT" ] && echo "Port : $PORT"
[ -n "$DSTIP" ] && echo "DstIP: $DSTIP"
echo

# ----------------------------------------------------------
# Collect connections into a normalized list:
# IP STATE
# ----------------------------------------------------------
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT

if [ "$TOOL" = "ss" ]; then
  # ss output: State Recv-Q Send-Q Local Address:Port Peer Address:Port
  # We extract: peer_ip and state
  if [ -n "$PORT" ]; then
    ss -H -tn "sport = :$PORT" 2>/dev/null || true
    ss -H -tn "dport = :$PORT" 2>/dev/null || true
  else
    ss -H -tn 2>/dev/null || true
  fi | awk '
    {
      state=$1;
      peer=$5;
      gsub("\\[|\\]","",peer);
      split(peer,a,":");
      ip=a[1];
      # skip empty/localhost if wanted (keep for now)
      if(ip!="") print ip, state;
    }
  ' > "$tmp"

else
  # netstat output: tcp 0 0 local:port peer:port state
  if [ -n "$PORT" ]; then
    netstat -tan 2>/dev/null | awk -v p=":$PORT" '
      $1 ~ /^tcp/ && ($4 ~ p || $5 ~ p) { print }
    ' || true
  else
    netstat -tan 2>/dev/null | awk '$1 ~ /^tcp/ { print }' || true
  fi | awk '
    {
      peer=$5; state=$6;
      gsub("\\[|\\]","",peer);
      split(peer,a,":");
      ip=a[1];
      if(ip!="") print ip, state;
    }
  ' > "$tmp"
fi

# Optional filter by destination IP (works only if we re-query with ss including local addr)
# For simplicity and safety, we filter only if DSTIP is set and tool is ss (can read local addr)
if [ -n "$DSTIP" ] && [ "$TOOL" = "ss" ]; then
  tmp2="$(mktemp)"
  trap 'rm -f "$tmp" "$tmp2"' EXIT

  if [ -n "$PORT" ]; then
    ss -H -tn "dport = :$PORT" 2>/dev/null || true
  else
    ss -H -tn 2>/dev/null || true
  fi | awk -v dst="$DSTIP" '
    {
      state=$1;
      local=$4;
      peer=$5;
      gsub("\\[|\\]","",local);
      gsub("\\[|\\]","",peer);

      # local addr
      split(local,la,":");
      lip=la[1];

      if(lip!=dst) next;

      split(peer,pa,":");
      pip=pa[1];
      if(pip!="") print pip, state;
    }
  ' > "$tmp2"
  mv "$tmp2" "$tmp"
fi

total=$(wc -l < "$tmp" | tr -d ' ')
echo "Total TCP connections seen: $total"
echo

# ----------------------------------------------------------
# 1) Top IPs by number of connections
# ----------------------------------------------------------
echo "=== TOP 30 IPs (by connections) ==="
awk '{print $1}' "$tmp" | sort | uniq -c | sort -nr | head -30 | awk '{printf "%6s  %s\n",$1,$2}'
echo

# ----------------------------------------------------------
# 2) Top states
# ----------------------------------------------------------
echo "=== STATES distribution ==="
awk '{print $2}' "$tmp" | sort | uniq -c | sort -nr | awk '{printf "%6s  %s\n",$1,$2}'
echo

# ----------------------------------------------------------
# 3) For each state, top 10 IPs (useful to spot SYN_RECV / ESTABLISHED abusers)
# ----------------------------------------------------------
echo "=== TOP IPs per state (top 10 each) ==="
states=$(awk '{print $2}' "$tmp" | sort | uniq)
for st in $states; do
  echo "-- $st --"
  awk -v s="$st" '$2==s {print $1}' "$tmp" | sort | uniq -c | sort -nr | head -10 | awk '{printf "%6s  %s\n",$1,$2}'
  echo
done

# ----------------------------------------------------------
# 4) Top /24 (rough grouping) - IPv4 only
# ----------------------------------------------------------
echo "=== TOP /24 networks (IPv4 only) ==="
awk '
  $1 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ {
    split($1,o,".");
    print o[1]"."o[2]"."o[3]".0/24"
  }
' "$tmp" | sort | uniq -c | sort -nr | head -20 | awk '{printf "%6s  %s\n",$1,$2}'
echo

# ----------------------------------------------------------
# 5) Optional CSV export
# ----------------------------------------------------------
OUT="active_ips_$(date +%Y%m%d_%H%M%S).csv"
echo "ip,state" > "$OUT"
awk '{print $1","$2}' "$tmp" >> "$OUT"
echo "CSV written: $OUT"
