Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
tunnel
Last updated on May 4, 2015 Authored by Dan Nanni 12 Comments
You are running a Linux server at home, which is behind a NAT router or restrictive firewall. Now you want
to SSH to the home server while you are away from home. How would you set that up? SSH port forwarding
will certainly be an option. However, port forwarding can become tricky if you are dealing with multiple
nested NAT environment. Besides, it can be interfered with under various ISP-specific conditions, such as
restrictive ISP firewalls which block forwarded ports, or carrier-grade NAT which shares IPv4 addresses
among users.
Here the port 10022 is any arbitrary port number you can choose. Just make sure that this port is not used by
other programs on relayserver.
The "-R 10022:localhost:22" option defines a reverse tunnel. It forwards traffic on port 10022
of relayserver to port 22 of homeserver.
With "-fN" option, SSH will go right into the background once you successfully authenticate with an SSH
server. This option is useful when you do not want to execute any command on a remote SSH server, and just
want to forward ports, like in our case.
After running the above command, you will be right back to the command prompt of homeserver.
Log in to relayserver, and verify that 127.0.0.1:10022 is bound to sshd. If so, that means a reverse tunnel
is set up correctly.
relayserver~$ sudo netstat -nap | grep 10022
Now from any other computer (e.g., clientcomputer), log in to relayserver. Then
access homeserver as follows.
relayserver~$ ssh -p 10022 homeserver_user@localhost
One thing to take note is that the SSH login/password you type for localhost should be for homeserver,
not for relayserver, since you are logging in to homeserver via the tunnel's local endpoint. So do not
type login/password for relayserver. After successful login, you will be on homeserver.
Connect Directly to a NATed Server via a Reverse SSH
Tunnel
While the above method allows you to reach homeserver behind NAT, you need to log in twice: first
to relayserver, and then to homeserver. This is because the end point of an SSH tunnel
on relayserver is binding to loopback address (127.0.0.1).
But in fact, there is a way to reach NATed homeserver directly with a single login to relayserver. For
this, you will need to let sshd on relayserver forward a port not only from loopback address, but also
from an external host. This is achieved by specifying GatewayPorts option in sshd running
on relayserver.
Open /etc/ssh/sshd_conf of relayserver and add the following line.
relayserver~$ vi /etc/ssh/sshd_conf
GatewayPorts clientspecified
Restart sshd.
Debian-based system:
relayserver~$ sudo /etc/init.d/ssh restart
Log in to relayserver and confirm with netstat command that a reverse SSH tunnel is established
successfully.
relayserver~$ sudo netstat -nap | grep 10022
In the above command, while 1.1.1.1 is the public IP address of relayserver, homeserver_user must be
the user account associated with homeserver. This is because the real host you are logging in to
is homeserver, not relayserver. The latter simply relays your SSH traffic to homeserver.
Set up a Persistent Reverse SSH Tunnel on Linux
Now that you understand how to create a reverse SSH tunnel, let's make the tunnel "persistent", so that the
tunnel is up and running all the time (regardless of temporary network congestion, SSH timeout, relay host
rebooting, etc.). After all, if the tunnel is not always up, you won't be able to connect to your home server
reliably.
For a persistent tunnel, I am going to use a tool called autossh. As the name implies, this program allows
you to automatically restart an SSH session should it breaks for any reason. So it is useful to keep a reverse
SSH tunnel active.
As the first step, let's set up passwordless SSH login from homeserver to relayserver. That
way, autossh can restart a broken reverse SSH tunnel without user's involvement.
Next, install autossh on homeserver where a tunnel is initiated.
From homeserver, run autossh with the following arguments to create a persistent SSH tunnel destined
to relayserver.
homeserver~$ autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o
"StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval
60" -o "ServerAliveCountMax 3" -R 1.1.1.1:10022:localhost:22 relayserver_user@1.1.1.1
The "-M 10900" option specifies a monitoring port on relayserver which will be used to exchange test data
to monitor an SSH session. This port should not be used by any program on relayserver.
The "-fN" option is passed to ssh command, which will let the SSH tunnel run in the background.
The "-o XXXX" options tell ssh to:
Use key authentication, not password authentication.
Automatically accept (unknown) SSH host keys.
Exchange keep-alive messages every 60 seconds.
Send up to 3 keep-alive messages without receiving any response back.
The rest of reverse SSH tunneling related options remain the same as before.
If you want an SSH tunnel to be automatically up upon boot, you can add the above autossh command in
/etc/rc.local.
Conclusion
In this post, I talked about how you can use a reverse SSH tunnel to access a Linux server behind a restrictive
firewall or NAT gateway from outside world. While I demonstrated its use case for a home network via
a public VPS, you must be careful when applying it for corporate networks. Such a tunnel can be considered
as a breach of a corporate policy, as it circumvents corporate firewalls and can expose corporate networks to
outside attacks. There is a great chance it can be misused or abused. So always remember its implication
before setting it up.
Subscribe to Xmodulo
Do you want to receive Linux FAQs, detailed tutorials and tips published at Xmodulo? Enter your email
address below, and we will deliver our Linux posts straight to your email box, for free. Delivery powered by
Google Feedburner.
Your email add Subscribe
Support Xmodulo
Did you find this tutorial helpful? Then please be generous and support Xmodulo!
Bio
Latest Posts
Dan Nanni
Dan Nanni is the founder and also a regular contributor of Xmodulo.com. He is a Linux/FOSS enthusiast who
loves to get his hands dirty with his Linux box. He likes to procrastinate when he is supposed to be busy and
productive. When he is otherwise free, he likes to watch movies and shop for the coolest gadgets.
Related FAQs:
How to create an HTTP tunnel on Linux with httptunnel
How to diff remote files over SSH
How to edit a remote file over ssh
How to block unwanted IP addresses on Linux efficiently
How to secure SSH login with one-time passwords on Linux
Categories: Networking, Security
Tags: firewall, nat, ssh, tunnel
12 thoughts on “How to access a Linux server behind NAT via reverse SSH tunnel”
1. Reply
Reply
> open-vpn in udp mode is more stealthy compared with ssh on tcp
I thought the opposite. If a firewall is set to block unrecognized encrypted application protocols, it will
block OpenVPN. But SSH is whitelisted in many corporate networks.
Reply
And you are right. ssh is easy, but think for a moment there was time in the past when all of us
discovered a bug in ssl (Heartbleed). At that time any admin who used ssh could not sleep very well,
until the patch was available! I was running ssh with Heartbleed bug for many years!
But for some others admins (me included), open-vpn (udp/tls-auth, and ssh accessible only from the
open-vpn tunnel) was very happy, because it was not vulnerable (TLS-auth on top of the SSL -
see https://openvpn.net/index.php/access-server/heartbleed.html)
In conclusion, some setups are easy to made, others are more complicated, each of them has
advantages and disadvantages at the same time.
2. Reply
3. Reply
Can the same trick be used to expose other services? Like a MySQL database for example?
Reply
4. Reply
5. Reply
I've been searching for something close like that so I can access services that come out of my home network,
which is NATed.
I don't master very well using VPNs and stuff...(I've read the above comments too)
6. Reply
7. Reply
Reply
Reply