Wednesday, March 15, 2006

DynamicForward, Where Have You Been All My Life?

So I just recently discovered the DynamicForward option for openssh, and man, I've gotta tell you, it's just about the coolest thing ever. I've been using ssh to forward specific ports practically forever, but this option starts up a full fledged SOCKS proxy, so you can point Firefox at it and it'll let you do arbitrary HTTP requests through your tunnel, not to mention all the other applications that work with SOCKS proxies.

Just run something like ssh -o 'DynamicForward 1080' and you'll get your SOCKS proxy listening on port 1080 on your local machine.

Now that's cool, but combine it with Firefox's PAC support for dynamically configuring proxies and you're really cooking. You see, the regular proxy settings in Firefox just let you set your proxy and exclude a list of URLs if you're so inclined. That's nice, but what I really want is for a specific set of URLs (say, the internal servers on a remote network accessible only via ssh) to be proxied but everything else should use my direct connection to the internet.

First, we write a PAC file, which is just a text file that contains a single Javascript function:

function FindProxyForURL(url, host)
if (dnsDomainIs(host, "")) {
return "SOCKS localhost:1080; DIRECT";
} else {
return "DIRECT";

Then you stick it up on a web server someplace and set the URL as your Automatic Proxy Configuration URL in your Firefox Connection Settings. From then on every time you try to connect to a host in * it'll go through the proxy (or try to go directly via the internet if the proxy doesn't work), and everything else just uses your local internet connection.

There are a bunch of other interesting and useful functions like dnsDomainIs() that you can make use of in your implementation of FindProxyForURL(), just take a look at the docs.

If you want to confirm that the things you want to go through the proxy are doing so, just start up the ssh tunnel with the -v option and you'll get debug output every time a new proxy connection is established.

I seriously cannot believe that all this functionality was just sitting there in tools I literally use every day and I never knew about it until now. No more screwing around with /etc/hosts and port forwarding for me!