Skip to main content

Command Palette

Search for a command to run...

reverse_ssh: Manage Reverse Shells With Native SSH Syntax, No VPN Required

Published
3 min read

Originally published at recca0120.github.io

You need to connect to a machine behind NAT with no public IP and inbound traffic blocked. The usual answers are VPN or ngrok-style tunnels, but both require setup on the target. reverse_ssh has the target connect back to your server, then you connect using standard ssh. SCP, SFTP, port forwarding — all of it works.

Architecture

Normal SSH requires you to reach the target (needs a public IP or shared network):

You ──SSH──→ Target (must be reachable inbound)

reverse_ssh flips it:

Target ──connects back──→ RSSH Server ←──SSH── You

The target only needs outbound connectivity. Firewalls almost never block outbound traffic.

Setting Up the Server

The fastest path is Docker:

docker run -d \
  --name rssh \
  -p 3232:2222 \
  -e EXTERNAL_ADDRESS=your-server.com:3232 \
  -e SEED_AUTHORIZED_KEYS="$(cat ~/.ssh/id_ed25519.pub)" \
  -v ./data:/data \
  --restart unless-stopped \
  reversessh/reverse_ssh
  • EXTERNAL_ADDRESS: your server's public address — clients use this to connect back
  • SEED_AUTHORIZED_KEYS: your SSH public key for accessing the management console

Verify it's running:

ssh -p 3232 your-server.com
# You're now in the RSSH console

Deploying a Client

On the target machine:

# Download the client binary from the server's built-in web server
curl https://your-server.com:3232/client -o rssh-client
chmod +x rssh-client
./rssh-client your-server.com:3232

Or generate a ready-to-run command from the RSSH console:

rssh> link --name my-machine --expiry 24h
# Outputs a curl command — run it on the target to connect

Connecting to a Target

Once a client connects, list it in the console:

rssh> ls
# my-machine  192.168.1.100  linux/amd64  2m ago

Connect using standard SSH jump host syntax:

ssh -J your-server.com:3232 my-machine

# Or set it up in ~/.ssh/config
Host rssh-*
  ProxyJump your-server.com:3232

ssh rssh-my-machine

SCP and SFTP

Everything runs over standard SSH protocol, so SCP and SFTP work without any changes:

# Copy a file to the target
scp -J your-server.com:3232 file.txt my-machine:/tmp/

# SFTP session
sftp -J your-server.com:3232 my-machine

# rsync over SSH
rsync -avz -e "ssh -J your-server.com:3232" ./local/ my-machine:/remote/

Port Forwarding

# Local forward: target's port 8080 → local port 9090
ssh -J your-server.com:3232 -L 9090:localhost:8080 my-machine

# Remote forward
ssh -J your-server.com:3232 -R 8080:localhost:3000 my-machine

# SOCKS proxy (use target as a jump point)
ssh -J your-server.com:3232 -D 1080 my-machine

Punching Through Restrictive Firewalls: Multiple Transports

If the target environment only allows specific outbound traffic, RSSH supports multiple transports:

# HTTP polling (works almost everywhere)
./rssh-client http://your-server.com:80

# HTTPS
./rssh-client https://your-server.com:443

# WebSocket
./rssh-client ws://your-server.com:80

# WebSocket over TLS
./rssh-client wss://your-server.com:443

The server can listen on multiple transports simultaneously. Clients choose whatever they can reach.

Persistent Connection

Auto-reconnect on boot with systemd:

cat > /etc/systemd/system/rssh.service << EOF
[Unit]
Description=RSSH Client
After=network.target

[Service]
ExecStart=/usr/local/bin/rssh-client your-server.com:3232
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now rssh

Use Cases

  • Remote access to NAT'd devices: home NAS, IoT devices, office intranet machines
  • Lab management: a fleet of VMs all connecting back to one console
  • Authorized penetration testing: the tool is designed for this workflow
  • Cross-firewall development: cloud CI machines reaching back to a local dev environment

Security Notes

  • Lock down authorized_keys on the server — only trusted operators should reach the console
  • Client binaries hardcode the server fingerprint, preventing MITM
  • Back up data/keys/ — regenerating server keys breaks all deployed clients
  • Don't use this on systems you don't have authorization for

Summary

reverse_ssh's core value: use the SSH tools you already know to work with reverse connections. Once a target is connected, everything is standard SSH — -J jump host handles the rest.

Multiple transports mean it works even in restrictive environments. HTTP polling gets out of almost any network that has internet access at all.

References

More from this blog

recca0120

115 posts