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.
#include "urldata.h"
#include "cfilters.h"
#include "cf-haproxy.h"
+#include "curl_addrinfo.h"
#include "curl_trc.h"
#include "select.h"
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;
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
--- /dev/null
+<?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>