Bug 55892 - ProxyRemote with HTTPS backend sends requests with absoluteURI instead of abs_path
Summary: ProxyRemote with HTTPS backend sends requests with absoluteURI instead of abs...
Status: CLOSED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.5-HEAD
Hardware: All All
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: FixedInTrunk
Depends on:
Blocks:
 
Reported: 2013-12-16 21:09 UTC by Hendrik Harms
Modified: 2018-12-03 10:36 UTC (History)
1 user (show)



Attachments
patch for proxy_util.c (631 bytes, patch)
2013-12-16 21:19 UTC, Hendrik Harms
Details | Diff
setup topology (67.91 KB, image/png)
2014-01-26 12:06 UTC, Hendrik Harms
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Hendrik Harms 2013-12-16 21:09:08 UTC
With ProxyRemote configuration the HTTPS backend receives a request with an absoluteURI - which the backend couldn't handle.

Example: 
> ServerName myserver.localnet
> ProxyRemote https://foobar.com http://forwardproxy.localnet:8080
> ProxyPass /content/ https://foobar.com/content/

The Request 
    https://myserver.localnet/content/index.html 
will be received and logged by myserver.localnet as 
    "GET /content/index.html HTTP/1.1"
After a successfull CONNECT handshake with the forwardproxy.localnet we get a SSL tunnel to the backend server. Cause of the SSL tunnel the request won't be transformed/touched by the forward proxy. But the proxy module always sends requests in the absoluteURI form to the backend if a forward proxy is configured. So the backend receives the request in the absoluteURI form: 
    "GET https://foobar.com/content/indext.html HTTP/1.1"

RFC 2616 5.1.2 says that the absoluteURI form should be supported by every HTTP/1.1 Server. My backend seems to have an incomplete rfc implemetation here. :-(

Setting the environment "force-proxy-request-1.0" doesn't help.

I'm not sure about the severity. Is it a bug or a feature to handle improper backend server. ;-)
Comment 1 Hendrik Harms 2013-12-16 21:19:14 UTC
Created attachment 31119 [details]
patch for proxy_util.c

I like to handle HTTPS requests via forward-proxy to backend like direct requests to backend.
This patch wants the "force-proxy-request-1.0" env to do so but I'm not sure that this is really the intention of this switch.
Comment 2 Jim Jagielski 2014-01-24 13:12:30 UTC
Trying to grok this... You seem to be mixing forward and reverse proxies here...
Comment 3 Hendrik Harms 2014-01-26 12:06:04 UTC
Created attachment 31255 [details]
setup topology

ok, my setup is no very usual but there is no mixture between reverse and forward proxy in the apache setup.

Like you can see on the picture (attachment) the Apache reverse proxy is only allowed to connect a special HTTPS-Backend through a HTTP-ForwordProxy. The Problem is that this backend could not serve absoluteURIs like defined in rfc-2616. When using the ProxyRemote setup the Apache Reverse Proxy sends every Request with absoluteURI. Also those tunneled with HTTPS though a HTTP-ForwaredProxy.

I think sending HTTP-Requests to a ForwardProxy this behavior is ok but when using a https tunnel it could cause problems.

The patch would be an enhancement to attach such broken backends.
Maybe the "force-proxy-request-1.0" switch is not the right one here.
Comment 4 William A. Rowe Jr. 2015-02-27 00:08:46 UTC
This assessment is correct.  http://tools.ietf.org/html/rfc7230#section-5.3 is controlling.  Reviewing your proposed patch.

Scenario;

outward.example.com
 - Gateway, reverse proxy
 - ProxyRemote http://{targetServer} http://proxy1.example.com
 - ProxyRemote https://{targetServer} http://proxy1.example.com
 - ProxyPass /foo http://{targetServer}/foo
 - ProxyPass /bar https://{targetServer}/bar

proxy1.example.com
 - At DMZ, faces outward.example.com and behind firewall
 - http:// request seen as proxy GET http://targetServer/foo/ absolute-form
 - https:// request seen as proxy CONNECT targetServer authority-form

targetServer
 - for http from proxy1.example.com, proxy1 has truncated URI to origin-form /foo
 - for https from outward.example.com through proxy1 tunnel, outward failed
   to truncate URI from https://targetServer/bar/ absolute-form to origin-form 
   of simply /bar/ (outward is a tunnel, it has no visibility into the tunneled 
   SSL stream's contents).
Comment 5 Yann Ylavic 2015-02-27 09:19:18 UTC
Comment on attachment 31119 [details]
patch for proxy_util.c

>--- modules/proxy/proxy_util.c.orig	2013-07-11 14:21:19.000000000 +0200
>+++ modules/proxy/proxy_util.c	2013-12-16 16:06:36.000000000 +0100
>@@ -2077,7 +2077,10 @@
>      * short living pool.
>      */
>     /* are we connecting directly, or via a proxy? */
>-    if (!proxyname) {
>+    /* handle HTTP/1.0 via SSL like direct connect */
>+    if (!proxyname ||
>+        (conn->is_ssl &&
>+         apr_table_get(r->subprocess_env, "force-proxy-request-1.0"))) {

I think we should do this regardless of HTTP version, eg :
+    if (!proxyname || conn->is_ssl) {

There is no point in forwarding a full URL to the target server (even in HTTP/1.1), it is not itself a forward proxy.
If it were, why would this work with HTTP/1.1 over SSL only, and not with HTTP/1.0 or without SSL?

>         *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "",
>                            uri->query ? uri->query : "",
>                            uri->fragment ? "#" : "",
Comment 6 William A. Rowe Jr. 2015-03-04 16:34:54 UTC
Well, here's a question;

if (!proxyname || conn->is_ssl)

sounds great, unless the fact is that the ProxyRemote itself was an https:// URL?
This would be common where the proxyremote receives authentication information that
needs to be secured, e.g. an https:// CONNECT connection that then opaquely tunnels 
an https:// session.

I think we need to disambiguate whether proxyname is for a CONNECT request or target 
host, and base the behavior off of this.
Comment 7 William A. Rowe Jr. 2015-03-04 16:43:45 UTC
Scratch that concern, I guess 

if (!proxyname || conn->is_ssl)

is the correct patch.  All https:// requests will have the origin-form of the URI and all non-Remote'd requests will have the origin-form of the URI (also correct).

Yann, do we have agreement to commit and push back to 2.4 (and perhaps 2.2)?
Comment 8 Yann Ylavic 2015-03-04 16:59:53 UTC
(In reply to William A. Rowe Jr. from comment #7)
> Yann, do we have agreement to commit and push back to 2.4 (and perhaps 2.2)?

Yes, absolutely.
Comment 9 Yann Ylavic 2015-03-09 13:31:48 UTC
Committed in r1665215, backport to 2.4 proposed in r1665220, to 2.2 in r1665229.
Comment 10 Yann Ylavic 2015-04-24 20:03:36 UTC
Backported to 2.4.12 in r1665215.
Comment 11 Hendrik Harms 2018-12-03 10:36:38 UTC
released with 2.4.16