3

In the following setup:

Client -> LB -> Varnish

I would like to configure Varnish acls to take certain action based on the Client's IP. The LB sends the client's IP in a variable called "ClientIP", which Varnish can read via req.httpd.ClientIP. I tried this:

acl admin_net {
  "10.10.1.160"/27;
}

sub vcl_deliever {
  if (req.http.ClientIP ~ admin_net) {
  // do something ... 
  }  
}

but the VCL compilation fails with "Expected CSTR got 'admin_net'" (C String?). I can work around this by req.http.ClientIP ~ "10.10.1.*"), but I have to comment out the ACL lines.

Is there another way to get this working with ACLs? I looked at client.ip as well, which is a read-only variable. In the above setup, it contains the LB's IP and not the Client's IP.

4 Answers 4

4

Actually Varnish handles client.ip as a different data type and so you can use ACLs against this value. This doesn't work with text values like req.http.ClientIP (or all req.http.* parameters). So a regex with this text value seems to be a good solution.

Alternatively you can use a specific module to set client.ip. I found this for example: http://lassekarstensen.wordpress.com/2013/07/22/setting-client-ip-in-varnish-vcl-with-libvmod-ipcast/

2
  • Thanks Jens, do you have an example of this regex?
    – KM.
    May 24, 2014 at 11:23
  • 1
    if (req.http.ClientIP ~ "^10\.10\.1\.1([6-8][0-9]|90)$") { ... } May 25, 2014 at 11:18
5

This can be done using std.ip, assuming ClientIP header is already set in vcl_recv(). For example:

vcl 4.0;
import std;

acl admin_net {
  "10.10.1.160/27";
}

sub vcl_deliver {
  if (std.ip(req.http.ClientIP,"0.0.0.0") ~ admin_net) {
  // do something ... 
  }  
}
2

The answer from alexus is actually the right answer if your Loadbalancer supports the "PROXY"-protocol as outlined here: https://info.varnish-software.com/blog/topic/proxy-protocol

With the PROXY protocol your Loadbalancer will inform Varnish of the real client ip address and set client.ip accordingly.

Alexus' code works:

acl e410 {
    "5.9.0.0"/16;
}

sub vcl_recv {
    ...
    if (client.ip ~ e410) {
        error 410;
    }
    ...
}

The above code example will do exactly what you want. Loadbalancers which support the PROXY protocol include:

  • HA-proxy
  • NginX
  • Apache HTTPD
  • Amazon's Elastic Load Balancer

.. just to name a few. Here is a more complete list: https://www.haproxy.com/blog/haproxy/proxy-protocol/

1
  • Unfortunately Amazon's Application Load Balancer does not support the Proxy Protocol as it's running on L4 (TCP) and and Application Load Balancer only works on L7. The Classic ELBs instead supports the Proxy Protocol.
    – benedikt
    Jul 3, 2020 at 9:21
-1

following is how I implement acl in my varnish:

acl e410 {
    "5.9.0.0"/16;
}

sub vcl_recv {
    ...
    if (client.ip ~ e410) {
        error 410;
    }
    ...
}

try looking inside of varnishlog and post output, it'll be easier to figure out what's wrong...

1
  • As noted at the end of my question, client.ip has the IP of the Load Balancer, not the Client, so I don't see how this helps. Could you please elaborate?
    – KM.
    May 23, 2014 at 19:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .