diff options
Diffstat (limited to 'usr.sbin/httpd')
-rw-r--r-- | usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html | 29 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/proxy/mod_proxy.c | 25 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/proxy/mod_proxy.h | 2 | ||||
-rw-r--r-- | usr.sbin/httpd/src/modules/proxy/proxy_http.c | 32 |
4 files changed, 83 insertions, 5 deletions
diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html b/usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html index 6e0b7e19c32..b4e6497d258 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html @@ -61,6 +61,8 @@ <li><a href="#proxypassreverse">ProxyPassReverse</a></li> + <li><a href="#proxypreservehost">ProxyPreserveHost</a></li> + <li><a href="#proxyblock">ProxyBlock</a></li> <li><a href="#allowconnect">AllowCONNECT</a></li> @@ -563,6 +565,33 @@ application/octet-stream bin dms lha lzh exe class tgz taz <samp>ProxyPass</samp> directive.</p> <hr /> + <h2><a id="proxypreservehost" + name="proxypreservehost">ProxyPreserveHost</a> directive</h2> + <a href="directive-dict.html#Syntax" + rel="Help"><strong>Syntax:</strong></a> ProxyPreserveHost + <em>on|off</em><br /> + <a href="directive-dict.html#Default" + rel="Help"><strong>Default:</strong></a> + <em><samp>ProxyPreserveHost</samp> off</em><br /> + <a href="directive-dict.html#Context" + rel="Help"><strong>Context:</strong></a> server config, virtual + host<br /> + <a href="directive-dict.html#Override" + rel="Help"><strong>Override:</strong></a> <em>Not + applicable</em><br /> + <a href="directive-dict.html#Status" + rel="Help"><strong>Status:</strong></a> Base<br /> + <a href="directive-dict.html#Module" + rel="Help"><strong>Module:</strong></a> mod_proxy<br /> + + <p>When enabled, this option will pass the Host: line from the + incoming request to the proxied host, instead of the hostname + specified in the proxypass line.<br /> + This option should normally be turned Off. It is mostly useful + in special configurations like proxied mass name-based virtual + hosting, where the original Host header needs to be evaluated by + the backend server.</p> + <h2><a id="allowconnect" name="allowconnect">AllowCONNECT</a> directive</h2> <a href="directive-dict.html#Syntax" diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c index fb43af97974..5206151041d 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c @@ -493,6 +493,8 @@ static void * ps->recv_buffer_size_set = 0; ps->io_buffer_size = IOBUFSIZE; ps->io_buffer_size_set = 0; + ps->preserve_host = 0; + ps->preserve_host_set = 0; ps->cache.root = NULL; ps->cache.space = DEFAULT_CACHE_SPACE; @@ -538,6 +540,8 @@ static void * ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size; ps->io_buffer_size = (overrides->io_buffer_size_set == 0) ? base->io_buffer_size : overrides->io_buffer_size; + ps->preserve_host = (overrides->preserve_host_set == 0) ? base->preserve_host : overrides->preserve_host; + ps->cache.root = (overrides->cache.root == NULL) ? base->cache.root : overrides->cache.root; ps->cache.space = (overrides->cache.space_set == 0) ? base->cache.space : overrides->cache.space; ps->cache.maxexpire = (overrides->cache.maxexpire_set == 0) ? base->cache.maxexpire : overrides->cache.maxexpire; @@ -973,6 +977,25 @@ static const char * return NULL; } +static const char * + set_preserve_host(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + + if (strcasecmp(arg, "Off") == 0) + psf->preserve_host = 0; + else if (strcasecmp(arg, "On") == 0) + psf->preserve_host = 1; + else { + return "ProxyPreserveHost must be one of: " + "off | on"; + } + + psf->preserve_host_set = 1; + return NULL; +} + static const handler_rec proxy_handlers[] = { {"proxy-server", proxy_handler}, @@ -1001,6 +1024,8 @@ static const command_rec proxy_cmds[] = "The default intranet domain name (in absence of a domain in the URL)"}, {"AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF, ITERATE, "A list of ports which CONNECT may connect to"}, + {"ProxyPreserveHost", set_preserve_host, NULL, RSRC_CONF, TAKE1, + "on if the host header should be preserved while proxying"}, {"CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1, "The directory to store cache files"}, {"CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1, diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h index 998f1ddcbde..2348afa0852 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h @@ -203,6 +203,8 @@ typedef struct { char recv_buffer_size_set; size_t io_buffer_size; char io_buffer_size_set; + int preserve_host; + int preserve_host_set; } proxy_server_conf; struct hdr_entry { diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_http.c b/usr.sbin/httpd/src/modules/proxy/proxy_http.c index c750f5f78be..46630aafe32 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_http.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_http.c @@ -151,7 +151,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, { 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; @@ -313,17 +313,39 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, 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)) { + destport = atoi(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,int,ptr), AP_HOOK_DECLINE(DECLINED), - &rc, r, f, desthost, destport, destportstr); + &rc, r, f, hostname, destport, destportstr); if (rc == DECLINED) { if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) - 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); } } @@ -570,7 +592,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); -/* check if NoCache directive on this host */ + /* check if NoCache directive on this host */ if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) { if (destaddr.s_addr == ncent[i].addr.s_addr || |