Ssh – http reverse-proxy on one server passing through ssh/socks proxy to second server

http-proxyreverse-proxysocksssh

There are some web sites that I can only access from a limited set of machines, but I can ssh into some of these machines (only as a regular user) and use ssh -D to set up a SOCKS proxy on my local machine, through which I can access the sites.

What I'd prefer, however, is to be able to go to http://server.that.i.control/some_path/ (secured in some fashion) and have it be a reverse-proxy through ssh -D or something similar on server.that.i.control.

Is this doable, preferably with apache or lighttpd on server.that.i.control?

Best Answer

I don't know of a way for apache or lighttpd to use a SOCKS proxy, but I think this is still doable with just ssh and a web server.

There are three servers.

  1. your.server
  2. gateway.server
  3. web.server

your.server cannot access websites on web.server or ssh to web.server. From your.server you can ssh to gateway.server. From gateway.server you can access websites on web.server.

First, set up ssh such that when a previously unused port (say, 3000) is accessed the traffic is sent via ssh to gateway.server and then via a normal connection to port 80 (or whatever the relevant port is) on web.server.

[your.server]$ ssh -fnL 3000:web.server:80 gateway.server

Second, configure the proxy in apache.

<VirtualHost *:80>
    ServerName your.server
    ProxyPass /some_path http://localhost:3000
    ProxyPassReverse /some_path http://localhost:3000
    ProxyPassReverseCookieDomain web.server your.server
    ProxyPassReverseCookiePath / /some_path
</VirtualHost>

Now, you should be able to access http://your.server/some_path and get content from http://web.server. You may be done, or another step may be necessary.

The potential flaw in this setup is that the Host header will be set to localhost when apache on your.server connects to web.server. If web.server host multiple sites and uses the Host header to decide what site to return, this won't work. I don't know of a way to have apache's mod_proxy change the Host header to something that isn't either the host that the request was made to (your.server) or the host of the backend server (which thanks to our ssh tunnel is localhost). A hack to work around this would be to edit the hosts file on your.server so that the domain names for the sites on web.server actually point to your.server. Let's say there are two sites you want to access, site1.web.server and site2.web.server. In /etc/hosts you would put

127.0.0.1 site1.web.server site2.web.server

and your apache configuration would change to

<VirtualHost *:80>
    ServerName your.server

    ProxyPass /some_path http://site1.web.server:3000
    ProxyPassReverse /some_path http://site1.web.server:3000
    ProxyPassReverseCookieDomain site1.web.server your.server
    ProxyPassReverseCookiePath / /some_path

    ProxyPass /another_path http://site2.web.server:3000
    ProxyPassReverse /another_path http://site2.web.server:3000
    ProxyPassReverseCookieDomain site2.web.server your.server
    ProxyPassReverseCookiePath / /another_path
</VirtualHost>

To secure access to your reverse proxy, look at Apache's authentication howto.

Related Topic