January 21, 2009

OpenSSH: The Poor Man's SOCKS Proxy

Just when I think I know everything I need to know about OpenSSH, I end up learning something new and tremendously useful. Today, that would be the -D argument.

Many times I have been stuck on an "untrusted" Internet connection and need to log in (insecurely) to a certain site. My university, for example, uses a system that has no way of logging in via HTTPS, nor does it secure the traffic to and from the browser. I have moderate faith that the folks at my ISP aren't snooping my traffic (since I know the company pretty well and used to work with them), so I don't have a huge problem logging into their site at home. I also have a colocated server at the web hosting company I work for, so I know the layout of their network even better and trust them not to snoop or interfere with my traffic. But when I'm on the road connected to some dodgy insecure hotel wifi, I acquire no small amount of anxiety over the fact that anyone with a packet sniffer can get access to all of my personal and academic details.

For the past few years, I've had this plan to get OpenVPN set up for my network and laptop so that I can always have a secure connection to my home and colocated server. And for the past few years, I've kept putting it off. While OpenVPN is easier to use than many other VPN solutions I could name, it's still at least a good hour of my time getting all the settings right and testing it out.

I was already aware of OpenSSH's -L option which simply forwards a local port through an SSH tunnel to a port on the remote machine. Very handy when you want to connect surely to a site hosted on that server and happen to have a shell account on it. But to do much more than that ranges from the complex to impossible. This is where -D comes in.

The -D arg tells OpenSSH to be a SOCKS proxy. So you simply log in to the endpoint via SSH with the -D arg like:

ssh -D 1234 user@host.example.com

And then tell your web browser to use a SOCKS v5 proxy on localhost at the specified port and bingo, you have a secure connection to your endpoint. In fact, any application with SOCKS support can have its traffic routed through the SSH tunnel via SOCKS. Firefox supports SOCKS just fine, Opera doesn't. Konqueror is supposed to, but judging from the Google responses I got, support might be a little flaky.

The final test was whether I'd be able to use this newfangled (to me) proxy method on my Nokia N800, a device that I browse and email with quite often whilst traveling. Obviously OpenSSH has to be installed as it doesn't come with the firmware. And the N800's web browser, MicroB, uses the Gecko engine. The UI has no widgets for entering a SOCKS proxy, but you can set the preferences manually with about:config:

network.proxy.socks localhost
network.proxy.socks_port 1234
network.proxy.type 1

The result? Portable proxy surfing!

12 comments:

Anonymous said...

You know, you can use ssh for IP-tunneling (eg ip in ip) as well as "ethernet" tunneling. That is about as close to using true IPSec you can get without doing the real thing. Check the -w option.

David Tangye said...

This would be a lot more useful if you explained : Does this allow secure browsing to anywhere, or just to the ip address named after -D? Ie do you use the localhost url in the browser and the ssh tunnel/proxie redirects to the address named after -D? A simple diagram would help a lot. Like many documents, this is understandable to peole who already know the technology, but not to 'outsiders'.

charles said...

You're probably right, David. However, I was in a rush to get the post up there because if I didn't do it right then and there, I probably wouldn't have posted it at all. Yes, I took for granted that the reader understood what OpenSSH did and what a SOCKS proxy is. That was deliberate because I was just writing a blog entry here, not a book. :) Still, the second paragraph gives an example of where ssh -D is useful and I hope this is enough of an illustration for most people.

To answer your question directly, -D is only useful for securing your connection right up to the machine that you're shelling into. After that, the traffic is in the clear. But this is still advantageous when all you're looking to do is keep your traffic away from prying eyes on a potentially hostile local network.

Anonymous said...

If you use Firefox don't forget to set true the setting:
network.proxy.socks_remote_dns
in about:config
to enable DNS through the proxy.
Thanks!

misterfurious said...

Nice tip.
Personally, living in the UK, I've gone for a GPRS modem dongle, as that is encrypted against attacks other than the ISP (and the UK records all traffic logs anyway) so MTM isn't going to happen unless it's the government. And it means I can dodge data charges from pirates in airports, etc. and not have to wardrive for a signal. (Of course, it does cost money!)
However, for access from webcafes or whatever from overseas, I'm going to look into this.

Joe Poniatowski said...

Commenting on an old post, I know, but - Opera now does support socks 5. In a nutshell, you can't do it from the menu, you have to open opera:config to set it up. Easy, step-by-step instructions with screen-shots here: http://hubpages.com/_1qx7t66a8hy2b/hub/How-to-Use-Opera-with-a-SOCKS-Proxy

Anne M. Archibald said...

My use case for this is to make my HTTP requests appear to originate from a work IP address. This is useful because many academic journals decide based on your IP whether you have an institutional subscription.

Tom said...

This solution works really well as long as I establish the SSH connection from my local machine, then have my browser use SOCKS pointing to localhost:1234. However, I am having a darned time trying to configure a shared machine as the proxy, and everytime I try something my browser says the proxy is refusing the connection.
Basically, instead of my browswer using localhost:1234, I want it to use another linux machine on my LAN called "flintstone". I want to run the same SSH commands on flintstone to create the SSH tunnel to an outside server, then have all of my internal browsers have their SOCKS proxy settings as flintstone:1234. I have been trying a few different things (not really knowing what I am doing) and opened the incoming firewall port 1234 on flintstone (so I know that is not the problem).
Any suggestions?

Tom

charles said...

@Tom:

By default, SSH opens the proxy on the localhost address (127.0.0.1) which is an address that only applications on the local machine can access. You'll need to specify flintstone's interface address with the -D flag, or use 0.0.0.0 which will tell it to listen on all IPs on the machine:

ssh -D 0.0.0.0:1234 user@remotehost

Only do this on a network that you completely trust and control. If you're on a company intranet, for example, you're much better off running the proxy on your local machine.

charles said...

@Tom:

By default, SSH opens the proxy on the localhost address (127.0.0.1) which is an address that only applications on the local machine can access. You'll need to specify flintstone's interface address with the -D flag, or use 0.0.0.0 which will tell it to listen on all IPs on the machine:

ssh -D 0.0.0.0:1234 user@remotehost

Only do this on a network that you completely trust and control. If you're on a company intranet, for example, you're much better off running the proxy on your local machine.

Anonymous said...

I receive this error for -D
"Permission denied (publickey)"
What should I do?

charles said...

@Anonymous: When I see that error, it usually means that the server only accepts public key authentication. Can you log in without the -D flag?