Convierte capturas .pcap/.pcapng en datos SQL consultables (DuckDB embebido). Captura tráfico en vivo y analízalo desde un único toolbox.
Requisitos: Python ≥ 3.12, tshark y git.
git clone <repo> traffic && cd traffic
python3 -m venv .venv
.venv/bin/pip install -e .Verifica:
.venv/bin/traffic --helpSi tshark no está en el host, la herramienta usa automáticamente la imagen Docker traffic-watcher/tshark como respaldo. Para construirla:
docker build -t traffic-watcher/tshark docker/tsharkRequisitos: Docker + docker compose.
git clone <repo> traffic && cd traffic
docker compose buildVerifica:
docker compose run --rm watcher --helpSi tu UID no es 1000, exporta antes:
export HOST_UID=$(id -u) HOST_GID=$(id -g)
El contenedor trae tshark, la CLI duckdb, ping, curl, iperf3 y tcpreplay.
traffic init # crea ./data/traffic.duckdb
traffic import captura.pcapng # importa una captura existente
traffic sql "SELECT * FROM connections LIMIT 5"
traffic capture -i eth0 -d 60 # captura 60s en vivo y la importadocker compose run --rm shell
# dentro:
traffic capture -i any -d 60 # 60s en todas las interfaces, auto-importa
traffic capture -i any -f "port 443" -d 30 # solo TCP/443
traffic capture -i any # hasta Ctrl-CDentro del contenedor el contenedor usa la interfaz
anypara ver todo el tráfico del host (incluido el de otros contenedores Docker). Las interfaces individuales (eth0,wlan0,docker0, ...) solo capturan lo que pasa por esa interfaz específica.
Flags de capture:
| Flag | Significado |
|---|---|
-i <iface> |
interfaz (obligatoria) |
-f "<BPF>" |
filtro de captura (ej. port 443, host 8.8.8.8) |
-d <segundos> |
parar tras N segundos |
-o <archivo> |
ruta de salida (auto si se omite: /data/capture_<iface>_<ts>.pcapng) |
--no-import |
guardar el pcap sin importarlo a la BD |
Sin argumentos muestra las interfaces disponibles y el uso.
tshark -i eth0 -a duration:60 -w captura.pcapng
mv captura.pcapng captures/
docker compose run --rm watcher import /captures/captura.pcapngO sin mover el archivo, directamente desde el host con el venv:
tshark -i eth0 -a duration:60 -w captura.pcapng
.venv/bin/traffic import captura.pcapngdocker run --rm --net=host \
-v "$PWD/captures:/data:ro" traffic-watcher/tshark \
-i eth0 -a duration:60 -w /data/captura.pcapng
docker compose run --rm watcher import /captures/captura.pcapngduckdb data/traffic.duckdbO desde el contenedor:
docker compose run --rm shell -c "duckdb /data/traffic.duckdb"Consultas iniciales útiles:
.tables
DESCRIBE captures;
DESCRIBE connections;
DESCRIBE dns;
DESCRIBE http;
DESCRIBE tls;
-- top conversadores
SELECT src_ip, dst_ip, COUNT(*) n
FROM connections GROUP BY src_ip, dst_ip ORDER BY n DESC LIMIT 10;
-- qué dominios resolvió cada IP
SELECT c.src_ip, d.query_name, COUNT(*) n
FROM dns d JOIN connections c ON c.id = d.connection_id
WHERE d.msg_type = 'query'
GROUP BY c.src_ip, d.query_name ORDER BY n DESC LIMIT 20;
-- a qué servicios TLS se conectó cada IP (SNI)
SELECT c.src_ip, t.sni, COUNT(*) n
FROM tls t JOIN connections c ON c.id = t.connection_id
WHERE t.sni IS NOT NULL
GROUP BY c.src_ip, t.sni ORDER BY n DESC LIMIT 20;Más queries canónicas en docs/ENGINEERING.md §9.
.traffic/
├── docker-compose.yaml # servicios watcher y shell
├── docker/
│ ├── tool/Dockerfile # imagen traffic-watcher/tool
│ └── tshark/Dockerfile # imagen traffic-watcher/tshark (respaldo)
├── src/traffic_watcher/ # paquete Python
│ ├── cli.py
│ ├── capture.py
│ ├── db.py
│ ├── ingest.py
│ └── schema.sql
├── scripts/generate_sample_pcap.py
├── captures/ # capturas traídas del host (bind mount, ro)
├── data/ # BD DuckDB + capturas generadas (bind mount, rw)
└── docs/DESIGN.md # arquitectura, modelo de datos y roadmap
Ver docs/DESIGN.md para arquitectura, modelo de datos y roadmap, y docs/ENGINEERING.md para el diario de ingeniería (bugs resueltos, decisiones, cómo retomar).
La imagen Docker congela el código al hacer pip install . (no editable), y la BD se conserva por volumen entre reinicios. Tras cualquier cambio hay que reconstruir la imagen y, si cambió el esquema SQL, vaciar la BD.
docker compose build watcher --no-cache
docker compose run --rm shelldocker compose build watcher --no-cache
rm -f data/traffic.duckdb
docker compose run --rm watcher bash -c "traffic init"El rm es obligatorio: DuckDB no aplica migraciones; una BD existente con el esquema viejo seguirá usando las columnas viejas y los INSERT fallarán.