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.


Was this information useful?


25 Responses to "Bypass Firewall and NAT with Reverse SSH Tunnel"
  1. knife geek on February 27th, 2008

    That’s pretty slick. Dugg. Somewhere a large IT department just cried out in pain.

  2. Mark Sanborn on February 27th, 2008

    :) Good thing I didn’t tell people that you can forward just about any type of traffic you want through a tunnel bypassing packet shapers.

    Opps… :P

  3. drokmed on May 19th, 2008

    “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…

  4. Mark Sanborn on May 19th, 2008

    @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.

  5. hugo.rod on May 29th, 2008

    yes, in fact you can also do it, directly from port 80: http tunnel

  6. hugo.rod on May 29th, 2008

    i forgot:
    great article!

  7. ezero on May 30th, 2008

    You can also use autossh to keep the connection alive if it breaks.

  8. davd on June 16th, 2008

    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.

  9. Mark Sanborn on June 16th, 2008

    Davd,

    Gald it worked for ya :)

  10. john on June 23rd, 2008

    “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

  11. Mark Sanborn on June 23rd, 2008

    I prefer a free solution.

  12. akbar on June 24th, 2008

    Great! my pc in lan now I can access via Internet !

    Thanks you very much!

  13. Baris on September 8th, 2008

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

  14. r3N0oV4 on January 20th, 2009

    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

  15. James on March 16th, 2009

    How exactly do you setup gatewayports? Does anyone know?

  16. ElPraga on March 16th, 2009

    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.

  17. Mark Sanborn on March 16th, 2009

    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.

  18. ElPraga on March 16th, 2009

    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?

  19. Mark Sanborn on March 16th, 2009

    hate to have to ask, is your file executable

  20. ElPraga on March 16th, 2009

    :-) I do not mind. It is executable. I set it up with rwx for owner (root) and nothing for others. In crontab the jobs are executed by user root. When I saw this is not working I tried to make it rwxr-xr-x as well, I tried SETUID SETGID, but no success. If I start the very same script in a terminal window (as root) it does what I need..

  21. ElPraga on March 24th, 2009

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

  22. Powerhouse Programs of Linux on April 29th, 2009

    [...] 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. [...]

  23. Wolf on July 22nd, 2009

    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.

  24. Ogmoid on October 14th, 2009

    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.

  25. Daniel Hedblom on November 7th, 2009

    Thanks! Has had enormous help with this tunnel countless times =)