HTTPS/SSL Implementation with Varnish Cache Nginx/Apache Stack
Varnish Cache is really, really fast. It typically speeds up delivery with a factor of 300 – 1000x, depending on your architecture. but Varnish Cache cannot deliver website over HTTPS. So here is a solution for that.
Step 1 – Install Hitch and Varnish
Hitch, is a scalable, open source network proxy designed to efficiently handle tens of thousands of connections on multicore machines. We will install and configure hitch to listen on port 443 while Varnish being the backend for the hitch.
Ubuntu Xenial
Update the package metadata and install the required packages:
sudo apt-get update sudo apt-get install hitch varnish
CentOS7 / Red Hat EL7
Install the required packages. In order to get Varnish 4.1 with added support for the PROXY protocol, we add the official Varnish repository first.
sudo yum install epel-release
sudo rpm –nosignature -i https://repo.varnish-cache.org/redhat/varnish-4.1.el7.rpm
sudo yum install hitch varnish
Step 2 – Configure Varnish
We want Varnish to forward all challenge requests to Acmetool, and we are going to create a request matching rule in VCL that will ensure this forwarding happens.
Again open your favourite editor and edit /etc/varnish/default.vcl with the following contents:
# Forward challenge-requests to acmetool, which will listen to port 402
# when issuing lets encrypt requests
backend acmetool {
.host = "127.0.0.1";
.port = "402";
}
sub vcl_recv {
if (req.url ~ "^/.well-known/acme-challenge/") {
set req.backend_hint = acmetool;
return(pass);
}
}
As we will be using Hitch to forward requests, we want Varnish to listen to an additional port (6086) using the PROXY protocol support that was added in Varnish 4.1. (If for some reason you do not want to run Varnish 4.1, you can skip this step, and simply change the port used for Varnish in the hitch config to 6081.)
On Ubuntu Xenial, open the file /lib/systemd/system/varnish.service add -a ‘[::1]:6086,PROXY’ to the ExecStart line. You then need to update systemd by running:
sudo systemctl daemon-reload
In CentOS7 the same option is added by editing /etc/varnish/varnish.params and ensure the DAEMON_OPTS setting includes the following: DAEMON_OPTS=”-a ‘[::1]:6086,PROXY'”
Restart Varnish so that it will listen to the new ports, and use the correct forwarding rule for the challenge requests.
sudo service varnish restart
Step 3 – Install Acmetool
We will now install the Acmetool binaries using the available APT PPA for Ubuntu, and the copr repository for CentOS7.
Ubuntu Xenial
Acmetool is published in a PPA, so we will add this and then install the package:
sudo add-apt-repository ppa:hlandau/rhea
sudo apt-get update
sudo apt-get install acmetool
CentOS7 / Red Hat EL7
Acmetool is available in a copr repository. We will get the repository file and then install the package:
sudo wget –quiet -O /etc/yum.repos.d/hlandau-acmetool-epel-7.repo ‘https://copr.fedorainfracloud.org/coprs/hlandau/acmetool/repo/epel-7/hlandau-acmetool-epel-7.repo‘
sudo yum install acmetool
Step 4 – Acquire the certificate
Now we will use Acmetool to acquire a certificate.
Now we have everything in place and we run the Acmetool quickstart process. It should detect that we are using Hitch and automatically set up a hook that will generate Hitch-compatible certificate-packages from certificate requests.
sudo acmetool quickstart
Answer the prompts like this to enable live certificates authenticated through challenge requests proxied through Varnish.
------------------------- Select ACME Server -----------------------
1) Let's Encrypt (Live) - I want live certificates
----------------- Select Challenge Conveyance Method ---------------
2) PROXY - I'll proxy challenge requests to an HTTP server
Review and (hopefully) accept the letsencrypt.org Terms of Service, and enter your email address.
-------------------- Install HAProxy/Hitch hooks? ------------------
Yes) Do you want to install the HAProxy/Hitch notification hook?
-------------------- Install auto-renewal cronjob? -----------------
Yes) Would you like to install a cronjob to renew certificates automatically? This is recommended.
Before we continue to requesting our certificate we need to generate a Diffie-Hellman group file (aka dhparams), used for perfect forward secrecy.
sudo openssl dhparam -out /var/lib/acme/conf/dhparams 2048
Now we can finally get our certificate:
sudo acmetool want example.com
Step 5 – Configure Hitch
Now we should have our own valid certificate, and we can use it to set up Hitch. As previously mentioned we configured Varnish to listen to an additional port (6086) where it will accept requests using the PROXY protocol.
Use your favorite editor to create the file /etc/hitch/hitch.conf and copy the following contents into it, note the required user/group settings on CentOS/RHEL.
## Basic hitch config for use with Varnish and Acmetool
# Listening
frontend = "[*]:443"
ciphers = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
# Send traffic to the Varnish backend using the PROXY protocol
backend = "[::1]:6086"
write-proxy-v2 = on
# If you run Varnish 4.0 use this instead
#backend = "[::1]:6081"
#write-proxy-v2 = off
# List of PEM files, each with key, certificates and dhparams
pem-file = "/var/lib/acme/live/example.com/haproxy"
# Set uid/gid after binding a socket
# Uncomment these on CentOS/RHEL
#user = "hitch"
#group = "hitch"
Start Hitch with the new configuration:
sudo service hitch start
Step 6 – Set up HTTP to HTTPS Redirection
Add following code to vcl_recv of VCL file
# set x-forwarded-proto header to https if connections comes from Hitch SSL Proxy.
if (std.port(local.ip) == 6086) {
set req.http.X-Forwarded-Proto = "https";
}
# force http://example.com to https://example.com if connections comes from HTTP (Port: 80) Listener.
if ( req.http.host ~ "^(?i)example.com" && req.http.X-Forwarded-Proto !~ "(?i)https") {
set req.http.x-redir = "https://example.com" + req.url;
return(synth(301));
}
Add following code to vcl_synth of VCL file
if (resp.status == 301) {
set resp.http.Location = req.http.x-redir;
return (deliver);
}
Step 7 – Restart Varnish Cache and test
sudo service varnish restart
Access your website with HTTP, now it should be redirected to HTTPS. Contact me in case of any issues.