Absolutely; the Varnish handling of X-Forwarded-For
is actually just defined in the default vcl_recv
function.
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
The default definition of a function is always appended to one you've defined in your active VCL file, but if your defined function always handles a request, then the default logic will never execute.
Set a vcl_recv
along these lines:
sub vcl_recv {
/* Your existing logic goes here */
/* After that, we'll insert the default logic, with the X-Forwarded-For handling removed */
/* The return (lookup); at the end ensures that the default append behavior won't have an impact */
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
return (lookup);
}
Edit:
Since Varnish handles some connections directly as well, a better approach might be to have it selectively set the header. You'll still want include the full vcl_recv
so that the default doesn't apply its own header, but include this at the top:
if (req.restarts == 0) {
if (!req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = client.ip;
}
}