
Sensor de red Spip escrito en Go
Spip es un sensor de honeypot de red ligero y de baja interacción. Escucha tráfico TCP entrante arbitrario (simple y TLS), captura lo que los escáneres y bots envían, y registra cada conexión como JSON estructurado (con forma ECS) para facilitar su ingesta en tu SIEM o lago de datos.
Los sensores Spip alimentan HoneyLabs, una plataforma gratuita y consultable de inteligencia de amenazas construida sobre los datos que capturan. Para ver lo que Spip recopila en la práctica, consulta los informes en vivo por IP allí o el informe de amenazas semanal generado desde la red de sensores.

Requisitos previos
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
Este asistente escribe un config.toml (pide un name corto usado en los registros), puede generar claves TLS autofirmadas, opcionalmente configura Loom (URL, sensor_id, token, etc.), y opcionalmente aplica la redirección PREROUTING de iptables usada en los ejemplos siguientes.
config.toml
config.toml mínimo:name = "spip-agent"
ip = "127.0.0.1"
port = 8080
Claves de configuración opcionales:
cert_path / key_path — habilitar TLS si ambos están configurados; pueden ser relativos al archivo de configuración (el script de configuración escribe rutas relativas para que la configuración funcione desde cualquier directorio de trabajo)log_file (local) y/o [loom] (remoto). Ver Salida de registros más abajo.read_timeout_seconds / write_timeout_seconds — tiempos de espera de conexiónrate_limit_per_second / rate_limit_burst — limitación de tasa de conexióncommunity_id_seed — semilla opcional de 16 bits para el hash de flujo Community ID v1 (omitir o 0 para usar el valor predeterminado)Si estos campos de ajuste en tiempo de ejecución se omiten o se establecen en 0, Spip aplica los siguientes valores predeterminados:
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 escribe registros ECS en un único destino local y puede opcionalmente enviar los mismos registros a un servidor Loom:
Por lo tanto: local predetermina a stdout; se puede sobrescribir con log_file para un archivo. Opcionalmente, añadir Loom adicionalmente. Ambos usan el mismo formato ECS.
log_file comentado/vacío (stdout) o establecerlo en una ruta.[loom] con url, sensor_id, token (ver Loom más abajo).Spip emite cada conexión como un único objeto JSON. La salida está formateada para ser compatible con ECS utilizando solo los campos que Spip puede proporcionar (sin enriquecimiento ASN/geo). Los campos típicos producidos incluyen:
@timestamp — marca de tiempo RFC3339 para el eventoevent.id — identificador de sesión por conexiónobserver.hostname / host.name — name del agente desde la configuraciónsource.ip, source.port y destination.ip, destination.portnetwork.transport — ej. tcphttp.request.body / url.path — cuando la carga útil se asemeja claramente a HTTPuser_agent.original — cuando esté disponibleEjemplo de registro (con forma ECS) producido por 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: el agente solo emite campos que puede derivar de la carga útil y los metadatos de la conexión. Los sistemas posteriores pueden enriquecer estos registros (geo, ASN, etc.) si se desea.
Spip puede añadir campos de huella digital pasiva a cada registro de conexión (compatible con ECS, sin cambios en la captura de carga útil):
network.community_id) — hash de flujo v1 del 5-tuple (IP de origen/destino y puerto, protocolo). Cuando el tráfico se redirige mediante iptables, Spip utiliza el destino original (antes de REDIRECT) para que el hash coincida con lo que otras herramientas (ej. Zeek, Suricata) calcularían para el mismo flujo.tls.client.server_name (SNI), tls.client.supported_protocols (lista ALPN), tls.client.hash.ja4 (huella digital JA4).http.request.hash.ja4h (JA4H).SSH-2.0- y contiene un KEXINIT: ssh.client.hash.hassh (Hassh).Todos estos son aditivos; el comportamiento existente (registro local, Loom, hexadecimal de carga útil, análisis HTTP) no cambia.
Referencias (para verificación y atribución):
Community ID: Corelight Community ID spec.
JA4 / JA4H: FoxIO JA4.
Hassh: Salesforce HASSH.
TLS fingerprinting utiliza github.com/psanford/tlsfingerprint (MIT).
Parte de salida de registros: cuando [loom] tiene enabled = true, los mismos registros ECS también se agrupan y se envían mediante POST a tu URL de ingesta de Loom. Requerido cuando está habilitado: url, sensor_id, token. Opcional: batch_size (predeterminado 50), flush_interval (ej. "10s"), insecure_skip_verify (para certificados Loom autofirmados). El exportador se ejecuta de forma asíncrona y no bloquea el bucle de captura; los POST fallidos se registran en stderr y el lote se descarta (fail-open).
.
├── cmd/ # Main application entry point
├── internal/ # Config, logging, network, TLS, fingerprinting, exporters (e.g. Loom)
├── pkg/ # Linux socket helpers (SO_ORIGINAL_DST via syscall)
├── test/ # End-to-end test helpers
└── scripts/ # Utility scripts (including `initial_setup.sh`)
Ejecutar pruebas unitarias con:
go test ./...
Pruebas de extremo a extremo requieren privilegios para manipular iptables. Ejecutarlas mediante el script (desde la raíz del repositorio):
sudo -E ./scripts/run_e2e_tests.sh
El script configura el entorno e iptables. Alternativamente, usar el contenedor auxiliar: ./scripts/run_e2e_in_container.sh. E2E valida el comportamiento principal (captura de carga útil, origen/destino, detección TLS, agrupación Loom, huella digital).
Spip realiza una detección de solicitudes HTTP de mejor esfuerzo a partir de la carga útil capturada. Cuando la carga útil se asemeja claramente a una solicitud HTTP (línea de solicitud válida más encabezados básicos o ALPN), el agente emite los campos http.*, url.path y user_agent.original. Cuando no es así, Spip recurre a almacenar la carga útil en event.summary y siempre conserva el hexadecimal de la carga útil bruta en event.original_payload_hex.
Debido a que Spip refleja la IP de origen en sus respuestas y acepta tráfico TCP entrante arbitrario, está destinado a ser utilizado como un sensor tipo honeypot o colector perimetral en entornos controlados/monitoreados, no en puntos finales de usuario arbitrarios.
Ejecutar el asistente interactivo desde la raíz del repositorio (requiere root al aplicar reglas iptables):
sudo ./scripts/initial_setup.sh
El script solicita: un name corto (escrito en config.toml, usado en los registros como observer.hostname / host.name), IP y puerto de escucha, generación opcional de certificados TLS autofirmados (las rutas se escriben relativas a la configuración para que funcionen desde cualquier directorio), configuración opcional de Loom (URL, sensor_id, token, batch_size, flush_interval, verificación TLS), ruta del archivo de registro y redirección PREROUTING opcional de iptables.
| Destino | Configuración | Comportamiento |
|---|
| Local | log_file | Predeterminado: omitir o dejar vacío → stdout. Establecer una ruta → ese archivo. Uno de los dos, siempre activo. |
| Loom | [loom] con enabled = true | Opcional. Los mismos eventos se agrupan y se envían mediante POST a tu URL de ingesta de Loom además del local. |
event.summary — carga útil bruta para sondas no HTTPevent.original_payload_hex — hexadecimal de la carga útil bruta (siempre se conserva)network.community_id, tls.client.*, http.request.hash.ja4h, ssh.client.hash.hassh cuando corresponda.