my setup is HAPROXY -> Varnish -> Origin
Haproxy with forwardfor option, forward the client original IP to Varnish:
option forwardfor header X-HEADER-IP
I want that Varnish print an header Remote-IP in the response, so I have defined:
set beresp.http.Remote-IP = bereq.http.X-HEADER-IP;
inside the function vcl_backend_response
When I make the first request with CURL from the Machine1 (IP1) I have a MISS with the correct Remote IP address:
Machine1 (IP1)$ curl -I https://foo.bar
HTTP/2 200
server: nginx
content-type: text/html; charset=utf-8
**remote-ip: IP1**
via: 1.1 varnish (Varnish/6.6)
vary: Accept-Encoding, Cookie, User-Agent
x-varnish-beresp: 200
x-varnsih-cache: MISS
If I make the same request from another machine (located in another network IP2), I receive an HIT but the remote IP is the same of the first request, because (I think) has been cached from Varnish.
Machine2 (IP2)$ curl -I https://foo.bar
HTTP/2 200
server: nginx
content-type: text/html; charset=utf-8
**remote-ip: IP1**
via: 1.1 varnish (Varnish/6.6)
vary: Accept-Encoding, Cookie, User-Agent
x-varnish-beresp: 200
x-varnsih-cache: HIT
I want that the second request gives me an HIT, but I want that inside the Remote-IP header there is the correct IP Address (IP2)
How can I do?
Thanks in advance
2
Answers
Thanks to Thijs Feryn answer I've solved! I've followed the suggestion to use X-Forwarded-For and I've also enabled the Proxy Protocol in HAProxy and Varnish. So they now are working with that feature enabled. But, also using the X-Forwarded-For header instead of the custom one, my problem was the same as I have described.
Instead I have definitely solved the issue when I've moved my code to vcl_deliver function, as suggested in the section Quick & Dirty.
My final goal was to have a cookie __cc with the country code where the IP Address come from.
In this way everything works.
Thanks a lot!
The best way to identify the original client IP address in Varnish is through the conventional
X-Forwarded-For
header, which is automatically set by Varnish.The problem with X-Forwarded-For
The problem that people often experience, is that they have another server in front of Varnish (HaProxy in your case), so the
X-Forwarded-For
value is always the same.PROXY Protocol to the rescue
Varnish supports the PROXY protocol. This protocol extends the TCP/IP packets and stores connection information from the original client IP, regardless of the number of hops the traffic had to go through.
Enabling PROXY protocol support in Varnish
Varnish can listen for incoming PROXY connections if you configure the right listening interface.
Typically you’ll have a Varnish configuration like this one:
You can enable PROXY support by adding the following listening interface:
The complete process would look like this:
With that extra listening interface in place, it’s now a matter of configuring HaProxy
Enabling PROXY protocol in HaProxy
The great thing about HaProxy is that they invented the PROXY protocol. Enabling it is super easy.
Imagine having the following Varnish backend configuration in HaProxy:
It’s just a matter of adding
send-proxy-v2
to the server definition.The end result looks like this:
Problem solved
Once both Varnish & HaProxy communicate over through the PROXY protocol, you can rely on your
X-Forwarded-For
header to always show the original client IP address.Quick & dirty
So that was the best way to configure it. There’s also a quick & dirty way.
Assuming the
X-HEADER-IP
request header is sent by HaProxy and contains the original client IP, you can also use the following VCL snippet to have the remote IP calculated upon every request: