chore: initial commit
Add project scaffolding: CLAUDE.md, PLAN.md, README.md, flake.nix, and go.mod. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
178
PLAN.md
Normal file
178
PLAN.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Oubliette - SSH Honeypot
|
||||
|
||||
A fun SSH honeypot that logs login attempts, presents fake shells to "successful" logins, and tries to detect when a real human is poking around.
|
||||
|
||||
The name comes from the medieval dungeon concept - a place you throw people into and forget about them.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Language:** Go
|
||||
- **SSH:** golang.org/x/crypto/ssh
|
||||
- **Database:** SQLite
|
||||
- **Web UI:** Go templates + htmx
|
||||
- **Deployment:** Single binary with embedded assets
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Shell Profiles
|
||||
Logins that "succeed" are routed to a fake shell. Shells are selected by weighted random from a registry. Each shell implements a common interface, making it easy to add new ones.
|
||||
|
||||
```go
|
||||
type Shell interface {
|
||||
Name() string
|
||||
Description() string
|
||||
Handle(ctx context.Context, ch ssh.Channel) error
|
||||
}
|
||||
```
|
||||
|
||||
### Smart Storage
|
||||
To avoid the database growing unbounded on a small VPS:
|
||||
- **Deduplication:** Store unique (username, password, IP) combinations with a count + first_seen/last_seen timestamps instead of one row per attempt.
|
||||
- **Retention policy:** Configurable auto-pruning of records older than N days.
|
||||
- **Aggregation:** Optionally roll up old raw data into daily summary tables before pruning.
|
||||
|
||||
### Human Detection
|
||||
Score sessions based on signals that distinguish humans from bots:
|
||||
- Keystroke timing (variable delays vs instant paste)
|
||||
- Typos and backspace usage
|
||||
- Tab completion and arrow key usage
|
||||
- Adaptive behavior (commands that respond to previous output)
|
||||
- Command diversity
|
||||
- Session duration
|
||||
|
||||
Sessions crossing a human-likelihood threshold get flagged for review and can trigger webhook notifications.
|
||||
|
||||
### Login Realism
|
||||
- Don't accept every attempt. Most attempts should fail. Bots commonly try thousands of combinations from a single IP (20k+ is not unusual), so the acceptance threshold should be high and configurable.
|
||||
- **Credential memory:** When a credential is accepted, store it as a "valid" credential for a configurable TTL (e.g. 24-72 hours). If the same bot returns with the same username/password, it gets in immediately - making the credential appear legitimate and encouraging further interaction.
|
||||
- Acceptance strategy is configurable: after N failed attempts from an IP, accept the next attempt (whatever the credentials are) and remember that combo.
|
||||
- Optionally also support a static list of always-accepted credentials for testing.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 - Foundation
|
||||
|
||||
Goal: A working SSH honeypot that logs attempts, stores them in SQLite, and can present a basic fake shell. Minimal but functional.
|
||||
|
||||
### 1.1 Project Setup
|
||||
- Go module, directory structure, basic configuration (YAML or TOML)
|
||||
- Configuration for: listen address, SSH host key path/auto-generation, database path, web UI listen address
|
||||
- Nix flake with devshell and package output
|
||||
- NixOS module for easy deployment (listen address, config path, state directory, etc.)
|
||||
|
||||
### 1.2 SSH Server
|
||||
- Listen for SSH connections using x/crypto/ssh
|
||||
- Handle authentication callbacks
|
||||
- Log all login attempts (username, password, source IP, timestamp)
|
||||
- Configurable credential list that triggers "successful" login
|
||||
- Basic login realism: reject first N attempts before accepting
|
||||
|
||||
### 1.3 SQLite Storage
|
||||
- Schema: login_attempts table with deduplication (username, password, ip, count, first_seen, last_seen)
|
||||
- Schema: sessions table for successful logins (id, ip, username, shell_name, connected_at, disconnected_at, human_score)
|
||||
- Schema: session_logs table for command logging (session_id, timestamp, input, output)
|
||||
- Retention policy: background goroutine that prunes old records on a schedule
|
||||
- **Database migrations:** Version-tracked migrations using embedded SQL files. Store current schema version in a `schema_version` table, apply pending migrations on startup. Keep it simple - no external migration tool, just sequential numbered `.sql` files embedded in the binary.
|
||||
|
||||
### 1.4 Shell Interface & Registry
|
||||
- Shell interface definition
|
||||
- Registry with weighted random selection
|
||||
- Shells receive a configuration struct with common settings from the config file: hostname, banner/MOTD, fake username, and any shell-specific options
|
||||
- Basic bash-like shell:
|
||||
- Prompt that looks like `user@hostname:~$`
|
||||
- Handful of commands: `ls`, `cd`, `cat`, `pwd`, `whoami`, `uname`, `id`, `exit`
|
||||
- Fake filesystem with a few interesting-looking files
|
||||
- Log all input/output to the session_logs table
|
||||
|
||||
### 1.5 Minimal Web UI
|
||||
- Embedded static assets (Go embed)
|
||||
- Dashboard: total attempts, attempts over time, unique IPs
|
||||
- Tables: top usernames, top passwords, top source IPs
|
||||
- List of active/recent sessions
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 - Detection & Notification
|
||||
|
||||
Goal: Detect likely-human sessions and make the system smarter.
|
||||
|
||||
### 2.1 Human Detection Scoring
|
||||
- Keystroke timing analysis
|
||||
- Track backspace, tab, arrow key usage
|
||||
- Command diversity scoring
|
||||
- Compute per-session human score, store in sessions table
|
||||
- Flag sessions above configurable threshold
|
||||
|
||||
### 2.2 Notifications
|
||||
- Webhook support (generic HTTP POST, works with Slack/Discord/ntfy)
|
||||
- Trigger on: human score threshold crossed, new session started, configurable
|
||||
- Include session details in payload
|
||||
|
||||
### 2.3 Session Replay
|
||||
- Store keystroke-by-keystroke data with timing information
|
||||
- Web UI: replay a session in a terminal-like viewer, watching commands play back in real-time
|
||||
- Filter/sort sessions by human score
|
||||
|
||||
### 2.4 Adaptive Shell Routing
|
||||
- If early keystrokes suggest a bot, route to basic shell or disconnect
|
||||
- If keystrokes suggest a human, route to a more interesting shell
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 - Fun Shells
|
||||
|
||||
Goal: Add the entertaining shell implementations.
|
||||
|
||||
### 3.1 Bash Shell Variations
|
||||
- **Infinite sudo:** always asks for password, never works, logs every attempt
|
||||
- **Slow decay:** shell gets progressively slower, commands take longer and longer
|
||||
- **Haunted:** commands gradually return stranger output, files appear/disappear, `whoami` returns different users
|
||||
- **Bread crumbs:** fake .bash_history, id_rsa files, database configs pointing to other honeypots
|
||||
|
||||
### 3.2 Cisco IOS Shell
|
||||
- Realistic `>` and `#` prompts
|
||||
- Common commands: `show running-config`, `show interfaces`, `enable`, `configure terminal`
|
||||
- Fake device info that looks like a real router
|
||||
|
||||
### 3.3 Smart Fridge Shell
|
||||
- Samsung FridgeOS boot banner
|
||||
- Inventory management commands
|
||||
- Temperature warnings
|
||||
- "WARNING: milk expires in 2 days"
|
||||
- Easter eggs
|
||||
|
||||
### 3.4 Text Adventure
|
||||
- Zork-style dungeon crawler
|
||||
- "You are in a dimly lit server room."
|
||||
- Navigation, items, puzzles
|
||||
- The dungeon is the oubliette itself
|
||||
|
||||
### 3.5 Other Shell Ideas (Future)
|
||||
- **Banking TUI:** 80s-style green-on-black bank terminal
|
||||
- **Nuclear launch terminal:** "ENTER LAUNCH AUTHORIZATION CODE"
|
||||
- **ELIZA therapist:** every response is a therapy question
|
||||
- **Pizza ordering terminal:** "Welcome to PizzaNet v2.3"
|
||||
- **Haiku shell:** every response is a haiku
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 - Polish
|
||||
|
||||
Goal: Make the web UI great and add operational niceties.
|
||||
|
||||
### 4.1 Enhanced Web UI
|
||||
- GeoIP lookups and world map visualization of attack sources
|
||||
- Charts: attempts over time, hourly patterns, credential trends
|
||||
- Session detail view with full command log
|
||||
- Filtering and search
|
||||
|
||||
### 4.2 Operational
|
||||
- Prometheus metrics endpoint
|
||||
- Structured logging (slog)
|
||||
- Graceful shutdown
|
||||
- Systemd unit file / deployment docs
|
||||
|
||||
### 4.3 GeoIP
|
||||
- Embed a lightweight GeoIP database or use an API
|
||||
- Store country/city with each attempt
|
||||
- Aggregate stats by country
|
||||
Reference in New Issue
Block a user