Greetings,
Following a small discussion on #httpd irc channel, about
X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Server.
These headers are currently set or altered by mod_proxy_http whenever a
reverse proxy request is handled.
Using RequestHeader to unset these headers is unefficient, probably for
order processing reasons. Even if it was possible, it would not be
sufficient, since an administrator might want to pass already existing
headers without altering them, rather than just unsetting them.
Here is a small patch against trunk. This patch introduces the
ProxyAddHeaders directive.
If set to "On" (default), the current mod_proxy_http behavior is kept :
X-Forwarded-* headers are set, or completed for the request sent to the
backend server.
If set to "Off", X-Forwarded-* headers are just passed as in the client
request, if defined.
I have included the documentation patch, unsure whether it should be
commited separately ?
Please comment and correct me if needed.
Vincent Deffontaines
Index: docs/manual/mod/mod_proxy.xml
===================================================================
--- docs/manual/mod/mod_proxy.xml (révision 1059390)
+++ docs/manual/mod/mod_proxy.xml (copie de travail)
@@ -1702,4 +1702,25 @@
</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>ProxyAddHeaders</name>
+<description>Add proxy information in X-Forwarded-* headers</description>
+<syntax>ProxyAddHeaders Off|On</syntax>
+<default>ProxyAddHeaders On</default>
+<contextlist><context>server config</context>
+<context>virtual host</context>
+<context>directory</context>
+</contextlist>
+<compatibility>Available in version 2.3.10 and later</compatibility>
+
+<usage>
+ <p>This directive determines whether or not proxy related information should be passed to the
+ backend server through X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Server HTTP headers.</p>
+ <note><title>Effectiveness</title>
+ <p>This option is of use only for HTTP proxying, as handled by <module>mod_proxy_http</module>.</p>
+ </note>
+
+
+</usage>
+</directivesynopsis>
</modulesynopsis>
Index: modules/proxy/mod_proxy_http.c
===================================================================
--- modules/proxy/mod_proxy_http.c (révision 1059390)
+++ modules/proxy/mod_proxy_http.c (copie de travail)
@@ -851,29 +851,30 @@
* a forward proxy configuation instead of X-Forwarded-*. See the
* ProxyVia option for details.
*/
+ if (dconf->add_forwarded_headers) {
+ if (PROXYREQ_REVERSE == r->proxyreq) {
+ const char *buf;
- if (PROXYREQ_REVERSE == r->proxyreq) {
- const char *buf;
+ /* Add X-Forwarded-For: so that the upstream has a chance to
+ * determine, where the original request came from.
+ */
+ apr_table_mergen(r->headers_in, "X-Forwarded-For",
+ c->remote_ip);
- /* Add X-Forwarded-For: so that the upstream has a chance to
- * determine, where the original request came from.
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-For",
- c->remote_ip);
+ /* Add X-Forwarded-Host: so that upstream knows what the
+ * original request hostname was.
+ */
+ if ((buf = apr_table_get(r->headers_in, "Host"))) {
+ apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
+ }
- /* Add X-Forwarded-Host: so that upstream knows what the
- * original request hostname was.
- */
- if ((buf = apr_table_get(r->headers_in, "Host"))) {
- apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
- }
-
- /* Add X-Forwarded-Server: so that upstream knows what the
- * name of this proxy server is (if there are more than one)
- * XXX: This duplicates Via: - do we strictly need it?
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-Server",
- r->server->server_hostname);
+ /* Add X-Forwarded-Server: so that upstream knows what the
+ * name of this proxy server is (if there are more than one)
+ * XXX: This duplicates Via: - do we strictly need it?
+ */
+ apr_table_mergen(r->headers_in, "X-Forwarded-Server",
+ r->server->server_hostname);
+ }
}
proxy_run_fixups(r);
Index: modules/proxy/mod_proxy.c
===================================================================
--- modules/proxy/mod_proxy.c (révision 1059390)
+++ modules/proxy/mod_proxy.c (copie de travail)
@@ -1246,6 +1245,7 @@
new->interpolate_env = -1; /* unset */
new->error_override = 0;
new->error_override_set = 0;
+ new->add_forwarded_headers = 1;
return (void *) new;
}
@@ -1278,6 +1278,7 @@
new->error_override_set = add->error_override_set || base->error_override_set;
new->alias = (add->alias_set == 0) ? base->alias : add->alias;
new->alias_set = add->alias_set || base->alias_set;
+ new->add_forwarded_headers = add->add_forwarded_headers;
return new;
}
@@ -1709,6 +1710,13 @@
return NULL;
}
static const char *
+ add_proxy_http_headers(cmd_parms *parms, void *dconf, int flag)
+{
+ proxy_dir_conf *conf = dconf;
+ conf->add_forwarded_headers = flag;
+ return NULL;
+}
+static const char *
set_preserve_host(cmd_parms *parms, void *dconf, int flag)
{
proxy_dir_conf *conf = dconf;
@@ -2225,6 +2233,8 @@
"A balancer or worker name with list of params"),
AP_INIT_TAKE1("ProxySourceAddress", set_source_address, NULL, RSRC_CONF,
"Configure local source IP used for request forward"),
+ AP_INIT_FLAG("ProxyAddHeaders", add_proxy_http_headers, NULL, RSRC_CONF|ACCESS_CONF,
+ "on if X-Forwarded-* headers should be added or completed"),
{NULL}
};
Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h (révision 1059390)
+++ modules/proxy/mod_proxy.h (copie de travail)
@@ -207,6 +207,7 @@
int preserve_host_set:1;
int error_override_set:1;
int alias_set:1;
+ int add_forwarded_headers:1;
} proxy_dir_conf;
/* if we interpolate env vars per-request, we'll need a per-request