feat(e2e): add multi-IP endpoint architecture with dedicated traffic VM
Replace single-service-per-endpoint with all-ips mode running nginx, apache, and hitch+varnish simultaneously on 3 dedicated IPs per VM (eth1 alias IPs). Add a dedicated traffic VM with curl-impersonate for realistic TLS fingerprints, parallelized traffic generation, and paired SNI_HOSTS/TARGET_IPS lists for per-VM per-service hostname identification (e.g. rocky9-nginx-platform.test). Key changes: - run-tests-vm.sh: add setup_all_ips(), IP-specific Listen/bind directives with reset-before-apply pattern, graceful service availability checks - run-e2e-test.sh: traffic VM architecture, all-ips mode, eth1 network, paired IP/SNI lists, updated cleanup for alias IPs - generate-traffic.sh: parallel background jobs, curl-impersonate detection, auto source interface detection via ip route get, Host header in HTTP traffic - Vagrantfile: add traffic VM with provision-traffic.sh - provision-traffic.sh: install curl-impersonate and httpx for traffic gen - test-rpm.sh: multi-interface TC check, updated ja4ebpf config - clickhouse-init.sh: load CSV stubs for Anubis/bot-networks dictionaries - Remove obsolete correlator/sentinel/mod-reqin-log docs - Add h2_settings_ack column to http_logs schema - Upgrade Go toolchain to 1.25.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
# Architecture :
|
||||
# 3 VMs endpoint (centos8 / rocky9 / rocky10) : nginx + ja4ebpf
|
||||
# 1 VM analysis (192.168.42.10) : ClickHouse + bot-detector + dashboard
|
||||
# Host : orchestrateur + génération de trafic
|
||||
# 1 VM traffic : curl-impersonate + httpx (génération de trafic externe)
|
||||
#
|
||||
# Pipeline testé :
|
||||
# trafic host → endpoints → ja4ebpf → ClickHouse central →
|
||||
@ -32,8 +32,9 @@ VM_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$VM_DIR/../.." && pwd)"
|
||||
ANALYSIS_IP="192.168.42.10"
|
||||
ENDPOINT_VMS="centos8 rocky9 rocky10"
|
||||
ALL_VMS="centos8 rocky9 rocky10 analysis"
|
||||
STACK="nginx"
|
||||
TRAFFIC_VM="traffic"
|
||||
ALL_VMS="centos8 rocky9 rocky10 analysis traffic"
|
||||
STACK="all-ips"
|
||||
|
||||
# ── Paramètres par défaut (surchARGEABLES par CLI ou env) ──
|
||||
TRAFFIC_COUNT="${TRAFFIC_COUNT:-500}"
|
||||
@ -242,7 +243,7 @@ phase1_analysis() {
|
||||
phase2_endpoints() {
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════╗"
|
||||
echo "║ Phase 2 : Endpoints (nginx + ja4ebpf → analysis CH) ║"
|
||||
echo "║ Phase 2 : Endpoints (nginx+apache+hitch + ja4ebpf) ║"
|
||||
echo "╚══════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
@ -251,38 +252,74 @@ phase2_endpoints() {
|
||||
# Arrêter les services existants sur les endpoints (session précédente)
|
||||
log "Arrêt des services existants sur les endpoints..."
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
vagrant ssh "$vm" -- "sudo nginx -s stop 2>/dev/null; sudo pkill ja4ebpf 2>/dev/null; sudo pkill httpd 2>/dev/null; sudo pkill hitch 2>/dev/null; sudo pkill varnishd 2>/dev/null" 2>/dev/null || true
|
||||
vagrant ssh "$vm" -- "sudo nginx -s stop 2>/dev/null; sudo pkill ja4ebpf 2>/dev/null; sudo pkill httpd 2>/dev/null; sudo pkill hitch 2>/dev/null; sudo pkill varnishd 2>/dev/null; sudo pkill -f 'TCPServer.*8080' 2>/dev/null; sudo pkill -f 'TCPServer.*:80' 2>/dev/null" 2>/dev/null || true
|
||||
done
|
||||
sleep 2
|
||||
|
||||
# Démarrer chaque endpoint en arrière-plan
|
||||
# ja4ebpf pointe vers le ClickHouse de la VM analysis (CH_HOST=192.168.42.10)
|
||||
PIDS=()
|
||||
ENDPOINT_PIDS=()
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
log "Démarrage $vm (nginx + ja4ebpf → ${ANALYSIS_IP})..."
|
||||
vagrant ssh "$vm" -- "sudo rm -f /tmp/ja4ebpf-traffic-done" 2>/dev/null || true
|
||||
vagrant ssh "$vm" -- "sudo CH_HOST=${ANALYSIS_IP} bash /ja4-platform/tests/vm/run-tests-vm.sh ${STACK} start" &
|
||||
PIDS+=($!)
|
||||
ENDPOINT_PIDS+=($!)
|
||||
done
|
||||
|
||||
# Attendre que les services soient prêts
|
||||
log "Attente démarrage des endpoints (30s)..."
|
||||
sleep 30
|
||||
log "Attente démarrage des endpoints (45s)..."
|
||||
sleep 45
|
||||
|
||||
# Vérifier la connectivité HTTP de chaque endpoint
|
||||
# Vérifier la connectivité de chaque endpoint (3 IPs × 2 ports)
|
||||
# Les services sont sur le réseau ja4-e2e (eth1, 192.168.42.0/24)
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
local vm_ip
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
local vm_ip1
|
||||
vm_ip1=$(vagrant ssh "$vm" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
if curl -sf "http://${vm_ip}/health" >/dev/null 2>&1; then
|
||||
pass "$vm HTTP OK (${vm_ip}:80)"
|
||||
else
|
||||
warn "$vm HTTP injoignable (${vm_ip}:80)"
|
||||
# Fallback eth0 si eth1 n'existe pas
|
||||
if [ -z "$vm_ip1" ]; then
|
||||
vm_ip1=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
fi
|
||||
if curl -sf -k "https://${vm_ip}/health" >/dev/null 2>&1; then
|
||||
pass "$vm HTTPS OK (${vm_ip}:443)"
|
||||
local np bl vm_ip2 vm_ip3
|
||||
np=$(echo "$vm_ip1" | awk -F. '{print $1"."$2"."$3}')
|
||||
bl=$(echo "$vm_ip1" | awk -F. '{print $4}')
|
||||
# Même logique que setup_all_ips : base+50 et base+51
|
||||
vm_ip2="${np}.$((bl + 50))"
|
||||
vm_ip3="${np}.$((bl + 51))"
|
||||
|
||||
# nginx (IP1)
|
||||
if curl -sf --connect-timeout 3 "http://${vm_ip1}/health" >/dev/null 2>&1; then
|
||||
pass "$vm nginx:80 OK (${vm_ip1})"
|
||||
else
|
||||
warn "$vm HTTPS injoignable (${vm_ip}:443)"
|
||||
warn "$vm nginx:80 injoignable (${vm_ip1})"
|
||||
fi
|
||||
if curl -sf -k --connect-timeout 3 "https://${vm_ip1}/health" >/dev/null 2>&1; then
|
||||
pass "$vm nginx:443 OK (${vm_ip1})"
|
||||
else
|
||||
warn "$vm nginx:443 injoignable (${vm_ip1})"
|
||||
fi
|
||||
# apache (IP2)
|
||||
if curl -sf --connect-timeout 3 "http://${vm_ip2}/health" >/dev/null 2>&1; then
|
||||
pass "$vm apache:80 OK (${vm_ip2})"
|
||||
else
|
||||
warn "$vm apache:80 injoignable (${vm_ip2})"
|
||||
fi
|
||||
if curl -sf -k --connect-timeout 3 "https://${vm_ip2}/health" >/dev/null 2>&1; then
|
||||
pass "$vm apache:443 OK (${vm_ip2})"
|
||||
else
|
||||
warn "$vm apache:443 injoignable (${vm_ip2})"
|
||||
fi
|
||||
# hitch+varnish (IP3)
|
||||
if curl -sf --connect-timeout 3 "http://${vm_ip3}/health" >/dev/null 2>&1; then
|
||||
pass "$vm hitch:80 OK (${vm_ip3})"
|
||||
else
|
||||
warn "$vm hitch:80 injoignable (${vm_ip3})"
|
||||
fi
|
||||
if curl -sf -k --connect-timeout 3 "https://${vm_ip3}/health" >/dev/null 2>&1; then
|
||||
pass "$vm hitch:443 OK (${vm_ip3})"
|
||||
else
|
||||
warn "$vm hitch:443 injoignable (${vm_ip3})"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@ -299,60 +336,97 @@ phase3_traffic() {
|
||||
|
||||
local total_ok=0
|
||||
|
||||
# Hostnames pour SNI (cert CN=platform.test, nginx accepte tout via server_name _)
|
||||
local SNI_HOSTS_ALL=("platform.test" "api.platform.test" "www.platform.test" "app.platform.test")
|
||||
local SNI_HOSTS=("${SNI_HOSTS_ALL[@]:0:${DNS_COUNT}}")
|
||||
# Domaines pour SNI (cert CN=platform.test, nginx accepte tout via server_name _)
|
||||
local DOMAIN_SUFFIXES_ALL=("platform.test" "api.platform.test" "www.platform.test" "app.platform.test")
|
||||
local DOMAIN_SUFFIXES=("${DOMAIN_SUFFIXES_ALL[@]:0:${DNS_COUNT}}")
|
||||
|
||||
# ── Collecter les IPs de tous les endpoints ──
|
||||
# ── Collecter les IPs de tous les endpoints (3 IPs par VM sur réseau ja4-e2e/eth1) ──
|
||||
local -A VM_IPS_MAP
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
VM_IPS_MAP[$vm]=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
local base_ip
|
||||
base_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
# Fallback eth0
|
||||
if [ -z "$base_ip" ]; then
|
||||
base_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
fi
|
||||
VM_IPS_MAP[$vm]="$base_ip"
|
||||
# Calculer IP2 et IP3 (identique à setup_all_ips : base+50 et base+51)
|
||||
local np bl
|
||||
np=$(echo "$base_ip" | awk -F. '{print $1"."$2"."$3}')
|
||||
bl=$(echo "$base_ip" | awk -F. '{print $4}')
|
||||
VM_IPS_MAP["${vm}_ip2"]="${np}.$((bl + 50))"
|
||||
VM_IPS_MAP["${vm}_ip3"]="${np}.$((bl + 51))"
|
||||
done
|
||||
|
||||
# ── Ajouter des IPs alias sur chaque VM pour diversifier les sources ──
|
||||
if [ "$SRC_IP_COUNT" -gt 1 ]; then
|
||||
log "Ajout de ${SRC_IP_COUNT} IPs sources sur chaque VM..."
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
local base_ip="${VM_IPS_MAP[$vm]}"
|
||||
local net_prefix
|
||||
net_prefix=$(echo "$base_ip" | awk -F. '{print $1"."$2"."$3}')
|
||||
local base_last
|
||||
base_last=$(echo "$base_ip" | awk -F. '{print $4}')
|
||||
for i in $(seq 1 $((SRC_IP_COUNT - 1))); do
|
||||
local alias_last=$((base_last + 100 + i))
|
||||
[ "$alias_last" -gt 254 ] && alias_last=$((10 + i))
|
||||
local alias_ip="${net_prefix}.${alias_last}"
|
||||
vagrant ssh "$vm" -- "sudo ip addr add ${alias_ip}/24 dev eth0 2>/dev/null || true" 2>/dev/null || true
|
||||
done
|
||||
# ── Ajouter des IPs alias sur la VM traffic pour diversifier les sources ──
|
||||
# Utiliser eth1 (réseau ja4-e2e, 192.168.42.x) car les cibles sont sur ce réseau.
|
||||
local TRAFFIC_IP
|
||||
TRAFFIC_IP=$(vagrant ssh "$TRAFFIC_VM" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
# Fallback eth0 si eth1 n'existe pas
|
||||
if [ -z "$TRAFFIC_IP" ]; then
|
||||
TRAFFIC_IP=$(vagrant ssh "$TRAFFIC_VM" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
fi
|
||||
local TRAFFIC_IFACE
|
||||
if [ -n "$TRAFFIC_IP" ]; then
|
||||
case "$TRAFFIC_IP" in
|
||||
192.168.42.*) TRAFFIC_IFACE="eth1" ;;
|
||||
*) TRAFFIC_IFACE="eth0" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$SRC_IP_COUNT" -gt 1 ] && [ -n "$TRAFFIC_IP" ]; then
|
||||
log "Ajout de ${SRC_IP_COUNT} IPs sources sur ${TRAFFIC_VM} (${TRAFFIC_IFACE})..."
|
||||
local net_prefix
|
||||
net_prefix=$(echo "$TRAFFIC_IP" | awk -F. '{print $1"."$2"."$3}')
|
||||
local base_last
|
||||
base_last=$(echo "$TRAFFIC_IP" | awk -F. '{print $4}')
|
||||
for i in $(seq 1 $((SRC_IP_COUNT - 1))); do
|
||||
local alias_last=$((base_last + 100 + i))
|
||||
[ "$alias_last" -gt 254 ] && alias_last=$((10 + i))
|
||||
local alias_ip="${net_prefix}.${alias_last}"
|
||||
vagrant ssh "$TRAFFIC_VM" -- "sudo ip addr add ${alias_ip}/24 dev ${TRAFFIC_IFACE} 2>/dev/null || true" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
|
||||
# ── Construire les listes d'IPs cibles et SNI ──
|
||||
# ── Construire les listes d'IPs cibles et SNI appariées ──
|
||||
# Chaque entrée (VM, service, domaine) a un SNI unique : <vm>-<service>-<domaine>
|
||||
# TARGET_IPS et SNI_HOSTS sont des listes parallèles de même longueur.
|
||||
local TARGET_IPS=""
|
||||
local SNI_HOSTS_STR=""
|
||||
# Noms de services par clé IP
|
||||
local SVC_NAMES_ip1="nginx" SVC_NAMES_ip2="apache" SVC_NAMES_ip3="hitch"
|
||||
for target_vm in $ENDPOINT_VMS; do
|
||||
TARGET_IPS="$TARGET_IPS ${VM_IPS_MAP[$target_vm]}"
|
||||
local vm_base="${VM_IPS_MAP[$target_vm]}"
|
||||
local vm_ip2="${VM_IPS_MAP[${target_vm}_ip2]}"
|
||||
local vm_ip3="${VM_IPS_MAP[${target_vm}_ip3]}"
|
||||
for ip_key in ip1 ip2 ip3; do
|
||||
local svc_name_var="SVC_NAMES_${ip_key}"
|
||||
local svc_name="${!svc_name_var}"
|
||||
local map_key="${target_vm}_${ip_key}"
|
||||
local target_ip="${VM_IPS_MAP[$map_key]:-$vm_base}"
|
||||
for domain in "${DOMAIN_SUFFIXES[@]}"; do
|
||||
local sni="${target_vm}-${svc_name}-${domain}"
|
||||
TARGET_IPS="$TARGET_IPS $target_ip"
|
||||
SNI_HOSTS_STR="$SNI_HOSTS_STR $sni"
|
||||
done
|
||||
done
|
||||
done
|
||||
TARGET_IPS=$(echo $TARGET_IPS)
|
||||
|
||||
local SNI_HOSTS_STR=""
|
||||
for h in "${SNI_HOSTS[@]}"; do
|
||||
SNI_HOSTS_STR="$SNI_HOSTS_STR $h"
|
||||
done
|
||||
SNI_HOSTS_STR=$(echo $SNI_HOSTS_STR)
|
||||
log "Cibles : $(echo "$TARGET_IPS" | wc -w) paires IP/SNI ($(echo "$SNI_HOSTS_STR" | tr ' ' '\n' | sort -u | wc -l) uniques)"
|
||||
|
||||
# ── Synchroniser generate-traffic.sh vers les VMs ──
|
||||
log "Synchronisation du script de trafic..."
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
vagrant rsync "$vm" 2>&1 | tail -1
|
||||
done
|
||||
# ── Synchroniser generate-traffic.sh vers la VM traffic ──
|
||||
log "Synchronisation du script de trafic vers ${TRAFFIC_VM}..."
|
||||
vagrant rsync "$TRAFFIC_VM" 2>&1 | tail -1
|
||||
|
||||
# ── Écrire le config et lancer le trafic depuis chaque VM ──
|
||||
for src_vm in $ENDPOINT_VMS; do
|
||||
log "Génération depuis $src_vm : ${HTTPS_COUNT} HTTPS + ${HTTP_COUNT} HTTP (${SRC_IP_COUNT} IPs src)..."
|
||||
# ── Écrire le config et lancer le trafic depuis la VM traffic ──
|
||||
log "Génération depuis ${TRAFFIC_VM} : ${HTTPS_COUNT} HTTPS + ${HTTP_COUNT} HTTP..."
|
||||
|
||||
# Écrire le fichier de config sur la VM (heredoc quoté — pas d'expansion SSH)
|
||||
vagrant ssh "$src_vm" -- "cat > /tmp/e2e-traffic.env << 'ENVEOF'
|
||||
vagrant ssh "$TRAFFIC_VM" -- "cat > /tmp/e2e-traffic.env << 'ENVEOF'
|
||||
export HITS=${HTTPS_COUNT}
|
||||
export HITS_HTTP=${HTTP_COUNT}
|
||||
export TARGET_IPS='${TARGET_IPS}'
|
||||
@ -361,50 +435,46 @@ export TLS_FLAGS='${CURL_TLS_FLAGS}'
|
||||
export SRC_IP_COUNT=${SRC_IP_COUNT}
|
||||
ENVEOF"
|
||||
|
||||
# Lancer le générateur de trafic en arrière-plan
|
||||
vagrant ssh "$src_vm" -- \
|
||||
"source /tmp/e2e-traffic.env && bash /ja4-platform/tests/vm/generate-traffic.sh" \
|
||||
> /tmp/e2e-traffic-${src_vm}.out 2>&1 &
|
||||
# Lancer le générateur de trafic (curl-impersonate + curl)
|
||||
vagrant ssh "$TRAFFIC_VM" -- \
|
||||
"source /tmp/e2e-traffic.env && bash /ja4-platform/tests/vm/generate-traffic.sh" \
|
||||
> /tmp/e2e-traffic.out 2>&1 &
|
||||
|
||||
# Attendre que le processus se termine (max 300s)
|
||||
for i in $(seq 1 300); do
|
||||
if [ -f /tmp/e2e-traffic.out ] && ! pgrep -f "vagrant ssh $TRAFFIC_VM.*generate-traffic" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
local result
|
||||
result=$(tail -1 /tmp/e2e-traffic.out 2>/dev/null || echo "0/${HTTPS_COUNT} 0/${HTTP_COUNT}")
|
||||
|
||||
# ── Collecter les résultats HTTPS + HTTP ──
|
||||
for src_vm in $ENDPOINT_VMS; do
|
||||
# Attendre que le processus se termine (max 300s)
|
||||
for i in $(seq 1 300); do
|
||||
if [ -f /tmp/e2e-traffic-${src_vm}.out ] && ! pgrep -f "vagrant ssh $src_vm.*generate-traffic" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
local result
|
||||
result=$(tail -1 /tmp/e2e-traffic-${src_vm}.out 2>/dev/null || echo "0/${HTTPS_COUNT} 0/${HTTP_COUNT}")
|
||||
rm -f /tmp/e2e-traffic-${src_vm}.out 2>/dev/null
|
||||
# Format: "ok_https/hits_https ok_http/hits_http"
|
||||
local https_result http_result
|
||||
https_result=$(echo "$result" | awk '{print $1}')
|
||||
http_result=$(echo "$result" | awk '{print $2}')
|
||||
local ok_https ok_http
|
||||
ok_https=$(echo "$https_result" | cut -d/ -f1)
|
||||
ok_http=$(echo "${http_result:-0/0}" | cut -d/ -f1)
|
||||
|
||||
# Format: "ok_https/hits_https ok_http/hits_http"
|
||||
local https_result http_result
|
||||
https_result=$(echo "$result" | awk '{print $1}')
|
||||
http_result=$(echo "$result" | awk '{print $2}')
|
||||
local ok_https ok_http
|
||||
ok_https=$(echo "$https_result" | cut -d/ -f1)
|
||||
ok_http=$(echo "${http_result:-0/0}" | cut -d/ -f1)
|
||||
log " ${TRAFFIC_VM} HTTPS : ${https_result} HTTP : ${http_result:-0/0}"
|
||||
total_ok=$((total_ok + ok_https + ok_http))
|
||||
|
||||
log " $src_vm HTTPS : ${https_result} HTTP : ${http_result:-0/0}"
|
||||
total_ok=$((total_ok + ok_https + ok_http))
|
||||
done
|
||||
# ── HTTP/2 massif depuis la VM traffic si httpx est disponible ──
|
||||
if vagrant ssh "$TRAFFIC_VM" -- 'python3 -c "import httpx"' 2>/dev/null; then
|
||||
log "Génération HTTP/2 depuis ${TRAFFIC_VM} (${HTTPS_COUNT} requêtes, TLS=${TLS_VERSIONS}, DNS=${DNS_COUNT})..."
|
||||
|
||||
# ── HTTP/2 massif depuis les VMs si httpx est disponible ──
|
||||
for src_vm in $ENDPOINT_VMS; do
|
||||
if vagrant ssh "$src_vm" -- 'python3 -c "import httpx"' 2>/dev/null; then
|
||||
local src_ip="${VM_IPS_MAP[$src_vm]}"
|
||||
log "Génération HTTP/2 depuis $src_vm (${HTTPS_COUNT} requêtes, TLS=${TLS_VERSIONS}, DNS=${DNS_COUNT})..."
|
||||
|
||||
# Écrire le script httpx sur la VM (évite les problèmes d'échappement)
|
||||
vagrant ssh "$src_vm" -- "cat > /tmp/e2e-h2-traffic.py << 'PYEOF'
|
||||
# Écrire le script httpx sur la VM traffic
|
||||
vagrant ssh "$TRAFFIC_VM" -- "cat > /tmp/e2e-h2-traffic.py << 'PYEOF'
|
||||
import httpx, ssl as _ssl, warnings, random, os
|
||||
warnings.filterwarnings('ignore')
|
||||
paths = ['/', '/health', '/data', '/api/users', '/api/v1/status', '/login', '/api/search']
|
||||
sni_hosts = os.environ.get('SNI_HOSTS', 'platform.test').split()
|
||||
target_ips = os.environ.get('TARGET_IPS', '127.0.0.1').split()
|
||||
# Les listes sont appariées : même index = même cible (vm-service-domaine)
|
||||
assert len(sni_hosts) == len(target_ips), f'SNI_HOSTS ({len(sni_hosts)}) != TARGET_IPS ({len(target_ips)})'
|
||||
targets = list(zip(target_ips, sni_hosts))
|
||||
tls_versions = [v.strip() for v in os.environ.get('TLS_VERSIONS', '1.2,1.3').split(',')]
|
||||
uas_browser = [
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/131.0.0.0 Safari/537.36',
|
||||
@ -424,21 +494,21 @@ hits = int(os.environ.get('HITS', '100'))
|
||||
with httpx.Client(http2=True, verify=ctx) as c:
|
||||
for i in range(hits):
|
||||
p = random.choice(paths)
|
||||
target = random.choice(target_ips)
|
||||
h = random.choice(sni_hosts)
|
||||
target_ip, sni = random.choice(targets)
|
||||
ua = random.choice(uas_browser if random.random() < 0.7 else uas_bot)
|
||||
try:
|
||||
c.get(f'https://{target}' + p, headers={'User-Agent': ua, 'Host': h})
|
||||
c.get(f'https://{target_ip}' + p, headers={'User-Agent': ua, 'Host': sni})
|
||||
except:
|
||||
pass
|
||||
PYEOF"
|
||||
|
||||
vagrant ssh "$src_vm" -- \
|
||||
"source /tmp/e2e-traffic.env && TLS_VERSIONS='${TLS_VERSIONS}' python3 /tmp/e2e-h2-traffic.py" \
|
||||
2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
pass "HTTP/2 généré depuis tous les endpoints"
|
||||
vagrant ssh "$TRAFFIC_VM" -- \
|
||||
"source /tmp/e2e-traffic.env && TLS_VERSIONS='${TLS_VERSIONS}' python3 /tmp/e2e-h2-traffic.py" \
|
||||
2>/dev/null || true
|
||||
pass "HTTP/2 généré depuis ${TRAFFIC_VM}"
|
||||
else
|
||||
warn "httpx non disponible sur ${TRAFFIC_VM} — HTTP/2 ignoré"
|
||||
fi
|
||||
|
||||
pass "Trafic total : ${total_ok} requêtes réussies"
|
||||
}
|
||||
@ -489,7 +559,7 @@ phase4_wait() {
|
||||
|
||||
# Attendre les processus endpoint en arrière-plan
|
||||
log "Attente fin des processus endpoint..."
|
||||
for pid in "${PIDS[@]:-}"; do
|
||||
for pid in "${ENDPOINT_PIDS[@]:-}"; do
|
||||
wait "$pid" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
@ -627,21 +697,25 @@ phase_summary() {
|
||||
# Nettoyage
|
||||
# ═════════════════════════════════════════════════════════════════════════════
|
||||
cleanup() {
|
||||
# Supprimer les IPs alias sur les VMs
|
||||
# Supprimer les IPs alias sur la VM traffic (sur eth1, réseau ja4-e2e)
|
||||
if [ "${SRC_IP_COUNT:-1}" -gt 1 ]; then
|
||||
log "Suppression des IPs alias sur les VMs..."
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
vagrant ssh "$vm" -- "
|
||||
log "Suppression des IPs alias sur ${TRAFFIC_VM}..."
|
||||
vagrant ssh "$TRAFFIC_VM" -- "
|
||||
base_ip=\$(ip -4 addr show eth1 2>/dev/null | awk '/inet / {sub(/\/.*/, \"\", \\\$2); print \\\$2; exit}')
|
||||
if [ -z \"\$base_ip\" ]; then
|
||||
base_ip=\$(ip -4 addr show eth0 | awk '/inet / {sub(/\/.*/, \"\", \\\$2); print \\\$2; exit}')
|
||||
net_prefix=\$(echo \$base_ip | awk -F. '{print \\\$1\".\"\\\$2\".\"\\\$3}')
|
||||
base_last=\$(echo \$base_ip | awk -F. '{print \\\$4}')
|
||||
for i in \$(seq 1 $((SRC_IP_COUNT - 1))); do
|
||||
alias_last=\$((base_last + 100 + i))
|
||||
[ \$alias_last -gt 254 ] && alias_last=\$((10 + i))
|
||||
sudo ip addr del \${net_prefix}.\${alias_last}/24 dev eth0 2>/dev/null || true
|
||||
done
|
||||
" 2>/dev/null || true
|
||||
done
|
||||
iface=eth0
|
||||
else
|
||||
iface=eth1
|
||||
fi
|
||||
net_prefix=\$(echo \$base_ip | awk -F. '{print \\\$1\".\"\\\$2\".\"\\\$3}')
|
||||
base_last=\$(echo \$base_ip | awk -F. '{print \\\$4}')
|
||||
for i in \$(seq 1 $((SRC_IP_COUNT - 1))); do
|
||||
alias_last=\$((base_last + 100 + i))
|
||||
[ \$alias_last -gt 254 ] && alias_last=\$((10 + i))
|
||||
sudo ip addr del \${net_prefix}.\${alias_last}/24 dev \$iface 2>/dev/null || true
|
||||
done
|
||||
" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Toujours arrêter les endpoints (sauf --keep global)
|
||||
@ -649,7 +723,19 @@ cleanup() {
|
||||
log "Nettoyage des endpoints..."
|
||||
cd "$VM_DIR"
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
vagrant ssh "$vm" -- "sudo pkill ja4ebpf 2>/dev/null; sudo nginx -s stop 2>/dev/null; sudo pkill httpd 2>/dev/null" 2>/dev/null || true
|
||||
vagrant ssh "$vm" -- "sudo pkill ja4ebpf 2>/dev/null; sudo nginx -s stop 2>/dev/null; sudo pkill httpd 2>/dev/null; sudo pkill hitch 2>/dev/null; sudo pkill varnishd 2>/dev/null; sudo pkill -f 'TCPServer.*8080' 2>/dev/null; sudo pkill -f 'TCPServer.*:80' 2>/dev/null" 2>/dev/null || true
|
||||
# Supprimer les IPs alias (IP2, IP3) sur eth1
|
||||
local vm_base_ip
|
||||
vm_base_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
if [ -n "$vm_base_ip" ]; then
|
||||
local np bl ip2 ip3
|
||||
np=$(echo "$vm_base_ip" | awk -F. '{print $1"."$2"."$3}')
|
||||
bl=$(echo "$vm_base_ip" | awk -F. '{print $4}')
|
||||
ip2="${np}.$((bl + 50))"
|
||||
ip3="${np}.$((bl + 51))"
|
||||
vagrant ssh "$vm" -- "sudo ip addr del ${ip2}/24 dev eth1 2>/dev/null || true; sudo ip addr del ${ip3}/24 dev eth1 2>/dev/null || true" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
@ -668,9 +754,16 @@ cleanup() {
|
||||
log "VMs endpoints conservées :"
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
local vm_ip
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
log " $vm : ${vm_ip}"
|
||||
if [ -z "$vm_ip" ]; then
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
fi
|
||||
local np bl
|
||||
np=$(echo "$vm_ip" | awk -F. '{print $1"."$2"."$3}')
|
||||
bl=$(echo "$vm_ip" | awk -F. '{print $4}')
|
||||
log " $vm : ${vm_ip} (nginx) ${np}.$((bl + 50)) (apache) ${np}.$((bl + 51)) (hitch+varnish)"
|
||||
done
|
||||
fi
|
||||
}
|
||||
@ -698,10 +791,20 @@ if [ "$UP_ONLY" = "true" ]; then
|
||||
log "Bot-detector : http://${ANALYSIS_IP}:8080"
|
||||
for vm in $ENDPOINT_VMS; do
|
||||
local vm_ip
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth1' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
log "$vm HTTP : http://${vm_ip}:80"
|
||||
log "$vm HTTPS : https://${vm_ip}:443"
|
||||
if [ -z "$vm_ip" ]; then
|
||||
vm_ip=$(vagrant ssh "$vm" -- 'ip -4 addr show eth0' 2>/dev/null \
|
||||
| awk '/inet / {sub(/\/.*/, "", $2); print $2; exit}')
|
||||
fi
|
||||
local np bl vm_ip2 vm_ip3
|
||||
np=$(echo "$vm_ip" | awk -F. '{print $1"."$2"."$3}')
|
||||
bl=$(echo "$vm_ip" | awk -F. '{print $4}')
|
||||
vm_ip2="${np}.$((bl + 50))"
|
||||
vm_ip3="${np}.$((bl + 51))"
|
||||
log "$vm nginx : http://${vm_ip}:80 https://${vm_ip}:443"
|
||||
log "$vm apache : http://${vm_ip2}:80 https://${vm_ip2}:443"
|
||||
log "$vm hitch+varnish : http://${vm_ip3}:80 https://${vm_ip3}:443"
|
||||
done
|
||||
log ""
|
||||
log "Pour générer du trafic :"
|
||||
|
||||
Reference in New Issue
Block a user