Squid Reverse SSL Proxy With Multiple Sites (on Windows)

I’ve been running my Exchange 2010 OWA site on a non-standard port (default is 443) for a while so that I can run SSL for my personal website (you’re reading it) on the standard port.  My server is hosted at home, and I only have 1 public IP, so unless I (re-)installed everything on a single server, I could only have 1 site running on port 443.

This has been fine, up until yesterday, when I attempted to install Exchange 2010 SP2.  The installation kept failing due to some issue with IIS.  I assumed it was due to the fact that I had moved the OWA site from “Default Site Name” to it’s own site on the same server.  To remedy, I removed the OWA, ECP and ActiveSync virtual directories and re-installed them in the default location on my Exchange box.  After doing this, SP2 installed fine.  However, now I am back at my original problem (2 servers needing incoming traffic on port 443).  I could re-do the custom OWA setup, but what a PITA that’d be to do every time an Exchange update comes out (theoretically).

My solution: Squid!  I fought Squid until the wee hours of the morning before calling it quits and going to bed.  This morning I tried my configuration again, and this time I have success.  The goal, of course, was to have Squid running on a local server and receiving all traffic on port 443, and based on the URL of the incoming request, redirect traffic to the proper server.

First thing you need to do is download Squid.  The Windows binary can be obtained from here: http://squid.acmeconsulting.it/download/dl-squid.html.  After you download it (it’s a zip file), extract it to c:/squid.  By default, Squid expects to be here, so if you place it somewhere else you’ll have a little bit more work to do.  This is my first experience with Squid, and as such I opted to use the stable release for Windows, which is 2.7, Stable8.  Also, since I’m setting up  a reverse proxy using SSL, I downloaded the SSL support version.

My configuration for squid.conf is below (edited to remove any personal information).  This file needs to be located in the squid/etc directory.  By default, there are example files in there for all config files.  You’ll also need to rename cachemgr.conf.default and mime.conf.default to cachemgr.conf and mime.conf, respectively.  I didn’t edit any settings within those files as I was under the impression that the defaults were fine.  There’s a 4th file in there that doesn’t even need to be configured or renamed for this setup.

The first section here is setting the cache directory (if you opt not to use the default).  Please note: the default location is c:/squid/var/cache, however, if you simply extracted the Squid Windows binary zip to c:/squid, the /var/cache directory does not exist and will cause an error.  Please create that directory (or whatever directory you specify below). Also, ensure that when typing directory paths you use the "/" slash instead of the normal Windows "\" slash.

#Set Cache Directory
cache_dir ufs c:/path/to/cache_dir 100 16 256

This next section is specifying that we want HTTPS to run on port 443 and accelerate (cache) reverse requests. Then it points to the SSL certificate and the corresponding private key. I installed a non-password protected key, as I found that Squid would hang when starting if the key was protected (makes sense). The last part, "vhost", tells Squid that there are multiple sites. I found that without "vhost", my config didn’t work as expected. Also, most documentation I found suggested adding "defaultsite=(url of default site)" to this line. This caused me major headaches, as Squid kept redirecting to the wrong site and I’d get 404 errors when the requested files didn’t exist on the server I was directed to.

#Define Port(s) and Cert(s) (if appropriate)#
https_port 443 accel cert=c:/path/to/cert/cert.crt key=c:/path/to/key/priv.key vhost

Here, we define the sites we are proxying to. "cache_peer" is followed by the internal IP address of the target host. 443 is the port number we’re directing to. "ssl" tells Squid to use SSL. "login=PASS" allows for pass-through authentication (such as when using .htaccess). "name" specifies the name we’ll use to refer to this host within Squid.

#Define Sites#
cache_peer parent 443 0 no-query originserver login=PASS ssl sslflags=DONT_VERIFY_PEER name=wordpress
cache_peer parent 443 0 no-query originserver login=PASS ssl sslflags=DONT_VERIFY_PEER name=exchange

Here we’re configuring some ACLs for our proxy. I chose to add "-acl" to the name of my ACLs just for clarity. The last 2 parts of the first line (and 1 part of the second line) specify the destination URL(s) that the ACL will work for. The last line, "acl all", defines an ACL for all IP addresses. This will be used to deny all traffic access that doesn’t meet our other conditions.

acl wordpress-acl dstdomain site.com www.site.com
acl exchange-acl dstdomain owa.exchange.com
acl all src

Here we’re enabling the ACLs (as before we just defined them). "http_access allow" allows traffic using the specified ACL. My "cache_peer_access" statements seem to be saying the same thing as the "http_access" statements, however, this is what I ended up with after tons of trial and error, so I’m leaving it as-is. Those statements may be redundant and only 1 might be necessary. The last line, "never_direct", was only needed for Exchange OWA. If you’re not hosting OWA, you can probably leave that off.

#Enable ACLs#
http_access allow wordpress-acl
cache_peer_access wordpress allow wordpress-acl
http_access allow exchange-acl
cache_peer_access exchange allow exchange-acl
never_direct allow exchange-acl

Here we’re denying all other requests to access our servers behind the proxy

#Deny all others#
cache_peer_access wordpress deny all
cache_peer_access exchange deny all


And that’s it!  Install Squid as a service (if you haven’t done so already), by using the “squid.exe –i” command.  The squid.exe file is in the squid/sbin/ directory.  If you unzipped Squid to any other directory than c:/squid, you’ll need to add another switch (I think it’s “-f”) to the install command to specify the location of everything.  Documentation for the Windows binary can be found here: http://squid.acmeconsulting.it/Squid27.html.

Please make sure that there are no port conflicts on the host running Squid.  I found that when another program was running on port 443 Squid would hang when started from the Services console.  Also, make sure that you have the necessary firewall ports open.  Then start Squid from the Services console.

Now verify that everything’s working properly.  Squid will create a log file in the same directory as the squid.exe file if there are any errors upon initialization.  After that, logs will be created in the squid/var/logs directory.