A memory-safe reimplementation of endlessh in Go, with new features and first-class NixOS support.
Endlessh is an SSH tarpit that slowly sends an endless, random SSH banner to connecting clients, trapping them for hours or days. It operates before any cryptographic exchange, so no crypto libraries are needed. Put your real SSH server on another port and let attackers waste their time here.
This reimplementation replaces the single-threaded C poll() loop with Go's goroutine-per-client model, providing compile-time memory safety and simpler concurrency while preserving full behavioral compatibility with the original.
- Custom banners -- serve lines from a file instead of random data
- Randomized transmission speed -- vary the delay between lines to appear more natural
- NixOS flake -- declarative module with full systemd hardening
Usage: endlessh [-vh] [-46] [-d MS] [-f CONFIG] [-l LEN] [-m LIMIT] [-p PORT]
[--banner FILE] [--random-speed] [--speed-min MS] [--speed-max MS]
-4 Bind to IPv4 only
-6 Bind to IPv6 only
-d INT Message millisecond delay [10000]
-f Set and load config file [/etc/endlessh/config]
-h Print this help message and exit
-l INT Maximum banner line length (3-255) [32]
-m INT Maximum number of clients [4096]
-p INT Listening port [2222]
-s Use syslog
-v Print diagnostics to standard output (repeatable)
-V Print version information and exit
--banner FILE Path to custom banner file
--random-speed Randomize delay between lines
--speed-min MS Minimum delay in ms for random speed
--speed-max MS Maximum delay in ms for random speed
Compatible with the original config file format, plus new options:
Port 2222
Delay 10000
MaxLineLength 32
MaxClients 4096
LogLevel 0
BindFamily 0
# New options
Banner /path/to/banner.txt
RandomSpeed true
SpeedMin 5000
SpeedMax 20000
When RandomSpeed is enabled without explicit SpeedMin/SpeedMax, the delay is randomized between Delay/2 and Delay*2.
| Signal | Action |
|---|---|
| SIGTERM | Graceful shutdown |
| SIGINT | Graceful shutdown |
| SIGHUP | Reload configuration file |
| SIGUSR1 | Log connection statistics |
go build -o endlessh-go
Add the flake to your inputs and enable the module:
# flake.nix
{
inputs.endlessh.url = "github:your-user/endlessh";
}
# configuration.nix
{ inputs, ... }:
{
imports = [ inputs.endlessh.nixosModules.default ];
services.endlessh-go = {
enable = true;
port = 22;
delay = 10000;
randomSpeed = true;
speedMin = 5000;
speedMax = 20000;
openFirewall = true;
};
}The systemd service runs with DynamicUser, restricted capabilities, and full hardening. Ports below 1024 automatically receive CAP_NET_BIND_SERVICE.
This is a reimplementation of endlessh by Chris Wellons. The original is an elegant ~740-line C99 program released into the public domain under the Unlicense.
This is free and unencumbered software released into the public domain.