TIP SSH Reverse Tunnel
From Gentoo Linux Wiki
[edit] Situation
You sometimes visit a campus lab, internet cafe ... and you want your computer (notebook) there to connect to your ssh daemon at your home, dorm ... (destination), but the destination is behind NAT (Network Address Translation, IP masquerade) or firewall, blocking connections to your destination machine.
Fortunately you somehow happened to be able to initiate a TCP connection to some other computer (the middle) from both computers (notebook and destination) where you have UNIX accounts.
[edit] Preconditions
- the notebook can connect to port 10000 (or any other) on the middle
- the middle is running an ssh daemon willing to do port-forwarding (enabled by default in OpenSSH) and the GatewayPorts feature is enabled
- you have an account on the middle
- you can open an ssh connection from destination to the middle in advance (and leave it open) or you have someone do it on your behalf
- the SSH daemon is running on destination on port 22. In fact the port can be arbitrary and the daemon does not have to allow port forwarding. You can even establish your own (not root) ssh daemon.
You do not need root privileges on any of these machines.
If you need to use port <=1024 on the middle, you would need to be root there.
[edit] The actual steps
All you have to do create a tunnel from the middle to destination.
- On destination, using an ssh client, login to middle and open a tunnel from port 10000 on middle to port 22 on destination.
user@destination$ ssh -R 10000:localhost:22 middleuser@middle
or
user@destination$ ssh -N -f -R 10000:localhost:22 middleuser@middle
- This will open port 10000 for listening and forward all future connections to port 22 at destination.
- Do not close this session and make sure it will not close itself due to inactivity (see /etc/ssh/sshd_config below)
- Go wherever you want with your notebook and point your ssh client to port 10000 on middle. Use the user/password pair on destination.
user@notebook$ ssh destinationuser@middle -p 10000
- You are now logged in the destination. Enjoy.
Note: To make the last command work you need to enable the GatewayPorts feature on middle.
Turn on -X or -Y for XForwarding, and you can run X apps on your localmachine through the tunnel!
[edit] Avoiding timeout
We must make sure that we can hold an SSH session without timing out. This way, when we leave home, we know that the connection won't just die. So, edit the /etc/ssh/sshd_config (destination) file on the server as shown:
| File: /etc/ssh/sshd_config on the server |
|
... TCPKeepAlive yes ClientAliveInterval 30 ClientAliveCountMax 99999 ... |
[edit] Enabling the GatewayPorts
If you want to use the above given example, the SSH daemon running on middle must be set to allow the GatewayPorts feature. To make this possible, edit the /etc/ssh/sshd_config as follows. Don't forget to restart the ssh server after making these changes!
| File: /etc/ssh/sshd_config on middle |
|
... GatewayPorts yes ... |
This makes it possible that forwarded ports on middle can be reached from another host. If you do not have the necessary privileges to make these changes, you can still log on to middle directly and then reach destination by opening a ssh connection to localhost -p 10000. That means, instead of:
user@notebook$ ssh destinationuser@middle -p 10000
You have to call:
user@notebook$ ssh user@middle
- Use the user/password pair on middle.
and then:
user@middle$ ssh user@localhost -p 10000
- Use the user/password pair on destination.
[edit] Alternatives
- app-shells/rrs: Reverse Remote Shell. Supports Encryption. Another way to do things, rrs has the advantage that when you close down a connection from your computer (say by accident) it will start trying to connect to you again. This behaviour can be emulated with ssh by putting it in a script or in crontab.
- autossh is a program to start a copy of ssh and monitor it, restarting it as necessary. see HOWTO_autossh
- harms is an 4-port-forwarding application that's doing exactly the same
- sshto: multihop ssh wrapper using UUCP-style host1!host2!host3 notation
