jump to navigation

A fun hack: triggered reverse ssh connections for remote access to anywhere November 8, 2010

Posted by jdstrand in security, ubuntu.

So, like a lot people, I get asked to install Ubuntu on friend’s and family’s computers. I talk to them about what their use cases are and more often than not (by far) I install it on their systems. That’s cool. What is less cool is tech support for said installation. Not that I mind doing it or that there is a lot to do, but what becomes problematic is when they go home and are sitting behind their NAT router from their ISP, and I can’t just connect to them to fix something I forgot or to help them out of a jam. Before I go any farther let me say that what I am going to describe is never done on machines without the owner’s permission and that I am always upfront in that my account on his/her machine is an administrative account that has access to everything on the system (barring any encryption they use, of course). I should also mention that what I am describing is more in the ‘fun hack that other people might like’ category, and not in the ‘serious systems administration’ category. In other words, this is total crack, but it is fun crack. :)

Now, there are a lot of ways to do this, and I have tried some and surely missed many others. Here are a few I’ve tried:

  • Giving realtime tech support over the phone
  • Giving realtime tech support over some secure/encrypted chat mechanism
  • Email support
  • OpenSSH access from my machine to theirs, including adjusting their router for port forwarding
  • VPN access from their machine to my network, at which point I can OpenSSH to their machine

Rather than going through a comparison of all the different techniques, let’s just say they all have issues: realtime support almost always entails describing some obscure incantation to fix the problem, which is neither confidence inspiring for them and is extremely time consuming. Email is too slow. Routers get reset and straight OpenSSH doesn’t work when they are away from home. VPN access is not bad, especially with the use of OpenVPN client and server certificates. It has the added benefit of being opt-in by the user, and is easy to use with the network-manager-openvpn-gnome package. It is probably the most legitimate form of access, and should be highly considered, especially for corporate environments. The only real issues are that some draconian networks will block this VPN traffic and that my IP happens to change so they have to fiddle with their connection setting. So I started doing something different.

Remotely triggered reverse OpenSSH connections
The basic idea is this: on the client install OpenSSH, harden it a bit, install a firewall so that no one can connect to it, then create a cron job to poll an HTTP server you have access to for an IP address to connect to, then create a reverse SSH connection to that IP address. If this sounds a little shady and a bit like a botnet, well, you’d be right, but again, I did ask for permission first. :)

