haproxy: use correct ip version on client supplied address

When a user supplies an IP address to use for the HAPROXY protocol,
the IP version reported must be deduced from the address and has
no relation to the IP version used for the upstream connection.

Add test3220 to verify.

Fixes #21340
Reported-by: Fiona Klute
Closes #21341
This commit is contained in:
Stefan Eissing 2026-04-16 13:44:13 +02:00 committed by Daniel Stenberg
parent 021a87cf81
commit 70281e39be
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
6 changed files with 86 additions and 10 deletions

View file

@ -28,6 +28,7 @@
#include "urldata.h"
#include "cfilters.h"
#include "cf-haproxy.h"
#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "select.h"
@ -61,9 +62,16 @@ static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
/* We fake a client connection report to the upstream server
* with the HAProxy protocol, reporting the client's source
* and destination IP addresses and ports.
* addresses: either the ones used to talk to the upstream
* OR the value supplied by the user
* ports: the ports used in the upstream connection */
const char *client_source_ip;
const char *client_dest_ip;
struct cf_haproxy_ctx *ctx = cf->ctx;
CURLcode result;
const char *client_ip;
struct ip_quadruple ipquad;
bool is_ipv6;
@ -79,15 +87,19 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf,
if(result)
return result;
/* Emit the correct prefix for IPv6 */
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
else
client_ip = ipquad.local_ip;
if(data->set.str[STRING_HAPROXY_CLIENT_IP]) {
client_source_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
client_dest_ip = client_source_ip;
is_ipv6 = !Curl_is_ipv4addr(client_source_ip);
}
else {
client_source_ip = ipquad.local_ip;
client_dest_ip = ipquad.remote_ip;
}
result = curlx_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
is_ipv6 ? "TCP6" : "TCP4",
client_ip, ipquad.remote_ip,
client_source_ip, client_dest_ip,
ipquad.local_port, ipquad.remote_port);
#ifdef USE_UNIX_SOCKETS