SSH Tunneling - Poor Techie's VPN

"If we see light at the end of the tunnel, it is the light of the oncoming train" ~ Robert Lowell. Oh yes, another good quote. This post is on SSH tunneling, or as I like to call it 'Poor Man's VPN'. Contrary to the sysadmin's popular belief, SSH tunneling actually can be very valuable use for both techies and home users. I say contrary to popular belief because 'reverse tunneling' and tunneling http traffic through SSH can bypass firewalls and content filters. But this article isn't about how to violate your corporate internet use policy, it's about how to create SSH tunnels to make your life just a little bit easier.

Why SSH Tunnels instead of VPN? Well, I actually use both at home. If you have followed any of my posts on jaysonbroughton.com, I use a 3-factor authentication with OpenVPN (user name, certificate & One-Time-Password). But if I want to check on one of my servers from the house via my Android, or a computer where I don't have administrative rights (required of my custom portable OpenVPN client), or even tunnel vnc over ssh to fix a problem on my better half's Linux laptop then SSH is my backup to using VPN.

What I'll cover here today is just your basics: how to create tunnels, what the syntax means, examples of reverse tunnels and why would you use each one of them. I'll briefly go over ssh_config, but a more in-depth post on custom ssh_config's will be at a later date.

So as always, time to dispense with the necessities. I use Debian in a virtual environment so your results may vary. In this case I am using OpenSSH_5.3p1 as a Server and a mix of OpenSSH 5.X ssh clients with my examples. Before I get too far into tunneling I'll say this: If you feel the need to use SSH tunneling via http or reverse SSH tunnels to bypass your corporate firewall make sure you are not violating any of your companies Internet Acceptable Use Policy. This goes without saying, your System Administrators will hunt you down and fry you when they find that you're bypassing the content filter or setting a reverse tunnel in order to tunnel back into a server at work. As a System Administrator myself, I take immense pleasure in locating such individuals. At the very least check with your Network/System Administrator so they are not caught off-guard. LinuxJournal.com and myself are not liable for your blatant violations of your corporate policy :-) With that said, let's have some fun shall we?

