Perform health checks without PROXY protocol to Squid?

I am using HAProxy 1.8 to balance in TCP mode between two or more Squid 4.7 servers.

To see the source IP of the clients in squid I set up:
http_port 3128 require-proxy-header
acl localnet src 192.168.20.1-192.168.20.254
proxy_protocol_access allow localnet
http_access allow localnet

And in HAProxy I set up:
defaults
global log
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000

frontend squid_in
bind *:3128
default_backend squid_pool

backend squid_pool
balance source
mode tcp
server proxy1 x.x.x.1:3128 check send-proxy inter 2000 rise 2 fall 3
server proxy2 x.x.x.2:3128 check send-proxy inter 2000 rise 2 fall 3

That’s the way it works for me. I can also see the IP origin of the clients in squid.

But the problem I have is that the HAProxy health checks leave me too many error messages in the squid log:

x.x.x.x NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -

According to the documentation I understand that I need to configure my backend health checks so that they do not use the PROXY protocol.

But I don’t understand how to configure it.
Can someone who is more knowledgeable give me an idea of how to do it?
Thank you in advance for your help.

Best regards

Gabriel

Instead of disabling the PROXY protocol in health checks - which I’m not sure will fix those errors, I suggest you actually make a HTTP request, like OPTIONS or something like that, so that the health is a real PROXY + HTTP request.

Refer to option httpchk in the docs.

Just to clarify, I want to continue using tcp mode in my backend because I consider it more performing.
That said, I made these changes:

backend squid_pool
balance source
mode tcp
server proxy1 x.x.x.1:3128 check port 8080 send-proxy inter 2000 rise 2 fall 3
server proxy2 x.x.x.2:3128 check port 8080 send-proxy inter 2000 rise 2 fall 3

And in squid.conf add a line:

http_port 8080 # Port for health check only

In this way I make squid receive connections in an X port that I use only to check that it is running.
Do you think this is a good idea?
Thanks in advance.
Gabriel

I know; but doing HTTP requests for health checks does not mean you need to switch from TCP to HTTP mode.

Using a proper HTTP request following a PROXY header is what your real production traffic looks like, which is why I’d recommend doing the same for the health check.

I would have gone with my recommendation, because it’s simpler and matches what your production traffic looks like. What if someone accidentally closes port 3128 on the server? Health checks won’t detect it.

Now the question is, does that actually resolve your issue? Because squid won’t see any HTTP request here either, which was what this log line was about.

If you just want to disable the proxy protocol in health checks, I would have just configured the same port as a health-check port (server proxy1 x.x.x.1:3128 check port 3128 send-proxy inter 2000 rise 2 fall 3), but even in this case, I’m unsure if squid actually is happy about such a request.

I would have gone with my recommendation, because it’s simpler and matches what your production traffic looks like. What if someone accidentally closes port 3128 on the server? Health checks won’t detect it.

This isn’t gonna happen, but I get the point.

Now the question is, does that actually resolve your issue? Because squid won’t see any HTTP request here either, which was what this log line was about.

Yes, because Squid configured port 8080 without requiring the PROXY protocol. So health states do not show any error in the Squid log.

If you just want to disable the proxy protocol in health checks, I would have just configured the same port as a health-check port ( server proxy1 x.x.x.1:3128 check port 3128 send-proxy inter 2000 rise 2 fall 3 ), but even in this case, I’m unsure if squid actually is happy about such a request.

I’ve tried several ways but without success.
Here are some examples:

option httpchk OPTIONS / HTTP/1.0
server proxy1 x.x.x.1:3128 check send-proxy inter 2000 rise 2 fall 3
Error:
NONE/400 3861 OPTIONS / - HIER_NONE/- text/html

option httpchk OPTIONS / HTTP/1.0
server proxy1 x.x.x.1:3128 check port 3128 send-proxy inter 2000 rise 2 fall 3
Error:
NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -

option httpchk OPTIONS / HTTP/1.0
server proxy1 x.x.x.1:3128 check send-proxy
Error:
NONE/400 3861 OPTIONS / - HIER_NONE/- text/html

Error:
option httpchk OPTIONS / HTTP/1.0
server proxy1 x.x.x.x1:3128 check port 3128 send-proxy
NONE/000 0 NONE error:transaction-end-before-headers - HIER_NONE/- -

As for configuring another identical port, i.e. 3128, without requiring the PROXY protocol, it is not feasible to configure the same port twice in different ways.

Although not optimal, the option of checking the health of the same service but in another port, leaves me the assurance that the service is running and you see I am not filled with errors Squid log.
I would be happy if in the same line where I configure the balancing could send health checks without the PROXY protocol and Squid would accept it. But I don’t know if it’s possible.

Thank you very much for any comments.
Best regards

Gabriel

Sorry for the necro bump…

How did you ever make out with this, I’ve recently moved to haproxy for the same reasons to proxy squid connections… and enabled the proxy protocol to see the users connections in squid… only to find the same

1572550408.021 0 10.20.0.69 NONE_NONE/000 0 - error:transaction-end-before-headers - HIER_NONE/- -

and not finding any way to successfully deal with it other than disabling the checks… which presents other issues…

Slight OT, I did mine with mode http to get features and a balance options…

Thanks in advance

Maybe you can use the tcp-check to forge a HTTP request.
Enforce a “tcp-check connect port 3128” as a first step, so no proxy-protocol header should be sent

According to the docs, server proxy1 x.x.x.x1:3128 check port 3128 send-proxy should actually make haproxy not send the proxy header in the health check. I need to verify whether this is actually the case, or if this is a code or documentation bug.

sorry @bcookatpcsd for the delay
I had left the health checks at another squid port without requiring proxy-header. I had it working well like that for many months. But now I’m going to redesign the proxy system so I started checking this again. And from what I can tell you, initially it looks like the solution @baptiste solves my initial error.

backend squid_pool
    balance source
    mode tcp
    option tcp-check
    tcp-check connect port 3128
    server proxy1 x.x.x.1:3128 check send-proxy inter 2000 rise 2 fall 3
    server proxy2 x.x.x.2:3128 check send-proxy inter 2000 rise 2 fall 3

Unfortunately I could never get health checks to work with option httpchk

Best regards,
Gabriel

How I’d do it: External health check script that uses cURL to make a request through the proxy server using proxy protocol.