- Go 82%
- Shell 18%
|
|
||
|---|---|---|
| .github/workflows | ||
| cmd/mssh | ||
| docs | ||
| install | ||
| internal | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
mssh
Minimal rendezvous service for reaching SSH behind NAT
This enables SSH access to machines behind NAT/firewalls using a simple rendezvous server. No complex VPN setup required, works with your ssh command out of the box.
Usage
Deploy the server on a publicly reachable machine, run the agent on each host behind NAT, then connect from your machines using either the built-in Go SSH client or the ProxyCommand approach described below.
| Command | Purpose |
|---|---|
mssh server |
Runs the rendezvous service on a public host |
mssh agent <node-id> |
Keeps a connection open from a NATed host back to the server |
mssh proxy <node-id> / mssh user@node |
Lets you connect from your machines |
Server
Run the rendezvous server:
mssh server --host 0.0.0.0 --port 8443
Production tip: Deploy behind a TLS proxy (nginx, Traefik, Caddy) with Let's Encrypt for secure public exposure.
Agent
Run on the remote host behind NAT:
# With explicit node-id
mssh agent prod-db-1 --server rendezvous.example.com:8443 --ssh-port 22
# Auto-detect node-id from primary IPv4
mssh agent --server rendezvous.example.com:8443
The agent automatically re-registers after each session ends.
Node-ID rules: May contain letters, digits, ., _, and -. If omitted, the primary IPv4 address is used.
Client
Built-in SSH client:
mssh alice@prod-db-1
# With custom server or identity
mssh alice@prod-db-1 --server other.example.net:8443 --identity ~/.ssh/prod_key
The client scans ~/.ssh/id_{ed25519,rsa,ecdsa} (with passphrase prompts) and falls back to SSH_AUTH_SOCK.
ProxyCommand integration:
ssh -o ProxyCommand="mssh proxy prod-db-1 --server rendezvous.example.com:8443" alice@localhost
To make this seamless, add it to ~/.ssh/config so ssh prod-db works without long command lines:
Host prod-db-1
HostName localhost
User alice
ProxyCommand mssh proxy prod-db-1 --server rendezvous.example.com:8443
Now simply run ssh prod-db and the ProxyCommand will invoke mssh proxy ... behind the scenes.
Installation
Set VERSION=vX.Y.Z to pin a specific release (default: latest).
Binary only
curl -fsSL https://raw.githubusercontent.com/eznix86/mssh/main/install/install.sh | sudo bash
The script drops the binary at /usr/local/bin/mssh (override with BIN_DIR=/path).
Server (systemd)
curl -fsSL https://raw.githubusercontent.com/eznix86/mssh/main/install/install.sh | \
sudo BIN_DIR=/usr/local/bin bash -s -- server --host 0.0.0.0 --port 8443
Agent (systemd)
curl -fsSL https://raw.githubusercontent.com/eznix86/mssh/main/install/install.sh | \
sudo bash -s -- agent --server rendezvous.example.com:8443 --ssh-port 22
if node-id is omited, it defaults to auto-detected IP. Or set unique name.
Manual Build
go build ./cmd/mssh
sudo install -m 0755 mssh /usr/local/bin/mssh
Uninstall
curl -fsSL https://raw.githubusercontent.com/eznix86/mssh/main/install/uninstall.sh | sudo bash
Removes the binary and disables all systemd units.
Configuration
Only used for mssh username@node-id
Initialize your config file:
mssh config init
This creates ~/.mssh/config.yaml:
server: rendezvous.example.com:8443
identity: ~/.ssh/id_ed25519 # optional; leave blank to auto-detect keys / use ssh-agent
nodes:
prod-db-1:
server: prod-rendezvous.example.com:8443
identity: ~/.ssh/prod_key
Priority: CLI flags → node-specific values → top-level defaults
Security
- TLS termination: Place the rendezvous server behind a TLS proxy (nginx/Caddy/Traefik) with Let's Encrypt
- Optional hardening: Add mutual TLS or IP filtering at the proxy layer
License
MIT
