Distributed honeypot-style decoys that look like vulnerable SSH services, capture attacker payloads, enrich them with MITRE ATT&CK mappings, and optionally react (log, notify, block).
- Async TCP honeypot (
asyncio) that mimics an SSH banner and reads inbound payloads. - Structured event pipeline: detect → enrich → notify → block.
- JSONL logging to
logs/attacks.jsonl. - Keyword-based detection with MITRE ATT&CK enrichment (
mitre_mapper.py). - Telegram notifications (compact or full format).
- Optional host-level IP blocking via macOS
pfctl(disabled by default).
Connection → Event → detect → enrich → log → notify → block
- detect: baseline “we received a payload”.
- enrich: normalize payload, keyword match, attach MITRE
technique_ids. - notify: Telegram alert (format controlled by env).
- block: add source IP to
pfctltable whendecision=block(host only).
cp .env.example .env
# edit .env (Telegram tokens, salt, etc.)
docker compose up --buildThe service listens on port 2222 (mapped in docker-compose.yml).
pfctl controls the host firewall, so run on macOS when you need blocking:
cp .env.example .env
set -a && source .env && set +a
python3 honey_server.pyNo third-party Python packages are required (stdlib only).
Enable blocking:
SENTINEL_ENABLE_PFCTL_BLOCK=trueNote: this project does not install pf rules for you—the bad_guys table must exist in your host configuration.
See .env.example. Important variables:
| Variable | Description |
|---|---|
SENTINEL_PORT |
Listen port (default 2222) |
SENTINEL_ANONYMIZE_IP |
Anonymize IPs in logs/alerts (default true) |
SENTINEL_ANONYMIZE_SALT |
Random per-deployment salt for HMAC pseudonyms |
TELEGRAM_ENABLED |
Enable Telegram notifications |
TELEGRAM_NOTIFY_FORMAT |
compact (default) or full |
SENTINEL_ENABLE_PFCTL_BLOCK |
Block IPs via pfctl (host only) |
IPs are stored as stable pseudonyms: anon:<hmac-prefix>. Set a unique SENTINEL_ANONYMIZE_SALT per deployment so pseudonyms are not predictable across installs.
Compact (default) — short alerts, no full JSON:
TELEGRAM_NOTIFY_FORMAT=compact
Example:
[sentinel-node] MALICIOUS decision=block src=anon:abc...:53950
payload: cat /etc/passwd
keywords=cat | mitre=T1005
Full — includes complete signals JSON (debugging / SOC review):
TELEGRAM_NOTIFY_FORMAT=full
Rules live in mitre_mapper.py (keyword → technique_id). This is intentionally minimal—extend mappings as detectors mature.
sentinel-node/
├── honey_server.py # honeypot + event pipeline
├── mitre_mapper.py # MITRE keyword rules
├── docker-compose.yml
├── Dockerfile
├── logs/ # runtime logs (gitignored)
├── SECURITY.md
└── CONTRIBUTING.md
This is a honeypot. Run only where you accept the risk. Do not commit secrets (.env) or real attack logs. See SECURITY.md.
MIT — see LICENSE.