Hi,

Here is a patch fixing an old bug in proxy mode, when you mix valid requests (using an IP) with invalid ones (with a domain name for instance).

With following configuration:

  listen test
      mode http
      bind *:8888
      option http_proxy

try to do:

  $> printf "GET http://pouet.com/ HTTP/1.0\r\n\r\n" | nc 127.0.0.1 8888

You will have a 503 returned by HAProxy, because there is no DNS resolution, as stated in the documentation. Then try:

$> printf "GET http://51.15.8.218 HTTP/1.0\r\nHost: www.haproxy.org\r\n\r\n" | nc 127.0.0.1 8888

You will get a haproxy.org homepage. Then retry the first request. It should return the same error...

  $> printf "GET http://pouet.com/ HTTP/1.0\r\n\r\n" | nc 127.0.0.1 8888

... But, instead you will have a 404 from haproxy.org (because there is no Host header).

With the patches, HAProxy always return an error 400 in this case.

--
Christopher Faulet
>From d1e5d8cb24ad0e71706cf5d4472142a4e048a7f1 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Fri, 13 Apr 2018 15:53:12 +0200
Subject: [PATCH] BUG/MINOR: http: Return an error in proxy mode when url2sa
 fails

In proxy mode, the result of url2sa is never checked. So when the function fails
to resolve the destination server from the URL, we continue. Depending on the
internal state of the connection, we get different behaviours. With a newly
allocated connection, the field <addr.to> is not set. So we will get a HTTP
error. The status code is 503 instead of 400, but it's not really critical. But,
if it's a recycled connection, we will reuse the previous value of <addr.to>,
opening a connection on an unexpected server.

To fix the bug, we return an error when url2sa fails.

This patch should be backported in all version from 1.5.
---
 src/proto_http.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/proto_http.c b/src/proto_http.c
index 80e001d69..8370889b4 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3720,9 +3720,11 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
 		}
 
 		path = http_get_path(txn);
-		url2sa(req->buf->p + msg->sl.rq.u,
-		       path ? path - (req->buf->p + msg->sl.rq.u) : msg->sl.rq.u_l,
-		       &conn->addr.to, NULL);
+		if (url2sa(req->buf->p + msg->sl.rq.u,
+			   path ? path - (req->buf->p + msg->sl.rq.u) : msg->sl.rq.u_l,
+			   &conn->addr.to, NULL) == -1)
+			goto return_bad_req;
+
 		/* if the path was found, we have to remove everything between
 		 * req->buf->p + msg->sl.rq.u and path (excluded). If it was not
 		 * found, we need to replace from req->buf->p + msg->sl.rq.u for
-- 
2.14.3

Reply via email to