From: Stefan Eissing Date: Fri, 8 Sep 2023 13:23:00 +0000 (+0000) Subject: Merge of /httpd/httpd/trunk:r1912180 X-Git-Tag: 2.4.58-rc1-candidate~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7f0c6d189765174dc61df35954ed5dcd9ec4733;p=thirdparty%2Fapache%2Fhttpd.git Merge of /httpd/httpd/trunk:r1912180 *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value. Fixes PR66752. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1912194 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/STATUS b/STATUS index c5a7e0da70b..4fd90979937 100644 --- a/STATUS +++ b/STATUS @@ -206,14 +206,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK: svn merge -c 1912015 ^/httpd/httpd/trunk . +1: rjung, gbechis - *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value. - Fixes PR66752. - Trunk version of patch: - https://svn.apache.org/r1912180 - Backport version for 2.4.x of patch: - svn merge -c 1912180 ^/httpd/httpd/trunk . - +1: icing, - PATCHES/ISSUES THAT ARE BEING WORKED [ New entries should be added at the START of the list ] diff --git a/changes-entries/h2_proxy_forwarded_host.txt b/changes-entries/h2_proxy_forwarded_host.txt new file mode 100644 index 00000000000..338935337e7 --- /dev/null +++ b/changes-entries/h2_proxy_forwarded_host.txt @@ -0,0 +1,4 @@ + *) mod_proxy_http2: fix `X-Forward-Host` header to carry the correct value. + Fixes PR66752. + [Stefan Eissing] + diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c index 8a5c591ab82..db223012766 100644 --- a/modules/http2/h2_proxy_session.c +++ b/modules/http2/h2_proxy_session.c @@ -818,7 +818,7 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, { h2_proxy_stream *stream; apr_uri_t puri; - const char *authority, *scheme, *path; + const char *authority, *scheme, *path, *orig_host; apr_status_t status; proxy_dir_conf *dconf; @@ -842,13 +842,14 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, return status; scheme = (strcmp(puri.scheme, "h2")? "http" : "https"); - + orig_host = apr_table_get(r->headers_in, "Host"); + if (orig_host == NULL) { + orig_host = r->hostname; + } + dconf = ap_get_module_config(r->per_dir_config, &proxy_module); if (dconf->preserve_host) { - authority = apr_table_get(r->headers_in, "Host"); - if (authority == NULL) { - authority = r->hostname; - } + authority = orig_host; } else { authority = puri.hostname; @@ -878,8 +879,6 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, if (dconf->add_forwarded_headers) { if (PROXYREQ_REVERSE == r->proxyreq) { - const char *buf; - /* Add X-Forwarded-For: so that the upstream has a chance to * determine, where the original request came from. */ @@ -889,8 +888,9 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url, /* Add X-Forwarded-Host: so that upstream knows what the * original request hostname was. */ - if ((buf = apr_table_get(r->headers_in, "Host"))) { - apr_table_mergen(stream->req->headers, "X-Forwarded-Host", buf); + if (orig_host) { + apr_table_mergen(stream->req->headers, "X-Forwarded-Host", + orig_host); } /* Add X-Forwarded-Server: so that upstream knows what the diff --git a/test/modules/http2/htdocs/cgi/hello.py b/test/modules/http2/htdocs/cgi/hello.py index 20974bfdd3f..a96da8aafb1 100644 --- a/test/modules/http2/htdocs/cgi/hello.py +++ b/test/modules/http2/htdocs/cgi/hello.py @@ -1,20 +1,25 @@ #!/usr/bin/env python3 import os +import json + +resp = { + 'https': os.getenv('HTTPS', ''), + 'host': os.getenv('X_HOST', '') if 'X_HOST' in os.environ else os.getenv('SERVER_NAME', ''), + 'server': os.getenv('SERVER_NAME', ''), + 'h2_original_host': os.getenv('H2_ORIGINAL_HOST', ''), + 'port': os.getenv('SERVER_PORT', ''), + 'protocol': os.getenv('SERVER_PROTOCOL', ''), + 'ssl_protocol': os.getenv('SSL_PROTOCOL', ''), + 'h2': os.getenv('HTTP2', ''), + 'h2push': os.getenv('H2PUSH', ''), + 'h2_stream_id': os.getenv('H2_STREAM_ID', ''), + 'x-forwarded-for': os.getenv('HTTP_X_FORWARDED_FOR', ''), + 'x-forwarded-host': os.getenv('HTTP_X_FORWARDED_HOST', ''), + 'x-forwarded-server': os.getenv('HTTP_X_FORWARDED_SERVER', ''), +} print("Content-Type: application/json") print() -print("{") -print(" \"https\" : \"%s\"," % (os.getenv('HTTPS', ''))) -print(" \"host\" : \"%s\"," % (os.getenv('X_HOST', '') \ - if 'X_HOST' in os.environ else os.getenv('SERVER_NAME', ''))) -print(" \"server\" : \"%s\"," % (os.getenv('SERVER_NAME', ''))) -print(" \"h2_original_host\" : \"%s\"," % (os.getenv('H2_ORIGINAL_HOST', ''))) -print(" \"port\" : \"%s\"," % (os.getenv('SERVER_PORT', ''))) -print(" \"protocol\" : \"%s\"," % (os.getenv('SERVER_PROTOCOL', ''))) -print(" \"ssl_protocol\" : \"%s\"," % (os.getenv('SSL_PROTOCOL', ''))) -print(" \"h2\" : \"%s\"," % (os.getenv('HTTP2', ''))) -print(" \"h2push\" : \"%s\"," % (os.getenv('H2PUSH', ''))) -print(" \"h2_stream_id\" : \"%s\"" % (os.getenv('H2_STREAM_ID', ''))) -print("}") +print(json.JSONEncoder(indent=2).encode(resp)) diff --git a/test/modules/http2/test_600_h2proxy.py b/test/modules/http2/test_600_h2proxy.py index cfcea45602d..040aef6515e 100644 --- a/test/modules/http2/test_600_h2proxy.py +++ b/test/modules/http2/test_600_h2proxy.py @@ -136,6 +136,28 @@ class TestH2Proxy: else env.http_port2 assert int(r.json[1]["port"]) == exp_port + # test X-Forwarded-* headers + def test_h2_600_06(self, env): + conf = H2Conf(env, extras={ + f'cgi.{env.http_tld}': [ + "SetEnvIf Host (.+) X_HOST=$1", + f"ProxyPreserveHost on", + f"ProxyPass /h2c/ h2c://127.0.0.1:{env.http_port}/", + f"ProxyPass /h1c/ http://127.0.0.1:{env.http_port}/", + ] + }) + conf.add_vhost_cgi(proxy_self=True) + conf.install() + assert env.apache_restart() == 0 + url = env.mkurl("https", "cgi", "/h1c/hello.py") + r1 = env.curl_get(url, 5) + assert r1.response["status"] == 200 + url = env.mkurl("https", "cgi", "/h2c/hello.py") + r2 = env.curl_get(url, 5) + assert r2.response["status"] == 200 + for key in ['x-forwarded-for', 'x-forwarded-host','x-forwarded-server']: + assert r1.json[key] == r2.json[key], f'{key} differs proxy_http != proxy_http2' + # lets do some error tests def test_h2_600_30(self, env): conf = H2Conf(env)