
Spip сетевой сенсор, написанный на Go
Spip — это лёгкий низкоинтерактивный сенсор сетевой ловушки. Он прослушивает произвольный входящий TCP-трафик (обычный и TLS), захватывает данные, отправленные сканерами и ботами, и записывает каждое соединение в структурированном JSON-формате (в форме ECS) для лёгкой загрузки в вашу SIEM или озеро данных.
Сенсоры Spip питают HoneyLabs — бесплатную, доступную для запросов платформу аналитики угроз, построенную на захваченных данных. Чтобы увидеть, что Spip собирает на практике, просмотрите живые отчёты по каждому IP-адресу на этом сайте или еженедельный отчёт об угрозах, формируемый из сенсорной сети.

Предварительные требования
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
Этот помощник создаёт файл config.toml (запрашивает короткое name, используемое в логах), может сгенерировать самоподписанные TLS-ключи, опционально настраивает Loom (URL, sensor_id, token и т.д.), а также опционально применяет перенаправление PREROUTING iptables, используемое в примерах ниже.
config.toml
Минимальный config.toml:name = "spip-agent"
ip = "127.0.0.1"
port = 8080
Опциональные ключи конфигурации:
cert_path / key_path — включить TLS, если заданы оба; могут быть относительными по отношению к файлу конфигурации (скрипт настройки записывает относительные пути, чтобы конфигурация работала из любой рабочей директории)log_file (локальный) и/или [loom] (удалённый). См. Вывод логов ниже.read_timeout_seconds / write_timeout_seconds — тайм-ауты соединенийrate_limit_per_second / rate_limit_burst — ограничение скорости подключенийcommunity_id_seed — опциональное 16-битное зерно для хеширования потока Community ID v1 (опустите или установите 0 для значения по умолчанию)Если эти поля настройки времени выполнения опущены или установлены в 0, Spip применяет следующие значения по умолчанию:
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 записывает ECS-логи в один локальный приёмник и может опционально отправлять те же логи на сервер Loom:
Итак: локально по умолчанию — stdout; переопределите с помощью log_file для записи в файл. Опционально добавьте Loom поверх. Оба используют одинаковый формат ECS.
log_file закомментированным/пустым (stdout) или укажите путь.[loom] с url, sensor_id, token (см. Loom ниже).Spip выводит каждое соединение как один JSON-объект. Вывод отформатирован для совместимости с ECS, используя только те поля, которые может предоставить Spip (без обогащения ASN/гео). Типичные поля включают:
@timestamp — метка времени в формате RFC3339 для событияevent.id — идентификатор сессии для каждого соединенияobserver.hostname / host.name — агент name из конфигурацииsource.ip, source.port и destination.ip, destination.portnetwork.transport — например, tcphttp.request.body / url.path — когда полезная нагрузка явно напоминает HTTPuser_agent.original — когда доступноПример записи (в форме ECS), создаваемой Spip:
{
"@timestamp": "2025-12-01T19:35:18.123Z",
"event": {
"id": "bd30cdc1-95b0-49aa-b8fe-e77230b6a04f",
"summary": "Протокол 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"}
}
Примечание: агент генерирует только те поля, которые может извлечь из полезной нагрузки и метаданных соединения. Вышестоящие системы могут обогащать эти записи (гео, ASN и т.д.) по желанию.
Spip может добавлять поля пассивного снятия отпечатков к каждой записи соединения (совместимо с ECS, без изменения захвата полезной нагрузки):
network.community_id) — хеш потока v1 от 5-кортежа (исходный/целевой IP и порт, протокол). Когда трафик перенаправляется через iptables, Spip использует исходный целевой адрес (до REDIRECT), поэтому хеш совпадает с тем, который вычислили бы другие инструменты (например, Zeek, Suricata) для того же потока.tls.client.server_name (SNI), tls.client.supported_protocols (список ALPN), tls.client.hash.ja4 (отпечаток JA4).http.request.hash.ja4h (JA4H).SSH-2.0- и содержит KEXINIT: ssh.client.hash.hassh (Hassh).Все эти поля являются дополнительными; существующее поведение (локальный лог, Loom, шестнадцатеричный код полезной нагрузки, разбор HTTP) не изменяется.
Ссылки (для проверки и атрибуции):
Community ID: Corelight Community ID spec.
JA4 / JA4H: FoxIO JA4.
Hassh: Salesforce HASSH.
Снятие отпечатков TLS использует github.com/psanford/tlsfingerprint (MIT).
Часть вывода логов: когда в [loom] установлено enabled = true, те же записи ECS также объединяются в пакеты и отправляются POST-запросами на ваш Loom ingest URL. Обязательные поля при включении: url, sensor_id, token. Опциональные: batch_size (по умолчанию 50), flush_interval (например, "10s"), insecure_skip_verify (для самоподписанных сертификатов Loom). Экспортёр работает асинхронно и не блокирует цикл захвата; неудачные POST-запросы логируются в stderr, и пакет отбрасывается (отказоустойчивое открытое поведение).
.
├── cmd/ # Точка входа основного приложения
├── internal/ # Конфигурация, логирование, сеть, TLS, снятие отпечатков, экспортёры (например, Loom)
├── pkg/ # Вспомогательные функции для сокетов Linux (SO_ORIGINAL_DST через системный вызов)
├── test/ # Вспомогательные функции для сквозных тестов
└── scripts/ # Служебные скрипты (включая `initial_setup.sh`)
Запустите модульные тесты командой:
go test ./...
Сквозные тесты требуют прав для управления iptables. Запустите их через скрипт (из корня репозитория):
sudo -E ./scripts/run_e2e_tests.sh
Скрипт настраивает окружение и iptables. Альтернативно используйте контейнерный помощник: ./scripts/run_e2e_in_container.sh. E2E проверяет основное поведение (захват полезной нагрузки, источник/назначение, обнаружение TLS, пакетирование Loom, снятие отпечатков).
Spip выполняет обнаружение HTTP-запросов на основе захваченной полезной нагрузки с максимально возможным качеством. Когда полезная нагрузка явно напоминает HTTP-запрос (валидная строка запроса плюс базовые заголовки или ALPN), агент генерирует поля http.*, url.path и user_agent.original. Если это не так, Spip сохраняет полезную нагрузку в event.summary и всегда сохраняет необработанную шестнадцатеричную строку полезной нагрузки в event.original_payload_hex.
Поскольку Spip отражает исходный IP-адрес в своих ответах и принимает произвольный входящий TCP-трафик, он предназначен для использования в качестве сенсора-ловушки (honeypot) или пограничного коллектора в контролируемых/мониторируемых средах, а не на произвольных конечных устройствах пользователей.
Запустите интерактивный помощник из корня репозитория (требуются права root при применении правил iptables):
sudo ./scripts/initial_setup.sh
Скрипт запрашивает: короткое name (записывается в config.toml, используется в логах как observer.hostname / host.name), IP-адрес и порт прослушивания, опциональную генерацию самоподписанного TLS-сертификата (пути записываются относительно конфигурации, чтобы они работали из любой директории), опциональную конфигурацию Loom (URL, sensor_id, token, batch_size, flush_interval, проверка TLS), путь к файлу лога и опциональное перенаправление PREROUTING iptables.
| Приёмник | Конфигурация | Поведение |
|---|
| Локальный | log_file | По умолчанию: опустите или оставьте пустым → stdout. Укажите путь → этот файл. Всегда активен один из двух вариантов. |
| Loom | [loom] с enabled = true | Опционально. Те же события объединяются в пакеты и отправляются POST-запросами на ваш Loom ingest URL дополнительно к локальному выводу. |
event.summary — необработанная полезная нагрузка для не-HTTP проверокevent.original_payload_hex — шестнадцатеричная строка необработанной полезной нагрузки (всегда сохраняется)network.community_id, tls.client.*, http.request.hash.ja4h, ssh.client.hash.hassh, когда применимо.