2026-07-14 13:30:28 +07:00
2026-07-13 23:02:02 +07:00
2026-07-13 22:54:42 +07:00
2026-07-14 13:30:28 +07:00
2026-07-13 17:58:48 +07:00
2026-07-13 17:58:48 +07:00
2026-07-13 17:58:48 +07:00
2026-07-13 17:58:48 +07:00
2026-07-13 17:58:48 +07:00
2026-07-13 23:06:36 +07:00
2026-07-14 05:49:10 +07:00

👻 TrollSSH

A fake SSH server that accepts any login and plays back video as colored ASCII/Unicode art at whoever connects to it

SSH Demo

Features

  • Accept any credentials
  • Colored ASCII/Unicode video playback - resized live to the client's terminal, using a configurable character ramp, defaults to the Unicode block-character preset
  • Automatic color detection - renders 24-bit truecolor, 256-color, or plain grayscale depending on what the connecting client reports supporting
  • Multiple frame sets - clients get a random one, arrow keys switch between them (configurable)
  • Honeypot extras - optional credential logging, per-IP and global connection limits, handshake timeout, customizable banner / fake login / goodbye text

Quick start

Generate a frame set from a video through container image

docker run --rm -v ./video.mp4:/home/app/video.mp4 -v ./frames:/home/app/frames \
    ghcr.io/yuzuzensai/trollssh:v1.0.1 trollssh --generate --video video.mp4 --resolution 512

This writes frames/<name>.tsf, a simple container of color JPEG frames plus the source fps. You can drop as many .tsf files into frames/ as you like. The server loads all of them.

Run the server with docker-compose.yaml

cp .env.example .env
docker compose up -d

./data persists host keys and text assets.

./frames holds the .tsf frame sets.

Then try it:

ssh anyone@localhost

Configuration

Server configuration is via environment variables, loaded from a .env file if one exists (see .env.example for the full annotated list). Durations are in milliseconds.

Host keys (data/id_rsa, data/id_ed25519) are generated on first run and reused afterwards.

Frame generation is configured with flags:

Flag Default Description
--generate, -g Generate a .tsf frame set instead of serving
--video, -v Source video path
--resolution, -r 512 Stored frame max dimension in pixels. Higher = sharper but bigger .tsf files and slower rendering

Customization

Optional text files in data/ (created next to the binary):

File Shown
data/banner.txt As the SSH banner, before authentication
data/fakelogin.txt Right after "login", before playback
data/goodbye.txt When the session ends after MAX_LOOP playthroughs

Development

Requirements: Go 1.25+ and ffmpeg / ffprobe on PATH (only for --generate).

go run ./src --generate --video video.mp4 --resolution 512
go run ./src

Or build a binary:

go build -o trollssh ./src
./trollssh

CI runs the following checks on every push:

gofmt -l ./src                    # format
go vet ./src/...                  # vet
golangci-lint run ./src/...       # lint, see https://golangci-lint.run
go test ./src/...                 # tests

To run them automatically before each commit, install lefthook and golangci-lint, then:

lefthook install

License

MIT

S
Description
👻 A fake SSH server that accepts any login and plays back video as colored ASCII/Unicode
Readme MIT 28 MiB
Languages
Go 99.4%
Dockerfile 0.6%