Python · Deception

HoneyNet — Modular Honeypot Framework

SSH, HTTP, and FTP decoy services that log attacker credentials, shell commands, and file probes into a single JSON stream — with real-time coordinated scan detection

← Back to projects

HoneyNet — Modular Honeypot Framework

Three decoy services, one log stream, and a detector that flags the moment a scanner pivots across protocols.


The Goal

I wanted to understand what automated attackers actually do when they reach an internet-exposed service — not from a PCAP, but by giving them something that looks real and watching what happens.

The design goals were:

  1. Run convincing SSH, HTTP, and FTP decoys that accept connections and log everything
  2. Write all events to a single structured JSON log so they could be analyzed together
  3. Detect when a single IP hit more than one service within a configurable time window — a signal that someone is running a multi-protocol scanner, not just guessing passwords

How It Works

Each honeypot runs in its own thread. All three share a single HoneyLogger instance, which is the only place events are written.

SSH

Uses paramiko in server mode. Presents a realistic OpenSSH banner (SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6) to fingerprint-aware scanners. Captures every credential pair that comes in, and if a session reaches a shell prompt, logs every command typed — whoami, cat /etc/passwd, all of it.

HTTP

A Flask server presenting a generic login form. Logs every POST credential submission and every request to sensitive paths like /.env, /.git/config, and /wp-admin.

FTP

A raw socket FTP server. Speaks enough of RFC 959 to get through the authentication sequence. Captures credentials and file-access commands.

Coordinated Scan Detection

HoneyLogger._check_multi_service() maintains a per-IP dictionary of {service: last_seen_timestamp}. After every event it prunes entries older than the configured window (default 60 seconds), then checks whether the same IP has touched two or more services. If it has, it fires a COORDINATED_SCAN alert to the console and writes a coordinated_scan event into the log.

[!] COORDINATED SCAN DETECTED
    185.220.101.45 hit 2 honeypot services: SSH, HTTP
    This indicates automated multi-service scanning.

That alert means the traffic isn't a human guessing passwords on one port. It's a tool working a list.


What It Captures

Service Events Logged
SSH Connection, login attempt (user + password), shell commands
HTTP Login attempt (user + password), sensitive path probe
FTP Login attempt (user + password), file access commands
System Coordinated scan detection (cross-service correlation)

All events share the same JSON schema:

{
  "timestamp": "2024-08-22T14:32:03.841234",
  "honeypot": "SSH",
  "source_ip": "185.220.101.45",
  "source_port": 52341,
  "event_type": "login_attempt",
  "details": {
    "username": "root",
    "password": "123456"
  }
}

The log is append-only NDJSON — one event per line — so it's easy to pipe into jq, grep, or any SIEM that accepts JSON.

Built-in Analyzer

Running python honeynet.py --analyze produces a summary from the log file: total events broken down by honeypot and event type, top source IPs by volume, and the most-attempted credential pairs. In a sample run of 1,247 events the top credential was root:123456 at 47 attempts, and admin:admin was close behind.


MITRE ATT&CK Coverage

Every event maps to a documented technique. The log is usable as labeled training data for detection rules.

Observed Behavior Tactic Technique
SSH/FTP/HTTP credential stuffing Credential Access T1110 — Brute Force
Shell commands after login Execution T1059.004 — Unix Shell
whoami, id Discovery T1033 — System Owner/User Discovery
cat /etc/passwd, account enumeration Discovery T1087.001 — Local Account Discovery
HTTP sensitive file probes Discovery T1083 — File and Directory Discovery
Multi-service scanning within time window Reconnaissance T1595 — Active Scanning

Tech & Tools

  • Python 3.8+ — threading, sockets, argparse
  • paramiko — SSH server mode
  • Flask — HTTP honeypot
  • PyYAML — configuration loading
  • NDJSON — log format (one JSON object per line)
  • All three services are individually togglable via config.yaml

What I Learned

On attacker behavior: The credential lists are remarkably consistent. root:123456, admin:admin, root:root, ubuntu:ubuntu — the same pairs show up in every run because scanners are cycling through the same wordlists. A defender who monitors for any of those exact strings has a reliable low-false-positive signal.

On multi-service detection: The coordinated scan alert was the most interesting part to build. The sliding window approach — pruning stale entries on every event rather than on a timer — keeps the data structure lightweight without needing a background thread. The tradeoff is that very slow scanners (one hit per service per hour) won't trigger it, but those aren't the automated mass-scanners this is aimed at.

On log design: Centralizing all events from three different services into one schema was the right call. Being able to jq 'select(.source_ip == "185.220.101.45")' and see a complete timeline across protocols — SSH attempt, then HTTP probe three minutes later — is much more useful than three separate log files.

On threading: Each honeypot's blocking accept loop runs as a daemon thread. threading.Lock() on every file write keeps the log from getting interleaved lines when two connections arrive simultaneously.

On deception as a detection primitive: A honeypot has near-zero false positives. There is no legitimate reason for a real user to connect to port 2222 on a VPS that only exists to be a decoy. Every event in the log is real adversary activity — which makes it unusually clean training data compared to production traffic.