So, more specifically, on the remote machine (ie, the one you want to administer):

  • Install openssh-server and set /etc/ssh/sshd_config with the following:
    # Force key authentication (ie, no passwords)
    PasswordAuthentication no
    # Only allow logins to my account
    AllowUsers me
    Obviously, you will need to copy your ssh key over to this machine (man ssh-copy-id) before restarting OpenSSH and putting the above into effect.
  • Setup a firewall. Eg:$ sudo ufw enable
  • Create some passwordless ssh keys. Eg:
    $ ssh-keygen -f revssh.id_rsa
  • Create a script to poll some HTTP server, then create the reverse connection (this is an abridged script. I’ve omitted error checking and locking for brevity):#!/bin/sh
    hname=`hostname | cut -f 1 -d '.'`
    ip=`elinks -no-home -dump "http://your.web.server/$hname" | head -1 | awk '{print $1}' | egrep '^[1-9][0-9\.]*$'` || {
    #echo "Could not obtain ip" >&2
    exit 0
    echo "Connecting to $ip"
    # we use StrictHostKeyChecking=no so that keys gets added without prompting
    ssh -oStrictHostKeyChecking=no -i $HOME/.ssh/revssh.id_rsa -p 8080 -NR 3333:localhost:22 revssh@"$ip" sleep 30 || true

To remotely administer a machine, create a file on the server with the name of the hostname of the client to have only the external IP address of your network in it, and then the remote client will pick it up and try to setup a reverse ssh connection on port 8080 (usually open even on the most draconian firewalls, but you could also use 53/tcp, 80/tcp or 443/tcp), after which you can connect to the remote machine with something like:$ ssh -t -p 3333 localhost

This is hardly perfect. For one thing, the client is polling an HTTP server so it can easily be man-in-the-middled, but that isn’t a big deal because even if the attacker had full knowledge of this technique, all it gives is a connection to OpenSSH on the client, which is configured to only allow connections from ‘me’ and with my ssh key. This could of course be fixed by connecting with HTTPS and using connection.ssl.cert_verify=1 with elinks. Similarly, the HTTP server could be subverted and under attacker control. For the client, this is no different than the MITM attack in that the attacker really doesn’t have much to work with due to the OpenSSH configuration. Also, the client completely ignores the fingerprint of the server it is connecting to, but again, not huge deal because of our OpenSSH configuration on the client, but you will need to be extra careful in checking fingerprints when connecting to the reverse connection.

You need to remember to update your webserver (ie, just remove the file) so the client isn’t always trying to connect to you. Also, it is somewhat inconvenient that when you logout the reverse connection is still there, but instead of using ‘exit’ to logout of the remote machine, use something like: $ kill -9 `ps auxww | grep [s]sh | grep 3333 | awk '{print $2}'`

While is it relatively easy to setup the client, it is somewhat harder to setup the initiating end. First off, you need to have a webserver that can be accessed by the client. Then you need to have the ssh server on your local machine listen on port 8080 (done either via a port redirect or a separate ssh server). You also need to setup a non-privileged ‘revssh’ user (eg, /bin/false for the shell, a disabled password, etc) on your machine. If you are behind a firewall/router you need to allow connections through your firewall to your machine so that the connection to port 8080 from the client is not blocked. Finally, if you remotely administer multiple clients you will want to keep track of their ssh fingerprints, because when you connect to ‘-p 3333 localhost’ they will conflict with each other (most annoying, but workable). I have written a ‘revssh_allow’ script to automate the above for me (not included, as it is highly site-specific). It will: fire up an sshd server on port 8080 that is specially configured for this purpose, adjust my local firewall to open port 8080/tcp from the client, connect to my router to set up the port redirection to my machine, then poll (via ‘netstat -atn | grep “:3333.*LISTEN”‘) for the connection from the client, then remind me how to connect to the client and how to properly kill the connection.

So yeah, this is a fun hack. Is it something to put in production? Probably not. Does it work for administering friend’s and family’s computers? Absolutely, but I’ll have to see how well it works over the long haul.

Have fun!


1. George Brooke - November 8, 2010

Have you seen http://telepathy.freedesktop.org/wiki/SSH-Contact I’ve not had a chance to actually test it yet but it seems like a usefull way to handle sshing to a machine potentially behind a NAT.

jdstrand - November 8, 2010

I have not tried it, though now that you mention it, I remember hearing something about it. It looks to be an interesting concept, though its caveat is (quoted from their web page):

If you install the ssh-contact service, your ssh daemon is exposed to all your IM contacts. Of course they still have to make the ssh authentication (password, ssh key, etc). This means that your sshd is not “protected” anymore behind a NAT or firewall. It is equivalent to have ssh daemon running with a public IP address and port 22 open. So ssh-contact-service security == sshd security. It is your choice to trust sshd or not.

Not having looked at the implementation, it seems a viable alternative as long as you understand the above.

2. Bryce Harrington - November 8, 2010

Have you found you often need to remotely administer user boxes? I ask because while I provide support for 3 family members, the administration typically is: 1) cable connection problems / power, 2) upgrade help, and 3) usage questions / confusion. None really needing to be ssh’d into the box.

Seriously, “Try turning it off and then back on” has been the solution to half the problems. “Is it plugged in and turned on?” has been most of the rest. Ubuntu itself just rocks.

jdstrand - November 8, 2010

Ubuntu does ‘just rock’! The three administrative items you mention are by far the most typical, and I certainly don’t need shell access for that. In fact, I very seldom have to do anything once I configure the box, but it does happen from time to time (especially for the users that know enough to do a lot of damage ;)) and having shell access can be a serious time saver.

3. Anonymous - November 8, 2010

You could also do the lookup of your IP with dyndns instead of putting a file on a webserver.

I have been using a similar setup for some time, only that I use dyndns and on the remote machine I run OpenVPN to connect to that address. I simply set it to when I don’t want the remote machine to connect to me.

4. Sygic cdkey - January 27, 2011

Interesting read, ive been visiting your site daily and really impressed with the topics on your site. Thank you.

5. konaya - December 21, 2011

Why a firewall? Seems like overkill to me. Why not simply configure the SSH daemon only to listen on the loopback interface?

jdstrand - December 21, 2011

Listening on the loopback should work fine. People will probably also want to enable remote ssh access from certain address ranges or IPs, so mentioning a firewall helps support both the reverse ssh connection and standard remote access.

6. Johan - September 9, 2012

So.. how does it work in the long run since you started using this method? I look for a solution to do remote surveillance and remote measurement via a satellite internet account on the remote site, but host name and port redirections (for connections originating from my home) ask for a expensive professional account on the remote end, otherwise hostname redirects (via no-ip.com) just get blocked. So I thought of using some sort of reverse VPN / ssh connection originating from the remote end.
At my level of knowledge it is complicated for me to implement, but maybe a viable method?

jdstrand - September 25, 2012

I found this method to be fairly brittle. It would work sometimes, but not others. I ended up using openvpn with client side certificates instead of ssh. The clients use the same polling method, and when they see the file on the remote server, they try to connect. So far, this has worked quite a bit better.

7. SebaZ - May 8, 2014

How do you connect to the client once VPN has been established? I mean, how do you know the IP assigned to the remote client?

jdstrand - June 6, 2014

The client is polling the HTTP server, so you can look in the HTTP server logs for the IP.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: