I got fascinated by this topic when I messed around with machines that were behind firewalls. It could really be annoying using services on those machines especially if you’re out of the machine’s subnet.
Imagine for example you access a wiki at work. But the problem is, the wiki server only accepts private IPs that are in the work subnet. So if I wanted to work from home, I am kind of doomed. Of course, one way is to setup a VPN service that would accept a remote connection and have access to the wiki. But, not many companies would like to use any of its resources for a VPN service. Also, accessing a VPN in and of itself could be annoying.
Here’s where I started getting attracted to SSH tunnels. SSH stand for Secure Shell, a protocol that allows you to access a server remotely through a console where, unlike Telnet, the communication is actually encrypted. So, this protocol was basically what allowed me to easily access the wiki from home.
I had a computer that had a public IP address at work. I setup an OpenSSH server on it, and added an account that I could log in to. The word tunnel in SSH tunnel refers to the fact that my laptop at home will access the work wiki through the SSH server that I setup on the work machine. So a tunnel will be established between my laptop and my work computer where that will allow me to send (and receive) HTTP data to the work computer. It would be just like I was on my work computer.
I just needed to do the following:
- Install OpenSSH on my work computer
- For firefox install an add-on called FoxyProxy that would allow your browser to direct http requests to the tunnel I will setup.
Setting up a tunnel:
To setup a tunnel, all what needs to be done from a Unix terminal is:
ssh -D8080 [my work computer ip]
According to the man page of the SSH tunnel, this basically opened up a port on my local machine (laptop) for forwarding quoted from the ssh man page:
“Whenever a connection is made to
this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine”
So basically the tunnel is set, now all I need to do is tell Firefox that I would like it to direct some requests to this SSH tunnel.
Righting click on the FoxyProxy icon (lower right of the browser in my case), I clicked on options to add a new proxy. Under the proxy details tab,I simply select the manual proxy configuration where I declare IP as localhost since that is where the first end of the tunnel is located, and the port as the listening port in the tunnel (8080 in my case). Since SSH man page mentions that the ssh protocol will act as a SOCKS server, I specify on FoxyProxy that the main protocol I will be using is SOCKS5.
Foxyproxy also has the option of setting up whitelist or blacklist urls, so that it only uses a proxy when you enter a specific URL. So that way, Firefox knows when to use the proxy. So I basically added my work’s URL followed by an asterisk indicating a wildcard.
Now I am done, as long as the tunnel is open, I can simply open my browser and type the work’s URL, and I have full access to the wiki.
Multiple Tunnels
Ok, that was relatively simple. Now let’s say you want to access a SOAP service in your company that is on an internal IP address.
Imagine the following environment:
- The SOAP service is in an internal subnet (e.g. 192.168.5.0/24)
- you have access to a server A that is in that subnet, but the server also has another network interface eth1 on a different subnet.
- eth1 on Server A can only be accessed through Server B.
- Authorized users have SSH access to Server B from anywhere in the world.
Confusing? yes. Don’t ask me why this configuration exists, sometimes building subnets and firewalls leads to this kind of mess. Nonetheless , I found myself required to open up a public interface to the soap server so that a remote client machine could access it. I decided to set it up on a server that I have control over let’s call it Server C.
So this is what I needed to do:
- Setup a tunnel between Server C and Server B. I’m not allowed to do a lot on server B, but I do have SSH access and I am allowed to ssh from it. So I setup a tunnel between server C and B (call it Tunnel A).
- I use the tunnel in 1 to setup another Tunnel between C and Server A, which I will use to get to the SOAP server.
- I need to make sure that the tunnel I set is open to the outside world so that the remote client could connect to it.
Here are the SSH commands I needed to perform:
ssh -L localhost:2222:[ip-address-of-server-A]:22 [ip-addres-of-server-B]
ssh -L [ip-address-of-server-C]:3333:[IP-address-of-SOAP-service]:80 localhost -p 2222
This way I simply tell the remote client to use the SOAP service by using the IP address of server C port 3333. That will direct the requests through the tunnel to the SOAP server I have in the private subnet.
It might be a good idea to setup security at this stage. One option would be to set iptables on server C that allows access to port 3333 to the client only.
This really summarizes what you can do with SSH: you tie up many servers together and setup one tunnel. Even though the protocol itself is secure it doesn’t mean we can really ignore security. Firewalls need to be set to limit what goes “in” and “out” of the tunnel. After all, an access point (a point that an attacker can exploit) is being opened up, so….make sure the right traffic gets to this access point.
This actually rocks! I’ve never tried SSH tunnels before, but now that i’m on Ubuntu i’ll definitely give this a try.
You mentioned installing OpenSSH on the server: doesn’t that require root access? Is there a way to accomplish this without this
You probably could (not sure why you’d want to though, I’m assuming you’ve got control over your server), you’ll need to set it up on an unprivileged port though so you can use port 22