I recently needed to establish an ad-hoc ssh connection to a server behind a firewall. I didn’t control the firewall and couldn’t get a port mapped through it for incoming ssh access, so I had to use a reverse ssh connection. What is a reverse ssh connection, why would you want to establish one and how do you do it?
Read on…
As I was not able to have a port mapped through the firewall for an incoming ssh connection, I needed some other way of establishing a secure shell connection to the server. Enter the technique of reverse ssh.
This will work if you either have incoming ssh access to your workstation, or you have an intermediate server that you can ssh into from the target server.
Assuming you’re going via an intermediate server, the chain then looks something like:
Workstation < – – – > Intermediate Server < – – – > Target Server
As long as your workstation and the target server can both ssh to the intermediate server, you are good to go.
Step 1 – On the Target Server
ssh -f -N -T -R22022:localhost:22 intermediate.example.com
This establishes an ssh connection from the target server to the intermediate server (and assumes that you can reach the intermediate server on port 22)
The various options are as follows:
-f : Tells ssh to put itself in the background after it authenticates. It allows ssh to ask for the password, but then after it’s done so, it puts itself in the background. This is so that you don’t need to keep the terminal window open that established the connection.
-N : This tells ssh not to execute a remote command – normally ssh will start a remote shell and let you type into it to run commands on the remote computer. This option is generally only useful when you’re forwarding ports (with -L or -R) and means that a remote shell isn’t executed, so it saves a small amount of system resources.
-T : This option tells ssh not to allocate a pseudo TTY, again it saves a small amount of system resources if you’re not using it for a remote shell.
-R : This is where the magic happens. I often use SSH to forward a local port to a remote machine with -L. This does the reverse, forwarding a port on the remote machine to the local machine.
22022:localhost:22 : This instruction for -R says to forward remote port 22022 (so, port 22022 on the intermediate server) through to port 22 on localhost. This is from the point of view of the target server, so any traffic sent to port 22022 on the intermediate server is forwarded to port 22 on the target server.
intermediate.example.com : This is the hostname or IP address of the intermediate server. Don’t forget to use a username if you need to, e.g. [email protected]. You can also specify -p if the intermediate server is listening on a port that’s not 22.
Step 2 – On the Workstation
Simply ssh to the intermediate server as normal:
ssh intermediate.example.com
Use a username if required, and specify the port with -p if it’s not listening on port 22.
Step 3 – On the Intermediate Server
Once you have ssh’d from your workstation to the intermediate server, you then ssh again to the port specified in the -R command above (port 22022 in this example) like so:
ssh localhost -p 22022
Again, use a username if you need to.
If the intermediate port (in this example 22022) is open to you on the intermediate server, then you can combine steps 2 and 2 above into one:
ssh intermediate.example.com -p 22022
This establishes a connection on the intermediate server to port 22022 – which is being listened on, and forwarded through to port 22 on the target server. So while ssh is being told to port 22022 on the intermediate server, the first ssh session from the target server listens to this and forwards it to port 22, where it’s own ssh daemon picks up the connection.
Done!
Now, you have an ssh connection being relayed from your workstation, via the intermediate server to the target server. Everything you type into ssh on your workstation will be running on the target server.
This post contains information that’s been condensed and re-worded from a post on StackExchange.