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"
```