I have previously talked about speeding up your site by using Squid as a reverse proxy to cache served pages. This is a great thing to do, but presents a problem now that all sites are moving over to HTTPS, since for various technical reasons reverse proxies can’t really handle HTTPS.

These days the standard way of doing this seems to be using Varnish as a cache, and Squid seems to be a little “old hat”, however I have several client estates which were set up before Varnish came on the scene, so I needed a solution I could get up and running very quickly.

Terminating HTTPS

Thankfully, the solution is very similar whatever reverse proxy you’re using. The solution is simple, you need to install something that terminates and handles the HTTPS session before sending it to your proxy. The simplest way to do this is to install NGINX and configure it to handle HTTPS sessions.

1) Disable Apache’s handling of HTTPS (if you’ve got an existing, un-cached, HTTPS server).

2) Install the basic nginx apt-get install nginx-light

3) Configure nginx to forward to your proxy (which you have previously configured to listen on port 80)

server {
        listen 443 ssl;
        server_name www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        location / {
            proxy_pass http://127.0.0.1:80;
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header Host $host;
        }
}

After restarting nginx, you should be able to see https requests coming in on your squid proxy logs.

Gotchas

The biggest gotcha that you’re going to hit is that if you’re checking whether a request is HTTPS in your app (e.g. for automatically forwarding from insecure to secure), you’re not going to be able to use the standard protocol checks. The reason being is that HTTPS is being terminated by nginx, so by the time the session hits your app, it will not be seen as secure!

To perform such a test, you’re instead going to have to check for the X-Forwarded-Proto header instead ($_SERVER['HTTP_X_FORWARDED_PROTO'] in PHP).