Bypass Firewall and NAT with Reverse SSH Tunnel
Recently I wanted to control my computer from a remote location. Problem was that the destination computer was behind a NAT and a firewall. Almost all large networks (corporate and universities) including home routers are now using some sort of NAT (Network Address Translation).
The problem with NAT is, that you can’t directly connect to the computers that are outside the NAT. Computers behind a NAT can only recieve packets that they request. For this reason we need to create a reverse SSH tunnel to establish a connection. If you are familiar with Hamachi or gotoypc type software this is the exact same thing they do to connect to computers behind NAT/Firewalls, only they use their severs as the middle man. We are going to have to find our middle man on our own.
Can’t I just use Hamachi gotomypc or some other software?
Well I actually forgot about reverse tunnels the other day and installed hamachi on my linux server. After trying to connect with my windows machine outside the NAT I found that it couldn’t create a connetion. After searching I found that Hamachi does not support low-speed relay (reverse tunnel) with their linux version of the program. That makes the Linux version of Hamachi useless. If you are trying to connect to a Windows machine by all means it is probably easier to just install Hamachi. But if you are dealing with a Linux machine there is a much easier way, provided that you ssh access to a computer in the middle. To establish a reverse tunnel in Linux you type in only one simple command.
So how about gotomypc? Well if you don’t have a computer in the middle to connect to and are willing to pay $19.95 a month, its not a bad service. I don’t believe gotomypc works for Linux however.
In order for you to create a reverse tunnel you must have SSH access to a middle computer that you can connect to from origin computer.
Setting it all up
On the destination computer type the following command. Replaceing middleuser with your name and replacing middle with the domain of the middle computer.
ssh -R 10002:localhost:22 middleuser@middle
This will open port 10002 for listening and forward all future connections to port 22 at destination. This connection must remain on the entire time to ensure that you can access your destination computer whenever you want.
Now if sshd is set to use GatewayPorts you should be able to connect with this:
ssh destinationuser@middle -p 10002
If you are not sure if GatewayPorts is on or you don’t have the access to change it use the following method to connect:
First connect to the middle computer how you would normally.
ssh user@middle
Then connect to the localhost of the middle computer on port 10002.
ssh user@localhost -p 10002
Note: The port 10002 is arbitrary you can use any port you want.
You should now be remotely logged into your computer behind the NAT/Firewall. Enjoy
For added security you could Add Port Knocking to SSH and Use Keys Instead of Passwords
FreeBSD Users
The above instructions will work for FreeBSD but for whatever reason I was unable to get the connection to stay alive for more than a few minutes. So, as a temporary work around I just do the same thing as above but I then run the program, “top” so that the connection is forced to stay alive. This isn’t the ideal solution however and I would appriceate it if someone could tell me why its closing the connection all of the time.








That’s pretty slick. Dugg. Somewhere a large IT department just cried out in pain.
Opps…
“Somewhere a large IT department just cried out in pain.”
A large IT department wouldn’t allow someone to ssh out the firewall using port 10002, or any other port for that matter.
Most of my users aren’t allowed to get through ANY ports. They have to use the proxy for web access, get their NTP and DNS etc from internal servers. No ssh, ftp, irc, etc. Nothing.
Only our privileged users are allowed to ssh using 22 out to the Internet. For them, I don’t mind if they can reverse ssh. I’ll port forward to their box if they like.
Still a great trick though, especially for smaller companies that don’t block internal to internet traffic, like those that use hardware firewalls like from Belkin, D-Link, Netgear, Linksys, etc.
Great article! Bookmarked…
@drokmed,
You are right, If you filter internal traffic on port 10002 this method will fail; however, don’t be to quick to think you protected.
I can just about guarantee you allow encrypted internal and external traffic through the port 443, AKA SSL/HTTPS. If you didn’t users wouldn’t be able to log into any secure site.
You can use this same method through ports 443 to masquerade the communication as if it were SSL.
yes, in fact you can also do it, directly from port 80: http tunnel
i forgot:
great article!
You can also use autossh to keep the connection alive if it breaks.
Thanks for an excelent howto! Using the command
ssh -N -f -R 10002:localhost:22 middleuser@middle
the tunnel between middle and destination has staid up for a couple of month now winthout problems.
Davd,
Gald it worked for ya
“Recently I wanted to control my computer from a remote location. Problem was that the destination computer was behind a NAT and a firewall”
just use a web based ssh client like this -
http://www.browsershell.com
I prefer a free solution.
Great! my pc in lan now I can access via Internet !
Thanks you very much!
Thanks a lot , It’s great an uncomplicated ssh reverse how to.
And what’s mean free? Free Software or free of charge software? I hope you mean Free Software (as free speech)
This solution is the one many commercial software developers relay on. Hope one day they’ll understand that open software is the only that really works, like the open-suggestions
you gave us.
Thank you
How exactly do you setup gatewayports? Does anyone know?
Thanks a lot! It almost solved completely what I need to do. I have one more thing I would like to ask though. I am in Spain, my mother in Czech Repulic without any computer knowledge running Ubuntu (because it actually runs better than Win on her HW), were bothe behind NAT. I know that if I ask her to make the ssh connection to middle, I can connect to her computer, but would it be possible to automate it?
I was thinking using cron to run every 15 minutes the connection (using sshpass to deal with identification) and killing it 5 minutes later (killall sshpass). — Only not to stay connected all the time (eventhough I do not know if this would provide a risk for my mothers computer, I think no, and I am not sure if this is a burden for the middle server or not)
But I was not able to open the ssh connection using cron. Running the same script manually from terminal did the work.
Have You ideas what could I change to run it through cron?
Or do I have to use something like rungetty and establish the connection at boot time?
Please, give me a hint.. I have looked, but I am not able to solve this.
Run if from a script using an identication key file to remove identifaction issues. If you want to keep the connection alive you can use autossh.
Thanks Mark,
but identification is not the issue. The thing is that if I run the script via cron, the ssh connection is not made. If I run the same script in terminal, it works as expected.
Here is the script:
root@Ubuntu-ElPraga:~# cat /etc/cron.grex_on/ssh.grex
#!/bin/bash
export SSHPASS=mypasswd
sshpass -e ssh -N -f -R 10005:localhost:22 middleuser@middle.org
root@Ubuntu-ElPraga:~#
Could it have something to do with starting within a terminal?? Do You have an idea?
hate to have to ask, is your file executable
I have found the error. The filename of the script I used for the cron contained a dot “.” That is why it was not executed by run-parts. It had nothing to do with being executed in the terminal after all.. It took me time to find out.
[...] SSH is a secure remote login program and is absolutely awesome. I use ssh to login to remote servers every day. You can also use it to create encrypted tunnels for transferring data and also NAT traversal using reverse tunnels. [...]
BTW: you could also use the keep-alive mechanism built into ssh/sshd (instead of running top) to keep the connection up. It should be turned on by default, but your configuration could be different.
I’ve had firewalls dropping TCP connections after a time (5min seems common). I set the ClientAlive sshd config value to 180 (3min) and stopped having problems with idle disconnect.
IIRC KeepAlive wasn’t enough in my situation.
Thanks! Has had enormous help with this tunnel countless times =)