SSL Redirection and Basic Auth in Varnish

Varnish has proven itself to be quite brilliant and blindingly fast when it comes to caching. Quite recently I was in a situation where varnish was used as a frontend with nginx serving out a webapp and node serving out API services. The requirements for varnish were to honour cache headers churned out by the application, redirect all incoming requests to https and have basic auth in place.

Now varnish doesn't ssl redirect out of the box nor does it have a straight forward way of putting basic auth in place.

In order to handle SSL Redirection, this is the most promising solution I found.
In the vcl_recv segment, right at the beginning put the following condition
sub vcl_recv {
  # SSL redirection
  if ( req.http.host ~ "^(?i)(www\.)?.*(\.<domain>)" && req.http.X-Forwarded-Proto !~ "(?i)https" ) {
    set req.http.x-Redir-Url = "https://" + req.http.host + req.url;
    error 750 req.http.x-Redir-Url;
  }

...
return (lookup);  
}
In the vcl_error segment, define the error and operation
sub vcl_error {
  if (obj.status == 750) {
    set obj.http.Location = obj.response;
    set obj.status = 302;
  }

...
return (deliver);
}
This means any request coming for http://www.<domain> or http://<domain> would be captured under error code 750 and as a part of error handling redirected to the SSL listener with HTTP status 302. Much detailed examples of redirection can be found at Redirect In VCL

The next issue to address is of Basic Auth. There can be a few scenarios to this.

Scenario 1: All incoming requests should pass through Basic Auth.

Generate Base64 Basic Auth via command line.
$ echo -n "user:password" | base64

In the vcl_recv, after the SSL redirection include the following logic
sub vcl_recv {
  if ( req.http.Authorization !~ "Basic dXNlcjpwYXNzd29yZA==" #user:password
  ) {
   error 401 "Restricted";
  }

...
return (lookup);  
}

Scenario 2: All incoming requests except a defined ACL should pass through Basic Auth.

At the beginning of the vcl define an ACL with the host IPs allowed without basic auth.
acl localhost {
  "localhost";
  "127.0.0.1";
}

Modify the vcl_recv as below
sub vcl_recv {
  if ( client.ip !~ localhost && req.http.Authorization !~ "Basic dXNlcjpwYXNzd29yZA==" #user:password
  ) {
   error 401 "Restricted";
  }

...
return (lookup);  
}

Scenario 3: All incoming requests except for a few specific requests should pass through Basic Auth.

sub vcl_recv {
  if ( req.url !~ "/version" && req.http.Authorization !~ "Basic dXNlcjpwYXNzd29yZA==" #user:password
  ) {
   error 401 "Restricted";
  }

...
return (lookup);  
}

Comments

Popular posts from this blog

To DR or Not To DR

High Availability NAT for AWS VPC with Multiple Private Subnets.

Load Balancer with SSL offloading - nginx + HAProxy