-1

@varnishcache HELP! How do I route client traffic based on client source IP address?

N.B: I have install two varnish-cache servers in two different data center.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
janbegjan
  • 1
  • 1

1 Answers1

0

As a point of reference I'd like you to look at https://www.varnish-software.com/developers/tutorials/multiple-backends/. This is a tutorial that explains how to use multiple backends.

If your goal is to have a "sticky IP" strategy, you could use some VCL code like the example below:

vcl 4.1;

import directors;

backend backend1 {
    .host = "backend1.example.com";
    .port = "80";
}

backend backend2 {
    .host = "backend2.example.com";
    .port = "80";
}

backend backend3 {
    .host = "backend3.example.com";
    .port = "80";
}

sub vcl_init {
    new vdir = directors.hash();
    vdir.add_backend(backend1);
    vdir.add_backend(backend2);
    vdir.add_backend(backend3);    
}

sub vcl_recv {
    set req.backend_hint = vdir.backend(client.ip);
}

In this case you'll create a hash based on the client.ip value and route traffic to the backend based on that hash. Every request by the IP address will end up on the same backend.

Watch out with TLS termination

It's important that the client.ip value contains the right value. If you're running a TLS proxy in front of Varnish the client.ip value will always be the one of the TLS proxy, unless you leverage the PROXY protocol.

If you're not using the PROXY protocol, you may want to consider using req.http.X-Forwarded-For as the value to hash on, because that header will contain the IP addresses of the actual client (and potentially other proxies in between).

UPDATE

Based on extra comments and a detailed specification of requirements, here's a new VCL file.

vcl 4.1;

import std;

probe health {
    .url = "/";
    .timeout = 2s;
    .interval = 5s;
    .window = 10;
    .threshold = 5;
}

backend cdn1 {
    .host = "cdn1.example.com";
    .port = "80";
    .probe = health;
}

backend cdn2 {
    .host = "cdn2.example.com";
    .port = "80";
    .probe = health;
}

backend origin {
    .host = "origin.example.com";
    .port = "80";
    .probe = health;
}

acl cdn2_acl {
    "12.13.14/24";
}

sub vcl_recv {
    set req.grace = 10s;
    if(std.ip(req.http.X-Forwarded-For,"0.0.0.0") ~ cdn2_acl) {
        set req.backend_hint = cdn2;
    } elseif(std.healthy(cdn1)) {
        set req.backend_hint = cdn1;
    } else {
        set req.backend_hint = origin;
        set req.grace = 24h;
    }

}

sub vcl_backend_response {
    set beresp.grace = 24h;
}

Summary of what this VCL file does:

  • If the value of the X-Forwarded-For header matches an IP address that is defined in the cdn2_acl ACL, route the traffic to the cdn2 backend
  • If the value of the X-Forwarded-For header doesn't match the ACL, try to route traffic to the cdn1 backend
  • If the cdn1 backend is healthy, serve content from cdn1
  • If the cdn1 backend is unhealthy, directly connect to the origin backend and ramp the grace value up to 24h;
  • If any of the CDNs are used, decrease the grace to 10 seconds
Thijs Feryn
  • 3,982
  • 1
  • 5
  • 10
  • Thank you for the valuable information above. I am working on this. Also, How do I select a cache cdn server based on IP prefix (i.e.: /24) to configure as static route? – janbegjan Apr 03 '22 at 04:20
  • How can I choose a caching CDN server based on an IP prefix (for example, /24)? Also, the above works perfectly. I'd like to make the following changes to the vcl file: 1. there will be two cache servers (cdn1 - DC,, cdn2 - DR). as well as one web server (as backend on cdn1) 2. The default scenario would be to serve web contents from DC site, the client will be served from the CDN1 cache; if the cache fails, the client will be served from the CDN1 backend. The request will then be cached in cdn1 for 24 hours (grace) – janbegjan Apr 04 '22 at 07:12
  • 3. For DR site, when request comes, we require capture the client IP address. If the client's IP matches the vcl, the client will be served from the CDN1 cache; if the cache fails, the client will be served from the CDN1 backend. The request will then be cached in cdn1 for 24 hours (grace) and further request will be served from CDN2 cache. Please guide if the above is possible using opensource varnish-cache. – janbegjan Apr 04 '22 at 07:13
  • @janbegjan sorry for the late reply, I wrote a new VCL example that should match your requirements. – Thijs Feryn Apr 07 '22 at 07:58