I'm creating a large online puzzle and would like one section to involve players connecting with a normal SSH client such as PuTTY to uncover lore or progress. The connection would lead to a text-adventure-style interface rather than a real shell, with only a few simulated commands such as cd, ls, cat, and possibly ssh. I don't want players—or automated attackers—to gain access to the host system, execute arbitrary commands, or damage anything. A username and password could filter out some bot traffic, and the emulated files would not need to exist on the real filesystem. Is it practical to run an SSH-compatible service that passes input to a custom terminal emulator? Are there existing libraries for this, or would it need to be written from scratch?
4 Answers
Yes. You can embed an SSH server in several languages and handle each session with your own application instead of launching a system shell. Libraries such as gliderlabs/ssh for Go can take care of the SSH protocol while your code implements the allowed commands and fictional directory tree. Avoid passing user input to a shell, run with a dedicated unprivileged account, and keep the service isolated from anything valuable on the host. A container or separate disposable machine adds another layer of protection.
Another option is a normal SSH server configured with a dedicated account whose login shell is your custom program. That program can display menus and simulated files without exposing an actual shell. However, public SSH services attract constant scanning and attack attempts, so this still needs careful isolation, minimal privileges, rate limiting, logging, and ideally a disposable container or virtual machine. Never rely on obscurity or a password alone as the security boundary.
Be careful with the design of the client experience. SSH clients use real authentication, host-key checking, terminals, and sometimes local configuration files, so players should not be asked to modify their existing keys or trust settings unnecessarily. An embedded SSH implementation can provide the familiar connection process while keeping the game state entirely in memory or in a restricted data store. Do not expose an interactive ssh command inside the emulated environment unless it is another tightly controlled simulation.
If confidentiality is not important, Telnet may be simpler than SSH. It is essentially a TCP connection carrying terminal input and output, so a small Python or similar program can provide the fake interface without implementing SSH authentication or terminal handling. A crashed process should only close the connection, provided it is not running with access to a real shell or sensitive files. The downside is that usernames, passwords, and puzzle data are sent unencrypted, so don’t use this approach for anything genuinely secret.

That’s exactly the kind of library I was looking for. I may implement the prototype in Go or Rust and keep the command set very small.