RoomlerDocs

SSH without sshd

Get a real shell on any enrolled machine by its mesh address — with no sshd installed, no port bound and no firewall rule, on Linux, macOS and Windows.

Roomler can serve SSH on a machine that runs no sshd, binds no port and needs no firewall rule — including Windows, where an SSH server is usually a separate project.

bash
ssh dev-box

Why there is no listening port

The agent intercepts SSH traffic below the operating system’s socket layer: packets addressed to the machine’s own mesh address on the SSH port are diverted into the agent before the OS ever sees them.

That is not cleverness for its own sake — it is what makes the feature possible at all:

Binding a port often fails — on a machine that already runs sshd, the port is taken for every local address.
Nothing for security software to kill — there is no sshd process for an endpoint agent to terminate.
Unreachable off-mesh by construction — not “closed by a firewall rule” but “there is nothing listening at all”.

It also means it works on locked-down corporate machines where installing an SSH server is not permitted, and on Windows, which it serves the same way it serves everything else.

What works

Interactive shells

— A real terminal, with resize handling, on Linux, macOS and Windows.

Commands

ssh dev-box uptime and friends.

File transfer

scp and sftp.

Port forwarding

-L local forwards, -J jump hosts and -D dynamic SOCKS.

`-R` remote forwarding is deliberately not implemented

It would make the machine bind a listening socket — the exact thing this design exists to avoid — and it is redundant here, because the client is itself a mesh node and can be reached directly.

Turning it on

SSH is off by default and stays off until several independent things are true. Each is owned by a different party, and any one of them refuses:

  1. The organization enables remote SSH. It is a separate switch from remote command execution.
  2. The user has the SSH permission. Also separate — and not included in the default administrator role.
  3. The device has an SSH policy allowing it.
  4. The machine itself has SSH enabled in its own configuration, with an authorised key list. Enabling SSH without listing a key grants nobody anything.

The machine's own setting is the one that survives a compromised server

Gate 4 exists precisely because the server cannot write it. Every other gate is a policy the control plane enforces; the last one is a decision the machine holds. That is what makes the whole chain worth having.

Which account a session runs as

A session runs as what was actually asked for, never more. The device decides which accounts are permitted, and an unset value means authenticate, then run nothing — rather than quietly handing over a root shell.

An unparseable setting is a refusal, not a fallback.

Port forwarding is default-deny

An empty forward allow-list means *nowhere*, not *anywhere*

This is the opposite of the tunnel path, and the reason is worth understanding: a tunnel flow was already authorised by the server before it reached the machine, so an empty local list sensibly means “no extra restriction”. An SSH direct-tcpip channel has no server in the path at all — so an empty list must mean nothing is permitted, or every SSH session would be a silent open pivot into whatever that machine can reach.

Refusals tell the client whether it was policy or an unreachable destination, so you can act on the difference. The reason text stays in the machine’s log, because it names internal topology.

`-J` needs the *jump* host to allow the final target

A jump-host hop is authorised by the machine doing the jumping, not by your client. If -J is refused, the allow-list you need to change is on the jump host.

Depending on the device’s policy, a session may prompt the person at the machine before it starts. The prompt fires when the session is redeemed, not when it is authorised, so a refusal can explain itself on your terminal instead of appearing as an unexplained rejected connection — and you are told a wait is happening rather than left looking at a hang.

What gets recorded

Two separate records, deliberately not merged:

Record Written by Is
The decision The server Authoritative — who asked, for what, and whether it was granted or refused, with the reason
The activity The machine A claim by the host: sessions opened and closed, commands run, forwards attempted

An empty activity log is not evidence of inactivity

Activity reporting is a machine-side setting that defaults to off, so a machine that does not report looks exactly like an idle one. The server’s own decision log is what survives a machine that lies.

Session contents are never recorded

No keystroke stream, no command output. Recording a terminal would mean shipping whatever an operator typed — passwords into sudo, credentials into a database client — off the machine, which is the opposite of what this product promises.

Last updated · Edit this page

to navigate · Enter to open · Esc to close