
Capteur réseau Spip écrit en Go
Spip est un capteur honeypot réseau léger et à faible interaction. Il écoute le trafic TCP entrant arbitraire (plain et TLS), capture ce que les scanners et robots envoient, et enregistre chaque connexion sous forme de JSON structuré (format ECS) pour une ingestion facile dans votre SIEM ou lac de données.
Les capteurs Spip alimentent HoneyLabs, une plateforme gratuite et interrogeable de renseignement sur les menaces construite à partir des données qu'ils capturent. Pour voir ce que Spip collecte en pratique, parcourez les rapports par IP en direct disponibles sur le site ou le rapport de menace hebdomadaire généré à partir du réseau de capteurs.

Prérequis
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
Cet assistant écrit un fichier config.toml (il demande un name court utilisé dans les journaux), peut générer des clés TLS auto-signées, configure optionnellement Loom (URL, sensor_id, token, etc.), et applique éventuellement la redirection PREROUTING iptables utilisée dans les exemples ci-dessous.
config.toml
config.toml minimal :name = "spip-agent"
ip = "127.0.0.1"
port = 8080
Clés de configuration optionnelles :
cert_path / key_path — active TLS si les deux sont définis ; peuvent être relatifs au fichier de configuration (le script d'installation écrit des chemins relatifs pour que la configuration fonctionne depuis n'importe quel répertoire de travail)log_file (local) et/ou [loom] (distant). Voir Sortie des journaux ci-dessous.read_timeout_seconds / write_timeout_seconds — délais d'attente de connexionrate_limit_per_second / rate_limit_burst — limitation du débit de connexioncommunity_id_seed — graine 16 bits optionnelle pour le hachage de flux Community ID v1 (omettre ou 0 pour la valeur par défaut)Si ces champs de réglage d'exécution sont omis ou mis à 0, Spip applique les valeurs par défaut suivantes :
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 écrit les journaux ECS vers une seule destination locale et peut optionnellement envoyer les mêmes journaux vers un serveur Loom :
Donc : par défaut, local est stdout ; remplacez par log_file pour un fichier. Ajoutez éventuellement Loom en complément. Les deux utilisent le même format ECS.
log_file commenté/vide (stdout) ou définissez un chemin.[loom] avec url, sensor_id, token (voir Loom ci-dessous).Spip émet chaque connexion sous la forme d'un objet JSON unique. La sortie est formatée pour être compatible ECS en utilisant uniquement les champs que Spip peut fournir (pas d'enrichissement ASN/géo). Les champs typiques produits incluent :
@timestamp — horodatage RFC3339 pour l'événementevent.id — identifiant de session par connexionobserver.hostname / host.name — name de l'agent depuis la configurationsource.ip, source.port et destination.ip, destination.portnetwork.transport — par ex. tcphttp.request.body / url.path — lorsque la charge utile ressemble clairement à HTTPuser_agent.original — lorsqu'il est disponibleExemple d'enregistrement (format ECS) produit par Spip :
{
"@timestamp": "2025-12-01T19:35:18.123Z",
"event": {
"id": "bd30cdc1-95b0-49aa-b8fe-e77230b6a04f",
"summary": "Procole BitTorrent",
"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"}
}
Remarque : l'agent n'émet que les champs qu'il peut déduire de la charge utile et des métadonnées de la connexion. Les systèmes en aval peuvent enrichir ces enregistrements (géo, ASN, etc.) si souhaité.
Spip peut ajouter des champs passifs d'empreintes digitales à chaque enregistrement de connexion (compatible ECS, sans modification de la capture de charge utile) :
network.community_id) — hachage de flux v1 du quintuplet (IP source/destination et port, protocole). Lorsque le trafic est redirigé via iptables, Spip utilise la destination d'origine (avant REDIRECT) pour que le hachage corresponde à ce que d'autres outils (par ex. Zeek, Suricata) calculeraient pour le même flux.tls.client.server_name (SNI), tls.client.supported_protocols (liste ALPN), tls.client.hash.ja4 (empreinte JA4).http.request.hash.ja4h (JA4H).SSH-2.0- et contient un KEXINIT : ssh.client.hash.hassh (Hassh).Tous ces champs sont additifs ; le comportement existant (journal local, Loom, hex de charge utile, analyse HTTP) reste inchangé.
Références (pour vérification et attribution) :
Community ID : Spécification Corelight Community ID.
JA4 / JA4H : FoxIO JA4.
Hassh : Salesforce HASSH.
L'empreinte TLS utilise github.com/psanford/tlsfingerprint (MIT).
Partie de la sortie des journaux : lorsque [loom] a enabled = true, les mêmes enregistrements ECS sont également regroupés et envoyés via POST à votre URL d'ingestion Loom. Obligatoire lorsque activé : url, sensor_id, token. Optionnel : batch_size (défaut 50), flush_interval (par ex. "10s"), insecure_skip_verify (pour les certificats Loom auto-signés). L'exportateur s'exécute de manière asynchrone et ne bloque pas la boucle de capture ; les POST échoués sont enregistrés sur stderr et le lot est abandonné (échec ouvert).
.
├── cmd/ # Point d'entrée principal de l'application
├── internal/ # Configuration, journalisation, réseau, TLS, empreintes digitales, exportateurs (ex. Loom)
├── pkg/ # Utilitaires de sockets Linux (SO_ORIGINAL_DST via syscall)
├── test/ # Aides aux tests de bout en bout
└── scripts/ # Scripts utilitaires (dont `initial_setup.sh`)
Exécutez les tests unitaires avec :
go test ./...
Les tests de bout en bout nécessitent des privilèges pour manipuler iptables. Exécutez-les via le script (depuis la racine du dépôt) :
sudo -E ./scripts/run_e2e_tests.sh
Le script configure l'environnement et iptables. Vous pouvez également utiliser l'aide conteneur : ./scripts/run_e2e_in_container.sh. Les tests E2E valident le comportement principal (capture de charge utile, source/destination, détection TLS, regroupement Loom, empreintes digitales).
Spip effectue une détection au mieux de la requête HTTP à partir de la charge utile capturée. Lorsque la charge utile ressemble clairement à une requête HTTP (ligne de requête valide plus en-têtes de base ou ALPN), l'agent émet les champs http.*, url.path et user_agent.original. Sinon, Spip se rabat sur le stockage de la charge utile dans event.summary et conserve toujours la charge utile brute en hexadécimal dans event.original_payload_hex.
Parce que Spip renvoie l'IP source dans ses réponses et accepte tout trafic TCP entrant arbitraire, il est destiné à être utilisé comme capteur de type honeypot ou collecteur périphérique dans des environnements contrôlés/surveillés, et non sur des terminaux utilisateurs arbitraires.
Exécutez l'assistant interactif depuis la racine du dépôt (nécessite root lors de l'application des règles iptables) :
sudo ./scripts/initial_setup.sh
Le script demande : un name court (écrit dans config.toml, utilisé dans les journaux comme observer.hostname / host.name), l'IP et le port d'écoute, la génération facultative de certificats TLS auto-signés (les chemins sont écrits relatifs à la configuration pour qu'ils fonctionnent depuis n'importe quel répertoire), la configuration optionnelle de Loom (URL, sensor_id, token, batch_size, flush_interval, vérification TLS), le chemin du fichier journal, et la redirection PREROUTING iptables optionnelle.
| Destination | Configuration | Comportement |
|---|
| Locale | log_file | Défaut : omettre ou laisser vide → stdout. Définir un chemin → ce fichier. Un des deux, toujours actif. |
| Loom | [loom] avec enabled = true | Facultatif. Les mêmes événements sont regroupés et envoyés via POST à votre URL d'ingestion Loom en plus du local. |
event.summary — charge utile brute pour les sondes non-HTTPevent.original_payload_hex — charge utile brute en hexadécimal (toujours conservée)network.community_id, tls.client.*, http.request.hash.ja4h, ssh.client.hash.hassh lorsque applicable.