#!/bin/bash # netdiag.sh — diagnostica (y prueba un fix) el camino DHCP del lab de red, todo como root en una corrida. # Corré: sudo bash scripts/netdiag.sh # Deja un reporte legible en work/netdiag.txt (chmod 644) y lo imprime. set -u cd "$(dirname "$0")/.." || exit 1 BR="${BR:-hmtap0}"; TAP="${TAP:-hmtap0}"; SUBNET="${SUBNET:-192.168.100}"; VMMAC="52:54:00:12:34:56" OUT=work/netdiag.txt DNSLOG=/tmp/hmdnsmasq.log mkdir -p work exec > >(tee "$OUT") 2>&1 [ "$(id -u)" = 0 ] || { echo "corré con: sudo bash scripts/netdiag.sh"; exit 1; } echo "===== netdiag =====" run_test() { KVM=1 MEM=4096 DEADLINE=45 LOG=work/netdiag-run.log python3 scripts/drive-netup.py >/dev/null 2>&1; } echo; echo "### 1. firewall del host (nft) ###" echo "-- base chains input + policies --" nft list ruleset 2>/dev/null | grep -iE 'table |chain |hook (input|forward|prerouting)|policy|type ' | head -40 INPUT_DROP=$(nft list ruleset 2>/dev/null | grep -iE 'hook input' | grep -ci 'policy drop') echo "input-hook chains con policy drop: $INPUT_DROP" echo; echo "### 2. captura DHCP en $TAP (egress del VM) + $BR mientras manda DISCOVER ###" command -v tcpdump >/dev/null || echo "(tcpdump ausente — salteo captura)" : > /tmp/netdiag.pcap.txt; : > /tmp/netdiag.br.txt echo "estado del tap/bridge ANTES (idle):"; ip -br link show "$TAP"; ip -br link show "$BR" if command -v tcpdump >/dev/null; then timeout 55 tcpdump -i "$TAP" -nnev 'udp port 67 or udp port 68' > /tmp/netdiag.pcap.txt 2>/dev/null & TPID=$! timeout 55 tcpdump -i "$BR" -nnev 'udp port 67 or udp port 68' > /tmp/netdiag.br.txt 2>/dev/null & TPID2=$!; sleep 1 fi run_test sleep 1; for pid in ${TPID:-} ${TPID2:-}; do kill "$pid" 2>/dev/null; wait "$pid" 2>/dev/null; done echo "-- DISCOVER/Offer en el TAP $TAP (lo que el VM realmente manda/recibe) --" grep -icE 'Discover|Offer|Request|Reply|BOOTP' /tmp/netdiag.pcap.txt; grep -iE 'Discover|Offer|cksum' /tmp/netdiag.pcap.txt | head -6 echo "-- paquetes DHCP capturados en $BR --" grep -icE 'Discover|Offer|Request|Reply|BOOTP' /tmp/netdiag.pcap.txt echo "-- muestra (Discover/Offer/checksum) --" grep -iE 'Discover|Offer|cksum' /tmp/netdiag.pcap.txt | head -10 echo "-- dnsmasq: ¿recibió/ofreció? --" grep -iE 'DHCPDISCOVER|DHCPOFFER|DHCPACK|no address' "$DNSLOG" 2>/dev/null | tail -8 || echo "(sin entradas DHCP)" echo; echo "### 3. veredicto del diagnóstico ###" SAW_DISC=$(grep -ic 'Discover' /tmp/netdiag.pcap.txt) BAD_CKSUM=$(grep -ic 'bad udp cksum' /tmp/netdiag.pcap.txt) DNS_SAW=$(grep -ic 'DHCPDISCOVER' "$DNSLOG" 2>/dev/null) echo "DISCOVER en bridge=$SAW_DISC bad-cksum=$BAD_CKSUM dnsmasq-vio-DISCOVER=$DNS_SAW input-drop=$INPUT_DROP" if [ "$SAW_DISC" = 0 ]; then echo ">> el DISCOVER NO llega al bridge (problema tap/QEMU)"; fi if [ "$SAW_DISC" != 0 ] && [ "$BAD_CKSUM" != 0 ]; then echo ">> DISCOVER llega con CHECKSUM MALO (offload) ⇒ dnsmasq lo descarta"; fi if [ "$SAW_DISC" != 0 ] && [ "$DNS_SAW" = 0 ] && [ "$BAD_CKSUM" = 0 ]; then echo ">> DISCOVER llega OK pero dnsmasq no lo procesa ⇒ firewall INPUT (drop=$INPUT_DROP)"; fi echo; echo "### 4. firewall INPUT: inspecciono, meto accepts CONTADOS y retesteo ###" echo "-- inet filter input ANTES (con handles) --" nft -a list chain inet filter input 2>/dev/null echo "-- inserto accepts contados (por iif del bridge y por puerto DHCP/DNS) --" nft insert rule inet filter input udp dport '{ 67, 68, 53 }' counter accept comment '"hmlab"' 2>&1 | head -2 nft insert rule inet filter input iifname "$BR" counter accept comment '"hmlab"' 2>&1 | head -2 run_test echo "-- reglas hmlab DESPUÉS del retest (los counters dicen cuál matcheó) --" nft -a list chain inet filter input 2>/dev/null | grep -i hmlab echo "-- dnsmasq tras retest --" grep -iE 'DHCPDISCOVER|DHCPOFFER|DHCPACK' "$DNSLOG" 2>/dev/null | tail -5 || echo "(nada)" echo "-- netup tras retest --" grep -aE 'netup: lease|netup: red configurada|sin respuesta DHCP|PING_OK|PING_FAIL|DNS_OK|DNS_FAIL' work/netdiag-run.log | tail -5 if grep -qa 'netup: red configurada' work/netdiag-run.log; then echo "RESULTADO: ✓ RED OK"; else echo "RESULTADO: ✗ sigue fallando"; fi echo; echo "### 5. dnsmasq log COMPLETO (volcado para análisis) ###" tail -30 "$DNSLOG" 2>/dev/null || echo "(no legible)" echo; echo "### 6. netup salida COMPLETA del retest ###" tr -d '\r' < work/netdiag-run.log 2>/dev/null | sed 's/\x1b\[[0-9;?]*[a-zA-Z]//g' | grep -aE 'netup:|e1000.*Link|PING_|DNS_' | tail -12 chmod 644 "$OUT" 2>/dev/null chmod 666 work/netdiag-run.log 2>/dev/null echo; echo "(reporte: $OUT)"