
Sensore di rete Spip scritto in Go
Spip è un sensore honeypot di rete leggero e a bassa interazione. Ascolta il traffico TCP arbitrario in arrivo (plain e TLS), cattura ciò che scanner e bot inviano e registra ogni connessione come JSON strutturato (in formato ECS) per una facile ingestione nel tuo SIEM o data lake.
I sensori Spip alimentano HoneyLabs, una piattaforma gratuita e interrogabile di threat intelligence basata sui dati che catturano. Per vedere cosa Spip raccoglie in pratica, consulta i rapporti live per IP lì o il rapporto settimanale sulle minacce generato dalla rete di sensori.

Prerequisiti
iptablesgit clone https://github.com/honeylabshq/Spip-Go.git
cd Spip-Go
go build -o spip-agent ./cmd/spip-agent
sudo ./scripts/initial_setup.sh
Questo script scrive un file config.toml (chiede un name breve usato nei log), può generare chiavi TLS autofirmate, configura opzionalmente Loom (URL, sensor_id, token, ecc.) e applica opzionalmente il reindirizzamento PREROUTING iptables usato negli esempi seguenti.
config.toml
Minimale config.toml:name = "spip-agent"
ip = "127.0.0.1"
port = 8080
Chiavi di configurazione opzionali:
cert_path / key_path — abilita TLS se entrambi impostati; possono essere relativi al file di configurazione (lo script di configurazione scrive percorsi relativi in modo che la configurazione funzioni da qualsiasi directory di lavoro)log_file (locale) e/o [loom] (remoto). Vedi Output dei log più sotto.read_timeout_seconds / write_timeout_seconds — timeout di connessionerate_limit_per_second / rate_limit_burst — limitazione della velocità di connessionecommunity_id_seed — seed opzionale a 16 bit per l'hashing del flusso Community ID v1 (ometti o 0 per default)Se questi campi di regolazione runtime vengono omessi o impostati a 0, Spip applica i seguenti default:
read_timeout_seconds: 30write_timeout_seconds: 10rate_limit_per_second: 20rate_limit_burst: 50000sudo iptables -t nat -F
sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j RETURN
sudo iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-port 8080
./spip-agent -config config.toml
Spip scrive i log ECS in una singola destinazione locale e può opzionalmente inviare gli stessi log a un server Loom:
Quindi: locale di default su stdout; sovrascrivi con log_file per un file. Opzionalmente aggiungi Loom in aggiunta. Entrambi usano lo stesso formato ECS.
log_file commentato/vuoto (stdout) o impostalo a un percorso.[loom] con url, sensor_id, token (vedi Loom più sotto).Spip emette ogni connessione come un singolo oggetto JSON. L'output è formattato per essere compatibile con ECS utilizzando solo i campi che Spip può fornire (nessun arricchimento ASN/geo). I campi tipici prodotti includono:
@timestamp — timestamp RFC3339 per l'eventoevent.id — identificatore di sessione per connessioneobserver.hostname / host.name — nome dell'agente dalla configurazionesource.ip, source.port e destination.ip, destination.portnetwork.transport — es. tcphttp.request.body / url.path — quando il payload assomiglia chiaramente a HTTPuser_agent.original — quando disponibileevent.summary — payload grezzo per probe non HTTPEsempio di record (in formato ECS) prodotto da Spip:
{
"@timestamp": "2025-12-01T19:35:18.123Z",
"event": {
"id": "bd30cdc1-95b0-49aa-b8fe-e77230b6a04f",
"summary": "BitTorrent protocol",
"original_payload_hex": "426974546f7272656e742070726f746f636f6c",
"ingested_by": "spip"
},
"observer": {"hostname": "spip-agent"},
"host": {"name": "spip-agent"},
"source": {"ip": "146.70.1.1", "port": 35882},
"destination": {"ip": "146.190.1.1", "port": 6881},
"network": {"transport": "tcp"}
}
Nota: l'agente emette solo campi che può derivare dal payload e dai metadati della connessione. I sistemi downstream possono arricchire questi record (geo, ASN, ecc.) se desiderato.
Spip può aggiungere campi passivi di fingerprinting a ogni record di connessione (compatibile con ECS, nessuna modifica alla cattura del payload):
network.community_id) — hash di flusso v1 della 5-tupla (IP sorgente/destinazione e porta, protocollo). Quando il traffico viene reindirizzato tramite iptables, Spip utilizza la destinazione originale (prima di REDIRECT) in modo che l'hash corrisponda a quello che altri strumenti (es. Zeek, Suricata) calcolerebbero per lo stesso flusso.tls.client.server_name (SNI), tls.client.supported_protocols (lista ALPN), tls.client.hash.ja4 (impronta JA4).http.request.hash.ja4h (JA4H).SSH-2.0- e contiene un KEXINIT: ssh.client.hash.hassh (Hassh).Tutti questi sono aggiuntivi; il comportamento esistente (log locale, Loom, hex del payload, parsing HTTP) rimane invariato.
Riferimenti (per verifica e attribuzione):
Community ID: specifica Corelight Community ID.
JA4 / JA4H: FoxIO JA4.
Hassh: Salesforce HASSH.
TLS fingerprinting utilizza github.com/psanford/tlsfingerprint (MIT).
Parte di output dei log: quando [loom] ha enabled = true, gli stessi record ECS vengono anche raggruppati e inviati tramite POST al tuo URL di ingest Loom. Richiesti quando abilitato: url, sensor_id, token. Opzionali: batch_size (default 50), flush_interval (es. "10s"), insecure_skip_verify (per certificati Loom autofirmati). L'esportatore viene eseguito in modo asincrono e non blocca il ciclo di cattura; i POST falliti vengono registrati su stderr e il batch viene scartato (fail-open).
.
├── cmd/ # Punto d'ingresso principale dell'applicazione
├── internal/ # Configurazione, logging, rete, TLS, fingerprinting, esportatori (es. Loom)
├── pkg/ # Helper socket Linux (SO_ORIGINAL_DST tramite syscall)
├── test/ # Helper per test end-to-end
└── scripts/ # Script di utilità (incluso `initial_setup.sh`)
Esegui i test unitari con:
go test ./...
Test end-to-end richiedono privilegi per manipolare iptables. Eseguili tramite lo script (dalla radice del repository):
sudo -E ./scripts/run_e2e_tests.sh
Lo script configura l'ambiente e iptables. In alternativa usa l'helper del contenitore: ./scripts/run_e2e_in_container.sh. E2E convalida il comportamento principale (cattura del payload, sorgente/destinazione, rilevamento TLS, raggruppamento Loom, fingerprinting).
Spip esegue il rilevamento best-effort delle richieste HTTP dal payload catturato. Quando il payload assomiglia chiaramente a una richiesta HTTP (riga di richiesta valida più intestazioni di base o ALPN), l'agente emette i campi http.*, url.path e user_agent.original. Quando non lo fa, Spip torna a memorizzare il payload in event.summary e preserva sempre l'hex del payload grezzo in event.original_payload_hex.
Poiché Spip riflette l'IP sorgente nelle sue risposte e accetta traffico TCP arbitrario in entrata, è destinato all'uso come sensore stile honeypot o collettore di bordo in ambienti controllati/monitorati, non su endpoint utente arbitrari.
Esegui lo script interattivo dalla radice del repository (richiede root quando si applicano le regole iptables):
sudo ./scripts/initial_setup.sh
Lo script chiede: un name breve (scritto in config.toml, usato nei log come observer.hostname / host.name), IP di ascolto e porta, generazione opzionale di certificato TLS autofirmato (i percorsi sono scritti relativi alla configurazione in modo che funzionino da qualsiasi directory), configurazione opzionale di Loom (URL, sensor_id, token, batch_size, flush_interval, verifica TLS), percorso del file di log e reindirizzamento PREROUTING iptables opzionale.
| Destinazione | Configurazione | Comportamento |
|---|
| Locale | log_file | Default: ometti o lascia vuoto → stdout. Imposta un percorso → quel file. Uno dei due, sempre attivo. |
| Loom | [loom] con enabled = true | Opzionale. Gli stessi eventi vengono raggruppati e inviati tramite POST al tuo URL di ingest Loom oltre al locale. |
event.original_payload_hex — hex del payload grezzo (sempre preservato)network.community_id, tls.client.*, http.request.hash.ja4h, ssh.client.hash.hassh quando applicabile.