DEV Community

Recca Tsai
Recca Tsai

Posted on • Originally published at recca0120.github.io

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

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)
Enter fullscreen mode Exit fullscreen mode

reverse_ssh flips it:

Target ──connects back──→ RSSH Server ←──SSH── You
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)