Featured image of post reverse_ssh: Manage Reverse Shells With Native SSH Syntax, No VPN Required

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

reverse_ssh flips SSH: target machines connect back to your server, and you connect to them with standard SSH syntax. HTTP/WebSocket/TLS transports punch through firewalls. SCP, SFTP, and port forwarding all work.

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):

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

reverse_ssh flips it:

1
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:

1
2
3
4
5
6
7
8
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:

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

Deploying a Client

On the target machine:

1
2
3
4
# 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:

1
2
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:

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

Connect using standard SSH jump host syntax:

1
2
3
4
5
6
7
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:

1
2
3
4
5
6
7
8
# 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

1
2
3
4
5
6
7
8
# 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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