Ssl – How to Enforce SSL in Varnish 4

sslvarnish

I am aiming to redirect clients to a SSL-version of a site using Varnish. In Varnish 3 this could be done by the following in the VCL:

sub vcl_recv {
    if ( (req.http.host ~ "^(?i)somesite.org" || req.http.host ~ "^(?i)www.somesite.org")
         && req.http.X-Forwarded-Proto !~ "(?i)https") {
        set req.http.x-Redir-Url = "https://www.somesite.org" + req.url;
        error 750 req.http.x-Redir-Url;
    }
}

sub vcl_error {
    if (obj.status == 750) {
        set obj.http.Location = obj.response;
        set obj.status = 302;
        return (deliver);
    }

Between Varnish versions 3 and 4 there were changes to the vcl requirements, these can be found in the varnish docs: https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html#changes-to-vcl.

My attempt at a Varnish 4 version of the redirect leads to a redirect loop. I am not entirely sure if it is this section of the the vcl which is incorrect, or if even the correct implementation would work with my current setup.

Either way, it would be useful to have a confirmed working ?Varnish 4 version of this. My attempt is:

sub vcl_recv {
    if ( (req.http.host ~ "^(?i)somesite.org" || req.http.host ~ "^(?i)www.somesite.org")
         && req.http.X-Forwarded-Proto !~ "(?i)https") {
        set req.http.x-Redir-Url = "https://www.somesite.org" + req.url;
        return (synth(750, req.http.x-Redir-Url));
  }
}

sub vcl_synth {
    if (resp.status == 750) {
        set resp.http.Location = resp.reason;
        set resp.status = 302;
        return (deliver);
    }

Is anyone familiar with this and able to spot if it is correct or incorrect?

Best Answer

Try the following for Varnish 4 while updating the TLD with your respective values:

sub vcl_recv {
        if ( (req.http.host ~ "^(?i)www.domain.com") && req.http.X-Forwarded-Proto !~ "(?i)https") {
                return (synth(750, ""));
        }
}

sub vcl_synth {
    if (resp.status == 750) {
        set resp.status = 301;
        set resp.http.Location = "https://www.domain.com" + req.url;
        return(deliver);
    }
}

You should be able keep the || statement and it should work (not tested):

sub vcl_recv {
        if ( (req.http.host ~ "^(?i)www.domain.com" || req.http.host ~ "^(?i)domain.com") && req.http.X-Forwarded-Proto !~ "(?i)https") {
                return (synth(750, ""));
        }
}
Related Topic