Creating an SSH tunnel is actually quite easy. Figuring out what to do with it once you have learned how to create a tunnel might be slightly more difficult. So I'll give you a few use cases to get your mind churning before we get into the details of creating a tunnel. I used to travel quite a bit before kids and with a previous IT job. When I traveled I would end up in the strangest of hotel rooms (you know the kind) with even stranger wireless access points. Do you really want to connect to a wireless access point where the SSID of the hotel is missspelled? Or the airport where there appears to be quite a few open WAP's? When I'm out and about I will tunnel my http traffic through ssh on my rooted droid to my home server. If I'm on my laptop/netbook I'll open an ssh tunnel and route http traffic via socks5 so that all of my traffic is encrypted via ssh then back out to me. I wouldn't trust an open WAP as far as I can throw it. What about anything else in plain text? I've tunneled SMTP traffic on my computer back to the house when certain places I've been block outbound SMTP. Same thing goes with pop3 (of which I've recently changed over to imap-s). Other examples of ssh tunneling include X11 applications tunneled via SSH, and VNC sessions. One of the things I brought up earlier is reverse tunneling, which is..well you got it, the reverse of tunneling. In this case you create a tunnel from a server that is behind a firewall with no SSH servers to an SSH server. Then when you log into that SSH server you can re-establish the connection. What good is that you say? Well if your corporate VPN is down, or requires Windows only VPN clients but you really don't want to lug your laptop home to check on a process running when you get home you can reverse tunnel. In this case you would establish a connection from server X to your home machine. Once you arrived at the house you would re-establish the connection to server X, thus bypassing the firewall/VPN and checking on the process without having to establish a VPN connection. I do this very rarely as I feel this is bad juju, bypassing all the rules setup on my firewall and VPN is usually a last resort.

So there are your examples for SSH tunneling, now let's show you how to get 'er done.

Before we get too carried away on the client side of things there are a few things that need to be edited on the server-side of sshd.config. in /etc/ssh/sshd_config I tend to make the following changes. Before you get too carried away, make a copy of /etc/ssh/sshd_config origional file so you have a reference in case something goes horribly wrong. cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig


# Force SSH Protocol 2
Protocol 2

#Turn on Privileged Separation for security
UsePrivilegeSeparation yes

#Deny root login
PermitRootLogin no

#Do not allow empty passwords
PermitEmptyPasswords no

# Forward my X Sessions
X11Forwarding yes
X11DisplayOffset 10

# I hate Motd displays
PrintMotd no

# It's alliivee
TCPKeepAlive yes

Don't forget if you do make any changes to your sshd_config file, you need to restart your sshd service in order to make the necessary changes.

All right, lets get into switches. No no, not the switches your 'pa made you pull off the tree branch when you broke ma's favorite vase, SSH switches.

A typical SSH tunnel (without tunneling X) looks like this:


ssh -N -p 22 bob@mylinuxserver.xxx -L 2110:localhost:110
Where:
-N
= Do not execute a remote command
-p 22
= External SSH port 22. I tend to use other external SSH ports to keep skript kiddies from hitting my home SSH server
bob@mylinuxserver.xxx
= username@hostname(or ip address)
-L 2110/localhost/110
= Bind information. Broken down as such: client-port:hostname:hostport - In this example your binding POP3 on the server to your localhost port 2110

So how about some examples?

Forward pop3 and smtp through SSH:


ssh -N -p 2022 bob@mylinuxserver.xxx -L 2110:localhost:110 -L 2025:localhost:25

Forward google Talk through SSH:
(-g Allows remote hosts to connect to local forwarding ports)


ssh -g -p 2022 -N bob@mylinuxserver.xxx 5223:talk.google.com:5223 

Basically anything that is sent in plain-text can be secured via SSH tunneling. Once you have established the tunnel, on the client-side you would configure your settings for the hostname as localhost and the port as your 'client-port', be it 2110,2020,5223, or any other port that you have selected to forward through.

Encrypt your HTTP Traffic

This is another one that goes without saying. If you work for a company that has an 'IT Acceptable Use Policy' check before you do this. This is one that I use whenever I'm out of town or in a place that I don't trust the wifi. On an android I'll use my SSHTunnel app, but if I'm on my laptop I use the following SSH command

ssh -D 5222 bob@mylinuxserver.xxx -N

After you make a connection, then set your browser of choice (or any application that allows proxy) to localhost:5222. This will create a dynamic port forward and tunnel all the application traffic through your SSH server, both encrypting your data and bypassing content filters.

Tunneling X and VNC Sessions

Remember when you added 'X11Forwarding yes' to your sshd_config? This is where tunneling X comes in.

ssh -X -p 2022 bob@mylinuxserver.xxx

You guessed it, -X tunnels X. Remember though, this will tunnel X apps from your remote machine to your client machine running Linux. If you somehow find you're on a Microsoft Windows machine and want to tunnel, just install Cygwin/X (http://x.cygwin.com/) on your guest OS. I haven't personally tried this but from what I understand it gives you an X windowing system that should allow you to run your remote X apps in Windows.

When it comes to tunneling VNC sessions, you have to be careful. If the client you're tunneling from has a vnc server running on say 5900, make sure you don't decide to put your local forwarding port at 5900 or you will just connect right back to yourself. Connecting via VNC is as straight forward as any of the other services:

ssh -p 2022 bob@mylinuxserver.xxx -L 5900:localhost:5900

In this example your connecting to ssh external port 2022 as user bob to mylinuxserver.com. Your local forwarding port is 5900, the port you want to forward is mylinxuserver.com's 5900 vnc. Once you setup the forward you can open up your vnc client of choice and type: localhost:0 at which point you should be connected via vnc to your remote desktop. If you used 5901, then it would be localhost:1, and so on and so forth.

Reverse SSH Tunnels

Oh yes it's time for my favorite part of SSH tunneling. Sure, getting access to a service from behind SSH is nice, so is tunneling your web traffic through encrypted SSH tunnels. But the real surprise comes when you can reverse the tunnel. As I've outlined earlier, a reverse tunnel is when you are behind a firewall that has no SSH server, but need to access it at a later date (be it minutes/hours/days later) but don't want or have the ability to VPN in. You would connect to your SSH server from that machine, then reverse the tunnel by connecting to that open connection. What do I use it for? From time to time against a server, or even with friends and family with reverse VNC sessions via SSH tunnels. In this case they execute a putty saved session that logs into my ssh server as a certain user with no rights. Once the tunnel is established, I can vnc to their machine in order to remote to them. No more having them setup their firewall, or figure out log-me-in, or any of those other websites.

So the steps to create a reverse SSH tunnel are as follows:

  1. From client machine: ssh -R remoteport:localhost:22 username@servername
    ex: ssh -R 2048:localhost:22 bob@mylinuxserver.xxx
  2. From server side (to re-establish the tunnel): ssh -p 2048 localhost

And there you have it, a reverse tunnel. Yay!

For you visual learners out there, daddoo and nerdboy4200 from #linuxjournal got together and whipped up a message sequence chart using mscgen (http://www.mcternan.me.uk/mscgen/). Yes it's opensource, and really awesome. I tried my hand at creating the mscgen chart for this article but what daddoo and nerdboy did in just a few short hours put my little image to shame.

Conclusion

An there you have it, a primer to SSH tunneling. Keep in mind that this was just a primer, what you can do with tunneling is limited only by your imagination. Later on I'll go over setting up ssh_config on the client side so that all of these settings that I have described above can be saved as individual settings on your client-side ssh. But that's a post for another time.

Load Disqus comments