The Problem

SSH access to hosts behind NAT or firewalls normally requires a VPN, port‑forwarding, or manual reverse tunnels. Setting up and maintaining those solutions adds operational overhead and breaks the standard ssh workflow.

What This Does

mssh provides a minimal rendezvous service that lets a NATed machine keep a persistent outbound connection to a public server. The server then proxies inbound SSH sessions to the agent, so users can run the ordinary ssh client or use a ProxyCommand without extra networking tricks.

  • The CLI lives in cmd/mssh/main.go and parses sub‑commands (server, agent, proxy).
  • Core networking is in internal/server/server.go (server listener, client registration) and internal/agent/agent.go (agent keep‑alive and reverse connection).
  • Stream handling (Wrap, Pipe) and SSH key loading (internal/sshutil/auth.go) are factored into small utility packages.

How It Is Wired

Execution starts at main in cmd/mssh/main.go (line 38). main loads configuration (loadConfig), then dispatches to one of four runners:

RunnerFileKey functions (calls)
runServercmd/mssh/main.goNew → Run (internal/server)
runAgentcmd/mssh/main.goParseServerAddr → runOnce (internal/agent)
runProxycmd/mssh/main.goDial (internal/proxy) → Pipe (internal/stream)
runSSHcmd/mssh/main.goDial → Wrap (internal/stream) → SSH client logic

runServer creates a Server via internal/server.New (10‑function reach) and calls Server.Run, which accepts connections and hands them to registerAgent or handleClient.

runAgent resolves the node ID (sanitizeNodeID), builds a connection to the server (Dial), then repeatedly calls runOnce to open a reverse stream (internal/stream/buffered_conn.New).

runProxy and runSSH share the Dial helper (called from three places) to open a TCP stream to the server, then either pipe raw bytes (Pipe) or wrap the connection with SSH framing (Wrap).

The most‑connected symbols are Dial, Wrap, New, Run, and ParseServerAddr, each referenced from four call sites, indicating they are change‑impact hotspots. No circular import cycles are present, and the internal call graph contains 58 edges, keeping the codebase relatively flat.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/mssh
cd mssh

# Build the binary
go build ./cmd/mssh

# Install (optional systemd wrapper)
sudo bash install/install.sh          # drops /usr/local/bin/mssh

# Start the rendezvous server (public host)
sudo mssh server --host 0.0.0.0 --port 8443

# On a NATed host, start the agent (node ID optional)
sudo mssh agent prod-db-1 --server <public‑host>:8443 --ssh-port 22

# From a client, connect via built‑in client
mssh alice@prod-db-1

# Or via ProxyCommand (no binary on client needed)
ssh -o ProxyCommand="mssh proxy prod-db-1 --server <public‑host>:8443" alice@localhost

Configuration files live under ~/.mssh/config.yaml and are created with mssh config init (the command exists in the source but is not exercised in the current binary). Keys are auto‑loaded from the standard ~/.ssh directory or via SSH_AUTH_SOCK.

Real‑World Use

A cloud‑based monitoring server runs mssh server behind an Nginx TLS terminator. Each on‑premise database instance runs mssh agent to maintain a reverse tunnel. Operators can then ssh db-admin@prod-db-1 from any workstation without opening inbound ports on the databases, preserving existing firewall policies.

Code Health & Issues

  • HIGH – Pin GitHub Action versions – .github/workflows/release.yml uses softprops/action-gh-release@v2. Replace with a fixed SHA to avoid supply‑chain drift.
  • HIGH – Missing LICENSE – No license file; default “all rights reserved” blocks reuse. Add MIT or Apache‑2.0.
  • MEDIUM – Enable Dependabot – Only one manifest (go.mod). Add .github/dependabot.yml for Go modules and GitHub Actions.
  • MEDIUM – Add dependency‑vulnerability scan – CI lacks a scan step; incorporate dependency-review-action or osv-scanner.
  • LOW – Set workflow timeouts – release.yml omits timeout-minutes; add a reasonable bound to prevent overlapping runs.
  • MEDIUM – Duplicated code blocks – Six‑line snippets repeat across install/install.sh, install/uninstall.sh, internal/agent/agent.go, and internal/proxy/proxy.go. Extract shared helpers to a common package/script.

No test files are present, so code paths are currently unverified by automated tests. CI runs only the release workflow.

The Bottom Line

mssh delivers a lightweight, Go‑based SSH rendezvous service that eliminates the need for VPNs or manual reverse tunnels, with a clear CLI and modest codebase. It lacks automated tests, a license, and some CI hardening, so teams should add those before adopting it in production. Suitable for engineers comfortable extending Go code and managing simple systemd services.