following up on my own post  (the only reponse I received was the 
suggestion to switch to nginx, and while it does appear that much 
development is happening there, I am not in a position to deploy 
current right away...)

On 23 Mar 2012 at 18:26, Jacob L. Leifman wrote:

> In the process of migrating a simple reverse proxy from a Linux box to
> OpenBSD (4.9-i386) I've come across a problem behavior that seems to
> indicate that the directive ProxyPreserveHost is not working. In fact
> setting it on or off does not affect the perceived behavior at all.
> 
> The setup is rather simple and syntactically identical between the Linux
> Apache2 and OpenBSD base httpd (Apache 1.3+):
> 
>  <VirtualHost [public_ip]>
>   ServerName  www.customer.com
>   ErrorLog            logs/error_log
>   CustomLog   logs/access_log common
>   ProxyPreserveHost On
>   ProxyPass           / http://10.xx.yy.zz/
>   ProxyPassReverse    / http://10.xx.yy.zz/
>  </VirtualHost>
> 
> The resulting behaviors differ thus:
> 
> request http://www.customer.com/test/page.aspx --
> *want/linux: the backend server recognizes that the request is for
> virtual server named www.customer.com and delivers the required page;
> *openbsd: the backend server sees http://10.xx.yy.zz/test/page.aspx,
> does not recognize the site and returns 404 Page not found.
> 
> request http://www.customer.com/ --
> *want/linux: the backend server recognizes the site and correctly forms
> all self-referential links on the home page; *openbsd: the backend
> server generates all self-referential links as http://10.xx.yy.zz/...
> which get handed back to the client outside the firewall, rendering the
> website not usable.
> 
> I checked cvsweb for the proxy module of the base httpd, and it has had
> no commits in year, so I believe I am running the latest code.
> 
> Please let me know if/what additional diagnostic info is needed, or
> hopefully patches to test.
> 
> Thanks,
> -Jacob.
> 
> 

After some code archeology I discovered that a critical piece of the 
ProxyPreserveHost implementation which was committed to proxy_http.c 
r1.17 was lost because r1.18 evolved directly from r1.16.

I have reconstructed the missing patch and made a minor adjustment 
related to the evolution of code since then. Below is the resulting 
"new" patch, which does appear to fix my problem above. I would 
appreciate the community/devs reviewing it to make sure I did not miss 
something important.

--- proxy_http.c.orig   Mon Jan 10 15:05:49 2011
+++ proxy_http.c        Sat Mar 24 14:29:30 2012
@@ -151,7 +151,7 @@
 {
     const char *strp;
     char *strp2;
-    const char *err, *desthost;
+    const char *err, *desthost, *hostname;
     int i, j, sock,/* len,*/ backasswards;
     table *req_hdrs, *resp_hdrs;
     array_header *reqhdrs_arr;
@@ -362,21 +362,41 @@
     ap_hard_timeout("proxy send", r);
     ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" 
CRLF,
               NULL);
+
+    if (conf->preserve_host) {
+       hostname = ap_table_get(r->headers_in, "Host");
+       if (!hostname) {    
+           hostname = r->server->server_hostname;
+           ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
+                         "proxy: No host line on incoming request "
+                         "and preserve host set forcing hostname to "
+                         "be %s for uri %s", hostname, r->uri);
+       }
+       strp2 = strchr(hostname, ':');
+       if (strp2 != NULL) {
+           *(strp2++) = '\0';
+           if (ap_isdigit(*strp2))
+               destportstr = strp2;
+       }
+    }
+    else
+       hostname = desthost;
+
     {
        int rc = DECLINED;
        ap_hook_use("ap::mod_proxy::http::handler::write_host_header", 
                    AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,ptr), 
                    AP_HOOK_DECLINE(DECLINED),
-                   &rc, r, f, desthost, destportstr, destportstr);
+                   &rc, r, f, hostname, destportstr, destportstr);
         if (rc == DECLINED) {
            destportstrtonum = strtonum(destportstr, 0, 65535, &errstr);
            if (errstr)
                errx(1, "The destination port is %s: %s", errstr, destportstr);
 
            if (destportstr != NULL && destportstrtonum != destport)
-               ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
+               ap_bvputs(f, "Host: ", hostname, ":", destportstr, CRLF, NULL);
            else
-               ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+               ap_bvputs(f, "Host: ", hostname, CRLF, NULL);
         }
     }

Reply via email to