Add 6 new Prometheus metrics for richer observability: - auth_attempts_by_country_total (counter by country) - commands_executed_total (counter by shell via OnCommand callback) - human_score (histogram of final detection scores) - storage_login_attempts_total, storage_unique_ips, storage_sessions_total (gauges via custom collector querying GetDashboardStats on each scrape) Add optional bearer token authentication for the /metrics endpoint via web.metrics_token config option. Uses crypto/subtle.ConstantTimeCompare. Empty token (default) means no auth for backwards compatibility. Also adds "cisco" to pre-initialized session/command metric labels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
3.5 KiB
Markdown
105 lines
3.5 KiB
Markdown
# Oubliette
|
||
|
||
An SSH honeypot that logs login attempts, presents fake shells to "successful" logins, and tries to detect when a real human is poking around.
|
||
|
||
Named after the medieval dungeon - a place you throw people into and forget about them.
|
||
|
||
## Status
|
||
|
||
Early development. See `PLAN.md` for the roadmap.
|
||
|
||
## Usage
|
||
|
||
### Build
|
||
|
||
```sh
|
||
# With Nix
|
||
nix build
|
||
|
||
# With Go
|
||
nix develop -c go build ./cmd/oubliette
|
||
```
|
||
|
||
### Configure
|
||
|
||
Copy and edit the example config:
|
||
|
||
```sh
|
||
cp oubliette.toml.example oubliette.toml
|
||
```
|
||
|
||
Key settings:
|
||
- `ssh.listen_addr` — listen address (default `:2222`)
|
||
- `ssh.host_key_path` — Ed25519 host key, auto-generated if missing
|
||
- `auth.accept_after` — accept login after N failures per IP (default `10`)
|
||
- `auth.credential_ttl` — how long to remember accepted credentials (default `24h`)
|
||
- `auth.static_credentials` — always-accepted username/password pairs (optional `shell` field routes to a specific shell)
|
||
- Available shells: `bash` (fake Linux shell), `fridge` (Samsung Smart Fridge OS), `banking` (80s-style bank terminal TUI), `adventure` (Zork-style text adventure dungeon), `cisco` (Cisco IOS CLI with mode state machine and command abbreviation)
|
||
- `storage.db_path` — SQLite database path (default `oubliette.db`)
|
||
- `storage.retention_days` — auto-prune records older than N days (default `90`)
|
||
- `storage.retention_interval` — how often to run retention (default `1h`)
|
||
- `shell.hostname` — hostname shown in shell prompts (default `ubuntu-server`)
|
||
- `shell.banner` — banner displayed on connection
|
||
- `shell.fake_user` — override username in prompt; empty uses the authenticated user
|
||
- `web.enabled` — enable the web dashboard (default `false`)
|
||
- `web.listen_addr` — web dashboard listen address (default `:8080`)
|
||
- Session detail pages at `/sessions/{id}` include terminal replay via xterm.js
|
||
- `web.metrics_enabled` — expose Prometheus metrics at `/metrics` (default `true`)
|
||
- `web.metrics_token` — bearer token to protect `/metrics`; empty means no auth (default empty)
|
||
- `detection.enabled` — enable human detection scoring (default `false`)
|
||
- `detection.threshold` — score threshold (0.0–1.0) for flagging sessions (default `0.6`)
|
||
- `detection.update_interval` — how often to recompute scores (default `5s`)
|
||
- `notify.webhooks` — list of webhook endpoints for notifications (see example config)
|
||
|
||
### GeoIP
|
||
|
||
Country-level GeoIP lookups are embedded in the binary using the [DB-IP Lite](https://db-ip.com/db/lite.php) database (CC-BY-4.0). The dashboard shows country alongside IPs and includes a "Top Countries" table.
|
||
|
||
For local development, run `scripts/fetch-geoip.sh` to download the MMDB file. The Nix build fetches it automatically.
|
||
|
||
### Run
|
||
|
||
```sh
|
||
./oubliette -config oubliette.toml
|
||
```
|
||
|
||
Test with:
|
||
|
||
```sh
|
||
ssh -o StrictHostKeyChecking=no -p 2222 root@localhost
|
||
```
|
||
|
||
### NixOS Module
|
||
|
||
Add the flake as an input and enable the service:
|
||
|
||
```nix
|
||
{
|
||
services.oubliette = {
|
||
enable = true;
|
||
package = inputs.oubliette.packages.${system}.default;
|
||
settings = {
|
||
ssh.listen_addr = ":2222";
|
||
auth.accept_after = 10;
|
||
auth.static_credentials = [
|
||
{ username = "root"; password = "toor"; }
|
||
];
|
||
};
|
||
};
|
||
}
|
||
```
|
||
|
||
Alternatively, use `configFile` to pass a pre-written TOML file instead of `settings`.
|
||
|
||
### Docker
|
||
|
||
Build a Docker image via nix:
|
||
|
||
```sh
|
||
nix build .#dockerImage
|
||
docker load < result
|
||
docker run -v /path/to/data:/data -p 2222:2222 -p 8080:8080 oubliette:0.8.0
|
||
```
|
||
|
||
Place your `oubliette.toml` in the data volume. The container exposes ports 2222 (SSH) and 8080 (web/metrics).
|