Reversing an ssh connection



Update: I have now created a script to automate setting up a persistent reverse ssh tunnel.

One of the nice features of VNC is that you can reverse a connection. If you are behind a firewall (or a router doing NAT) that doesn't allow incoming connections, VNC allows you to connect to a "listening server". As soon as a connection is established to the listening server, the "listener" gets a regular VNC connection back to the originating box.

Last Friday, I figured out how to do the same thing and reverse a connection with ssh.

I'll lay out the process first, and then talk about the applications and implications afterwards.

The simple approach:

Assume we have two machines. A firewalled server at work and your laptop. You can't connect to the server at work because all incoming connections are blocked by the firewall. So you ask Pete (who is at work and behind the firewall) to login to the server and then ssh to your laptop with the following command:

ssh -f -N -R 10000:localhost:22 username@ip_address_of_laptop

This creates an ssh connection from the work machine to the laptop. the -f and -N are basically cosmetic options. The -R 10000:localhost:22 option causes the laptop to listen on port 10000 and forward any requests on that port to the work machine (this is basically ssh tunneling).

So now, you can ssh to port 10000 on your laptop and you will actually be sshing to port 22 on the firewalled server:

ssh username@localhost -p 10000

(you will have to use your username and password for the server - despite it looking like you are logging onto localhost)

An ugly but effective hack to get rid of Pete:

To get rid of Pete you could setup a cron job on the server that attempts to connect to your laptop every hour. You would have to setup passwordless logins (using public_key authentication), but then you would know that if you needed to get on the server you could just make sure your laptop was on and willing to receive an ssh connection at the right time. Using www.dyndns.org would help you handle changing IP addresses on your laptop.

A better approach:

If you have access to a machine that is always on and outside of the firewall then you can use it as a middleman. The idea is to log onto middleman from behind the firewall, setup forwarded ports as above and just leave it connected all the time. Anytime you need to get behind the firewall you just go through the middleman. Here are the steps:

Setup your middleman to do gateways and stay connected without timing out. Edit /etc/sshd_config and make sure the following options are set:

TCPKeepAlive yes
ClientAliveInterval 30
ClientAliveCountMax 99999
GatewayPorts yes

You have to restart sshd to make these changes.

ps -aux | grep sshd

locate the ssh daemon

kill -hup

This will force sshd to rehash the config. (thanks Phil Vell!)


Then from the firewalled machine run:

nohup ssh -f -N -R 10000:localhost:22 username@middleman

The only difference from before is that this is now connecting the middleman and not the laptop to the firewalled machine, and we are using nohup to make sure the process doesn't die when the user logs out.

Then with your laptop you log onto port 10000 on the middleman which will forward your requests to the firewalled machine:

ssh usernameAtFirewalledMachine@middleman -p 10000

If you were unable to edit the sshd_config then you can still do this, you just have to jump through two hoops instead of one. First you log into middleman, then you log into the firewalled machine:

ssh usernameAtMiddleman@middleman
ssh usernameAtFirewalledMachine@localhost -p 10000

Applications and Implications

You can do a lot with this. It eliminates the need for a VPN. Ssh allows you to forward any port so you can connect to the intranet, the email server, anything that was hiding behind the firewall. This post is already too long, so I will leave it to the comments section for some examples of this sort of thing.

It also makes it pretty easy for social engineers to get behind your firewall. ("Could you run the Necessary Operation Help User Protocol for me, just type nohup...")

But I am a Windows luser!

Windows users can do this as well. Just install ssh using Cygwin. All of the ssh goodies including a client, server and scripts to set it up are there.

7 Response to Reversing an ssh connection

  1. [...] h which impacted the districts in which Dignitas operates. Mike of Hacktivate explains how to reverse an ssh connection which among other things allows access to network [...]

  2. 3 says:

    Very useful blog. Thank you.
    http://www.semeistvoto.com

  3. [...] okmark" title="Permanent Link: "> This was  all stolen from Hacktivate - Reversing an ssh connection. (I only pasted the contents here in [...]

  4. [...] 好景不长,今天发现居然连80端口都无法访问了。 于是上网找到这个。 [...]

  5. [...] found a post explain how to use SSH to create a reverse tunnel, it could be very useful in some case but also could be a terrible nightmare for information [...]

  6. Daenyth says:

    You also need to set "AllowTcpForwarding yes" for this to work.

  7. bijan says:

    this is a great post, thank you. However I have one problem. Let’s say I have a server (the middle man) with an IP address of 174.2.2.2, from my office box, I run:

    ssh -R 178.2.2.2:1200:localhost:22 bijan@178.2.2.2

    It connects with no problem. I also put “GatewayPorts clientspecified” in /etc/ssh/ssh_config. When I issue “netstat -an | grep LISTEN”, I see it’s listening on port 1200 for 127.0.0.1

    The problem is that when I issue:

    ssh -p 1200 officeUser@178.2.2.2

    I get the following error: “ssh: connect to host 178.2.2.2 port 1200: Connection refused”. However if I ssh into 178.2.2.2 (to port 22 with a user on it) and then issue:

    ssh -p 1200 officeUser@localhost

    It’s no problem, I login like a charm! I should say I disabled iptables, so, is it really a filtering problem or something wrong with me?

Post a Comment