Varnish logged in user to remote server

32 Views Asked by At

On a varnish cache server, I would like to send all logged in traffic to a remote server, while keeping non-logged in users in the same server w/ varnish. Currently, I have nginx web server running together with varnish. Port 80 is open to Varnish, and 8080 is given to nginx.

I've tried something like below, just to split the traffic.

`backend web1 {
    .host = "1.1.1.1";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

   backend web2 {
    .host = "127.0.0.1";
    .port = "8080";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}`

sub vcl_init {
    new balancer = directors.round_robin();
    balancer.add_backend(web1);
    balancer.add_backend(web2);
}

sub vcl_recv {
    set req.backend_hint = balancer.backend();
}`

Web1 is to give traffic to remotely connected server via DHCP, and web2 is for the nginx server running the same server.

and for the logged-in users, I've tried with the suggestion given from this link.

so, if(req.http.Cookie) for 'SESSION_COOKIE', but I think, for my case, this should go to sub vcl_init, instead of sub vcl_recv. (and certainly not round_robin)

From this point, I have no idea how to set it up.

1

There are 1 best solutions below

2
Thijs Feryn On

While you're free to use vmod_directors for loadbalancing, you don't really need it. You can also explicitly assign backends in VCL.

Here's the VCL code I wrote to tackle the issue, based on your example code:

vcl 4.1;

import cookie;

backend web1 {
    .host = "1.1.1.1";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

backend web2 {
    .host = "127.0.0.1";
    .port = "8080";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

sub vcl_recv {
    cookie.parse(req.http.Cookie);
    if(req.http.Authorization || cookie.isset("SESSION_COOKIE")) {
        set req.backend_hint = web1;
    } else {
        set req.backend_hint = web2;
    }
}

My assumption is that logged in users either authorize themselves using the Authorization header, or using the SESSION_COOKIE cookie.

I'm using vmod_cookie to easily access cookie values. If you're on a (relatively) recent version of Varnish, this VMOD should be available.

If an Authorization header is part of the request or there's a SESSION_COOKIE cookie, we send the traffic to the web1 backend, otherwise we send the traffic to the web2 backend.

Of course you probably need to modify the code a bit, but you get the idea, right?