Returning your client's IP address using Varnish

published Jan 08, 2022

A straightforward and simple VCL recipe.

Returning your client's IP address using Varnish

Sometimes, services need to know the IP address they are serving from.  Unfortunately, they might be running behind a NAT firewall (in a demilitarized zone), or they might be running while connected to an Internet connection with a dynamic IP address.

There are for sure online services that you can use to obtain your IP address (whatsmyip.org comes to mind), but those are not the kind of services that would treat you kindly if you hammered them with requests, say,  every five minutes.

However, if you have Varnish running in a server you control, you can always serve your client's IP address.  Here is some VCL you can add to your Varnish configuration file:

sub vcl_recv {
// Substitute the host name with your server's host name, or change the condition. if (req.http.Host == "yourhostname.com") { if ( req.url ~ "^/get-my-ip$" ) { return(synth(900)); } } } sub vcl_synth { if (resp.status == 900) { set resp.status = 200; set resp.http.Content-Type = "text/plain";
# See below for the right variable to use here. synthetic(regsub(req.http.X-Forwarded-For, ",.*", "")); return(deliver); } }

With this, any client hitting https://yourhostname.com/get-my-ip would receive their IP address.

As you can see, all we're doing is returning the first value of X-Forwarded-For header to the client, as a plain text file type.  This HTTP header is customarily set by the frontend that terminates SSL in most Varnish configurations (NginX, Caddy, et cetera).

If your Varnish configuration directly serves to clients in the regular HTTP port, and there is no intermediate proxy between the client and your Varnish instance, you would not return to the client regsub(req.http.X-Forwarded-For...) — you would instead directly return the contents of the variable client.ip, without regsub().