A typical proxy purge rule looks like this: ```vcl acl purge { 'localhost'; '127.0.0.1'; '::1'; } sub vcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge) { return(synth(405, "Not allowed")); } ... } } ``` The problem is that when behind any other local server (Nginx, load balancer), the client IP will `127.0.0.1` (or, more specifically, the IP of the server fronting it). There are three solutions to this. # 1. Use the PROXY Protocol If the fronting server supports the PROXY Protocol, the right headers will be set, allowing the above to work. This requires launching the server in the following way: ``` $ varnishd -a :6081,PROXY ... ``` This requires that the fronting server supports this protocol. Here's how to enable this with [[Nginx]]: ``` stream { server { listen 80; proxy_pass 127.0.0.1:6081; proxy_protocol on; } } ``` # 2. Use `X-Forwarded-For` The above rule becomes: ``` if (!std.ip(req.http.X-Forwarded-For, "0.0.0.0") ~ purge) { ... } ``` This should be safe provided the fronting server sets headers correctly. # 3. Use a Dedicated Port This can ensure that only those with access to the port can perform a `PURGE` request. Add the port to the command line: ``` $ varnishd -a :6081 -a :6091 ... ``` ```vcl import std; sub vcl_recv { if (req.method == "PURGE") { if (std.port(server.ip) == 6091) { return (purge); } else { return (synth(403)); } } } ``` # Other Resources ```embed title: "Purge and proxies, a love-hate affair" image: "https://info.varnish-software.com/hubfs/var.png" description: "We explore a classic purging mistake and potential solutions" url: "https://info.varnish-software.com/blog/failure-to-purge-a-story-about-client.ip-and-proxies" ```