#!/usr/bin/env bash
# capture-ja3.sh — JA3/JA4 Fingerprinting lab (ch.9)
# ---------------------------------------------------------------------------
# Enables JA3 + JA4 TLS fingerprinting in Suricata, captures for a window, ranks
# the fingerprints by frequency (with SNI), and emits a ready-to-use Suricata
# rule that alerts on the most common JA3. Run as root.
# Usage:  ./capture-ja3.sh [iface] [seconds]
# ---------------------------------------------------------------------------
set -uo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
print_header(){ echo -e "\n${GREEN}=== $1 ===${NC}"; }
die(){ echo -e "${RED}[x] $1${NC}"; exit 1; }
[[ ${EUID:-$(id -u)} -eq 0 ]] || die "Run as root."
export DEBIAN_FRONTEND=noninteractive
IFACE="${1:-$(ip route show default 2>/dev/null | grep -oP 'dev \K\S+' | head -n1)}"; IFACE="${IFACE:-eth0}"
SECS="${2:-30}"
YAML="/etc/suricata/suricata.yaml"
LOG="/var/log/suricata"; EVE="${LOG}/eve.json"

print_header "Ensuring Suricata + jq"
command -v suricata >/dev/null 2>&1 || { apt-get update -qq && apt-get install -y suricata; }
command -v jq >/dev/null 2>&1 || apt-get install -y jq

print_header "Enabling JA3 + JA4 fingerprinting"
sed -i 's/\(ja3-fingerprints:\).*/\1 yes/' "$YAML" 2>/dev/null || true
sed -i 's/\(ja4-fingerprints:\).*/\1 yes/' "$YAML" 2>/dev/null || true
echo -e "${YELLOW}If Suricata says JA3/JA4 are off, set them to 'yes' under app-layer.protocols.tls and make sure eve-log 'tls' logs ja3/ja4.${NC}"

print_header "Capturing on ${IFACE} for ${SECS}s — generate some TLS traffic now"
install -d "$LOG"
timeout "${SECS}s" suricata -i "$IFACE" -l "$LOG" >/dev/null 2>&1 || true
[ -s "$EVE" ] || die "no eve.json output — check the interface and that traffic flowed."

print_header "Top JA3 fingerprints (count · hash · SNI)"
jq -r 'select(.event_type=="tls") | (.tls.ja3.hash // .tls.ja3 // empty) as $h
       | select($h!=null and $h!="") | "\($h)\t\(.tls.sni // "-")"' "$EVE" \
  | sort | uniq -c | sort -rn | head -15 \
  | awk '{printf "  %4d  %s  %s\n",$1,$2,$3}'

print_header "Top JA4 fingerprints"
jq -r 'select(.tls.ja4) | .tls.ja4' "$EVE" 2>/dev/null | sort | uniq -c | sort -rn | head -10 \
  | awk '{printf "  %4d  %s\n",$1,$2}'

TOP="$(jq -r 'select(.tls.ja3.hash) | .tls.ja3.hash' "$EVE" 2>/dev/null | sort | uniq -c | sort -rn | awk 'NR==1{print $2}')"
if [[ -n "${TOP:-}" ]]; then
  print_header "Sample detection rule (alerts on the most common JA3)"
  echo "  alert tls any any -> any any (msg:\"LAB JA3 match\"; ja3.hash; content:\"${TOP}\"; sid:9000001; rev:1;)"
  echo "  # Put it in /var/lib/suricata/rules/local.rules, reload, and swap 'alert'->'drop' in inline IPS mode."
fi
echo -e "\n${GREEN}A JA3/JA4 is the shape of the client's TLS ClientHello — stable across IPs, great for spotting tooling and bots.${NC}"
