haproxy: use correct ip version on client supplied address
No binary (build failed)
—
(log yok)
| @@ -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. | |
| @@ -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 | |
| @@ -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 \ | |
| \ | |
| @@ -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 | |
| @@ -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 | |
| @@ -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> |