← Commit list

70281e39be

Stefan Eissing
Stefan Eissing
2026-04-17
SUCCESS Duration: 261s

Subject

haproxy: use correct ip version on client supplied address

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md+3 -0
@@ -31,6 +31,9 @@ When this parameter is set to a valid IPv4 or IPv6 numerical address in its
printable ASCII string version, the library sends this as the client address
in the HAProxy PROXY protocol v1 header at beginning of the connection.
+The client address is reported upstream as the source *and* destination address
+of the non-existing client connection (since 8.20.0).
+
This option is an alternative to CURLOPT_HAPROXYPROTOCOL(3) as that one cannot
use a specified address.
lib/cf-haproxy.c+19 -7
@@ -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
tests/data/Makefile.am+1 -1
@@ -283,7 +283,7 @@ test3100 test3101 test3102 test3103 test3104 test3105 \
\
test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 \
test3208 test3209 test3210 test3211 test3212 test3213 test3214 test3215 \
-test3216 test3217 test3218 test3219 \
+test3216 test3217 test3218 test3219 test3220 \
\
test3300 test3301 \
\
tests/data/test3201+1 -1
@@ -46,7 +46,7 @@ proxy
# Verify data after the test has been "shot"
<verify>
<strippart>
-s/^PROXY TCP4 192.168.1.1 %HOSTIP (\d*) %HTTPPORT/proxy-line/
+s/^PROXY TCP4 192.168.1.1 192.168.1.1 (\d*) %HTTPPORT/proxy-line/
</strippart>
<protocol crlf="yes">
proxy-line
tests/data/test3202+1 -1
@@ -51,7 +51,7 @@ proxy
# Strip off the (random) local port number. This test used to use a fixed
# local port number that frequently causes the test to fail
<strippart>
-s/^PROXY TCP6 2001:db8:: ::1 (\d*) %HTTP6PORT/proxy-line/
+s/^PROXY TCP6 2001:db8:: 2001:db8:: (\d*) %HTTP6PORT/proxy-line/
</strippart>
<protocol crlf="yes">
proxy-line
tests/data/test3220+61 -0
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+proxy
+haproxy
+</keywords>
+</info>
+
+# Server-side
+<reply name="%TESTNUMBER">
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: barkbark
+
+-foo-
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP GET when PROXY Protocol enabled and spoofed client IP
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --haproxy-clientip "2a04:4e42::347" -H "Testno: %TESTNUMBER"
+</command>
+<features>
+proxy
+</features>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^PROXY TCP6 2a04:4e42::347 2a04:4e42::347 (\d*) %HTTPPORT/proxy-line/
+</strippart>
+<protocol crlf="yes">
+proxy-line
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Testno: %TESTNUMBER
+
+</protocol>
+</verify>
+</testcase>