tarssh
An async Rust SSH tarpit
tarssh
is an SSH tarpit – a server that trickles an endlessly repeating introductory
banner to clients for as long as it remains connected, in order to expend the resources
of attackers.
It’s based on the same concept as Chris Wellons’ Endlessh, a similar service written in C.
Tarssh is my first Rust program using Tokio, an asynchronous runtime that allows for the construction of highly scalable event-driven programs using kqueue, epoll and similar APIs, using Rust’s Futures API.
The first release of tarssh
predates Rust’s async/await syntax, and so the result
was a quite unwieldy tree of method chains building up large types to implement
the required Futures:
loop_fn
For contrast here is how I rewrote that to use async/await:
for chunk in BANNER.iter.cycle
I ended up forgoing this future-per-connection approach in the name of efficiency: now instead of a timer delay for each connection, there is an array of slots corresponding to each delay interval. Connections and their associated state are placed in slots and polled as the daemon iterates through its delay loop.
This more closely resembles how Endlessh functions. It’s less straight-forward, but since the entire point of a tarpit is to maintain lots of connections without expending too many resources I felt it made sense here.
As of 2022 I’ve largely stopped running tarssh
– almost all clients have wised up to the
problem these simple tarpits cause and disconnect quite quickly. In its time, though,
it wasn’t uncommon for me to see many hundreds of clients to remain trapped for hours,
even days, regaled by Yon Yonson’s riveting tale.
-% tarssh -v --disable-timestamp &
[INFO tarssh] listen, addr: 0.0.0.0:2222
[INFO tarssh] privdrop, enabled: false
[INFO tarssh] sandbox, enabled: true
[INFO tarssh] start, servers: 1, max_clients: 4096, delay: 10s, timeout: 30s
-% telnet 0 2222
Trying 0.0.0.0...
[INFO tarssh] connect, peer: 127.0.0.1:21491, clients: 1
Connected to 0.
Escape character is '^]'.
My name is Yon Yonson
I liv^]
telnet> close
Connection closed.
-% [INFO tarssh] disconnect, peer: 127.0.0.1:21491, duration: 40.02s, error: Broken pipe (os error 32), clients: 0