0

We're using Varnish 3.0.3. Varnish is behind a load balancer.

We would like to bypass the Varnish cache for a particular IP address. After doing research, I found the following. Unfortunately, it is not working.

    acl passem { "7x.xxx.xxx.xxx"; }
    sub vcl_recv {
    if (!(client.ip ~ passem)) {
    return (pass);
            }
    }

This appears in varnishlog "6 VCL_acl c NO_MATCH passem"

I'm not sure what is wrong. The only thing I can think of is Varnish is not seeing the incoming IP address. This is what I see in varnishlog.

    6 RxHeader     c X-Real-IP: "7x.xxx.xxx.xxx"
    6 RxHeader     c X-Forwarded-For: "7x.xxx.xxx.xxx"

    6 SessionOpen  c 10.10.10.4 58143 0.0.0.0:80
    6 ReqStart     c 10.10.10.4 58143 1026834560

The RxHeader is receiving the correct IP and matches the acl passem, but I don't know if acl passemis instead referencing the SessionOpen IP address, which is the IP address of the load balancer.

iPhrankie
  • 51
  • 5

3 Answers3

4

In Varnish, "X-Real-IP" and "http.x-forwarded-for" are strings and "client.ip" is an object.

Extra code is required to copy the IP address from the "X-Forwarded-For" header into Varnish's client_ip structure.

Below is what was required to make it work. This worked successfully. Credit goes to http://zcentric.com/2012/03/16/varnish-acl-with-x-forwarded-for-header/

    C{
    #include <netinet/in.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    }C
    acl passem { "7x.xxx.xxx.xxx"; }
    sub vcl_recv {
    C{
    struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(sp);
    struct sockaddr_in *client_ip_si = (struct sockaddr_in *) client_ip_ss;
    struct in_addr *client_ip_ia = &(client_ip_si->sin_addr);
    char *xff_ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:");

    if (xff_ip != NULL) {
    inet_pton(AF_INET, xff_ip, client_ip_ia);
    }
    }C
    if (!(client.ip ~ passem)) {
    return (pass);
            }
    }
iPhrankie
  • 51
  • 5
  • Hi, any idea how to do the same in Varnish4 ? sp is not defined in Varnish4. I've tried this approac http://jan.bogutzki.de/Artikel/395/set-ttl-in-varnish-4.html but I get a "initialization from incompatible pointer type [-Werror] in struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(ctx); " error probably because the type has also been changed. – SimoneB Mar 11 '20 at 07:53
  • (continue from above) The code I'm trying to use is: `struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(ctx); struct sockaddr_in *client_ip_si = (struct sockaddr_in *) client_ip_ss; struct in_addr *client_ip_ia = &(client_ip_si->sin_addr); const struct gethdr_s hdr = { HDR_REQ, "20X-Forwarded-For:" }; char *xff_ip = VRT_GetHdr(ctx, &hdr);` – SimoneB Mar 11 '20 at 07:56
1

Yes, your client.ip will be the real IP, not anything forwarded in headers. Instead you need to use the correct header req.http.X-Real-IP for instance.

Clarence
  • 2,944
  • 18
  • 16
  • Thanks! It wasn't that easy, but your post certainly pointed me in the right direction to find a solution. – iPhrankie Sep 06 '13 at 20:05
0

In current varnish-cache versions you can use std.ip(), e.g.

import std;

sub vcl_recv {
  if (std.ip(req.http.X-Real-IP) !~ passem) {
    return (pass);
  }
}
Nils Goroll
  • 148
  • 4