summaryrefslogtreecommitdiff
path: root/usr.sbin/httpd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/httpd')
-rw-r--r--usr.sbin/httpd/htdocs/manual/mod/mod_proxy.html29
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.c25
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.h2
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_http.c32
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 ||