Bug 58120

Summary: ProxyPassInherit affects ProxyRemote, not ProxyPass
Product: Apache httpd-2 Reporter: silencer018
Component: mod_proxyAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: normal CC: a.t.chadwick
Priority: P2 Keywords: NeedsReleaseNote, Regression
Version: 2.4-HEAD   
Target Milestone: ---   
Hardware: All   
OS: All   
Attachments: testcase.tar.gz

Description silencer018 2015-07-10 06:26:34 UTC
http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypassinherit

It says the directive will cause the current server/vhost to "inherit" ProxyPass directives defined in the main server. My testing results show that no matter I 
set ProxyPassInherit On or ProxyPassInherit Off, the virtual host always inherits the ProxyPass defined in the main server.

I checked the code, it seems when ProxyPassInherit is set to Off , HTTP server does not merge the config of ProxyRemote(ps->proxies) from global, not the 
ProxyPass(ps->aliases) as I thought.

static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
{
    proxy_server_conf *ps = apr_pcalloc(p, sizeof(proxy_server_conf));
    proxy_server_conf *base = (proxy_server_conf *) basev;
    proxy_server_conf *overrides = (proxy_server_conf *) overridesv;

   
    ps->ppinherit = (overrides->ppinherit_set == 0) ? base->ppinherit : overrides->ppinherit;
    ps->ppinherit_set = overrides->ppinherit_set || base->ppinherit_set;

    if (ps->ppinherit) {
        ps->proxies = apr_array_append(p, base->proxies, overrides->proxies);  
    }
    else {
        ps->proxies = overrides->proxies;
    }

  
    ps->aliases = apr_array_append(p, base->aliases, overrides->aliases);      
   

   
    ... ...


    return ps;
}

Is this a bug ? or I misunderstood the usage of this directive ?

Thanks !
Comment 1 silencer018 2015-07-27 09:06:16 UTC
Is there anybody can help me take a look ?

Thanks
Comment 2 Andrew Chadwick 2022-03-01 17:42:22 UTC
(In reply to silencer018 from comment #0)
> Is this a bug ? or I misunderstood the usage of this directive ?

Confirmed this in 2.4.52 on Debian 11. You're right about the code:

-------------8<-------------

static const command_rec proxy_cmds[] =
{
//  ...
    AP_INIT_TAKE2("ProxyRemote", add_proxy_noregex, NULL, RSRC_CONF,
     "a scheme, partial URL or '*' and a proxy server"),
    AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
     "a regex pattern and a proxy server"),
//  ...
    AP_INIT_RAW_ARGS("ProxyPass", add_pass_noregex, NULL, RSRC_CONF|ACCESS_CONF,
     "a virtual path and a URL"),
    AP_INIT_RAW_ARGS("ProxyPassMatch", add_pass_regex, NULL, RSRC_CONF|ACCESS_CONF,
     "a virtual path and a URL"),
//  ...
------------->8-------------

Elsewhere, the add_pass*() functions update conf->aliases, and the add_proxy*() functions update conf->proxies. This directive is preventing or enabling the inheritance of ProxyRemote and ProxyRemoteMatch, not ProxyPass and ProxyPassMatch as documented.

I'll attach a test case.
Comment 3 Andrew Chadwick 2022-03-01 18:02:35 UTC
Created attachment 38215 [details]
testcase.tar.gz

Minimal test case, for Debian 11. I hope the little tarball attaches.

If your test instance is on Debian 11, unpack the tarball to / (or somewhere safe and then move the files). Don't forget to "a2enmod proxy" and a2enmod proxy_http".

If you're using something else, note that Debian 11 does the following from its main config file, and adapt yours accordingly to include the two config stubs in that tarball.

----------------8<-------------
root@debian11test:/etc/apache2# grep ^Include /etc/apache2/apache2.conf 
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
Include ports.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
---------------->8-------------

Once this is set up, you can test it as follows by tailing the logs.

HEAD http://YOUR.IP         # hits the default page on the default site
HEAD http://YOUR.IP:1080    # hits the default page on the port 1080 vhost
HEAD http://YOUR.IP:1081    # hits the default page on the port 1081 vhost
HEAD http://YOUR.IP/port1080/  # proxied to the port 1080 vhost, hits the default page
HEAD http://YOUR.IP/port1081/  # proxied to the port 1081 vhost, hits the default page
HEAD http://YOUR.IP/port1080/other/xxx  # double proxy! hits the *port 1081* vhost, and 404s
HEAD http://YOUR.IP/port1081/other/xxx  # double proxy! hits the *port 1080* vhost, and 404s

The 1080 and 1081 vhosts are configured with a further /other ProxyPass directive, which does not exist on the default port 80 site. This is just to demonstrate that ProxyPass is working for the 108[12] default vhosts, and is expected behaviour.

After this, the *incorrect* behaviour can be confirmed by tailing the logs

HEAD http://YOUR.IP/port1080/port1081/yyy  # hits the :1081 vhost (where it 404s)
    # Should be 404ed by the port 1080 vhost because ProxypassInherit is Off everywhere.
HEAD http://YOUR.IP/port1081/port1080/zzz  # hits the :1080 vhost (where it 404s)
    # Again, this is being proxied on to the wrong local vhost. ProxyPassInherit Off
    # is blocking inheritance of the wrong directives.