ASF Bugzilla – Attachment 34506 Details for
Bug 59829
Detect HTTPS marker from reverse proxy
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
reset scheme and port if next request to be processed is http; set scheme and port only from trusted proxies
mod_remoteip.patch (text/plain), 10.74 KB, created by
martin.kofahl
on 2016-12-07 19:51:14 UTC
(
hide
)
Description:
reset scheme and port if next request to be processed is http; set scheme and port only from trusted proxies
Filename:
MIME Type:
Creator:
martin.kofahl
Created:
2016-12-07 19:51:14 UTC
Size:
10.74 KB
patch
obsolete
>--- mod_remoteip.c 2016-12-07 17:11:27.530693671 +0100 >+++ ../mod_remoteip.c 2016-12-07 20:47:28.776895484 +0100 >@@ -44,10 +44,34 @@ > * from the proxy-via IP header value list) > */ > const char *proxies_header_name; >+ /** A header that may indicate user is using a >+ * HTTPS connection to the reverse-proxy, and >+ * the value that it must match for it to do so. >+ */ >+ const char *secure_header_name; >+ const char *secure_header_value; > /** A list of trusted proxies, ideally configured > * with the most commonly encountered listed first > */ > apr_array_header_t *proxymatch_ip; >+ /** The fixed scheme names http (derived from >+ * original server configuration) and https >+ * (set statically). >+ */ >+ const char *orig_scheme; >+ const char *secure_scheme; >+ /** The configured ports for http (derived from >+ * server configuration) and https (defaults to >+ * 443 and may be overwritten by the user. >+ */ >+ int orig_port; >+ int secure_port; >+ /** A buffer holding the current port number as >+ * string and thus not longer than 5 digits. >+ * This prevents the buffer to be malloc'ed >+ * for each request. >+ */ >+ char buffer[6]; > } remoteip_config_t; > > typedef struct { >@@ -65,6 +89,13 @@ > /* config->header_name = NULL; > * config->proxies_header_name = NULL; > */ >+ >+ config->secure_port = 443; >+ config->orig_port = s->port; >+ >+ config->secure_scheme = apr_pstrdup(p, "https"); >+ config->orig_scheme = s->server_scheme; >+ > return config; > } > >@@ -85,6 +116,15 @@ > config->proxymatch_ip = server->proxymatch_ip > ? server->proxymatch_ip > : global->proxymatch_ip; >+ config->secure_header_name = server->secure_header_name >+ ? server->secure_header_name >+ : global->secure_header_name; >+ config->secure_header_value = server->secure_header_value >+ ? server->secure_header_value >+ : global->secure_header_value; >+ config->secure_port = server->secure_port >+ ? server->secure_port >+ : global->secure_port; > return config; > } > >@@ -106,6 +146,24 @@ > return NULL; > } > >+static const char *secure_header_set(cmd_parms *cmd, void *dummy, >+ const char *name, const char *value) >+{ >+ remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, >+ &remoteip_module); >+ config->secure_header_name = name; >+ config->secure_header_value = value; >+ return NULL; >+} >+ >+static const char *secure_port_set(cmd_parms *cmd, void *dummy, const char *value) >+{ >+ remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, >+ &remoteip_module); >+ config->secure_port = atoi(value); >+ return NULL; >+} >+ > /* Would be quite nice if APR exported this */ > /* apr:network_io/unix/sockaddr.c */ > static int looks_like_ip(const char *ipstr) >@@ -215,6 +273,29 @@ > return NULL; > } > >+static int is_trusted_proxy(remoteip_config_t *config, apr_sockaddr_t *sa, void *internal) { >+ int i; >+ >+ if (config->proxymatch_ip) { >+ remoteip_proxymatch_t *match; >+ match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts; >+ for (i = 0; i < config->proxymatch_ip->nelts; ++i) { >+ if (apr_ipsubnet_test(match[i].ip, sa)) { >+ if (internal) { >+ /* Allow an internal proxy to present an external proxy, >+ but do not allow an external proxy to present an internal proxy. >+ In this case, the presented internal proxy will be considered external. >+ */ >+ internal = match[i].internal; >+ } >+ return 1; >+ } >+ } >+ } >+ >+ return 0; >+} >+ > static int remoteip_modify_request(request_rec *r) > { > conn_rec *c = r->connection; >@@ -229,6 +310,11 @@ > char *proxy_ips = NULL; > char *parse_remote; > char *eos; >+ char *pchar = NULL; >+ /* The protocol to be set: http(0), https(1). */ >+ int secure = 0; >+ /* Flag whether allowed to change the request, here: the protocol. */ >+ int trusted_proxy = 0; > unsigned char *addrbyte; > > /* If no RemoteIPInternalProxy, RemoteIPInternalProxyList, RemoteIPTrustedProxy >@@ -237,7 +323,7 @@ > */ > void *internal = NULL; > >- if (!config->header_name) { >+ if (!config->header_name && !config->secure_header_name) { > return DECLINED; > } > >@@ -248,39 +334,16 @@ > */ > internal = (void *) 1; > } >- >+ > remote = (char *) apr_table_get(r->headers_in, config->header_name); >- if (!remote) { >- return OK; >+ temp_sa = c->client_addr; >+ if (remote) { >+ remote = apr_pstrdup(r->pool, remote); > } >- remote = apr_pstrdup(r->pool, remote); >- >- temp_sa = r->useragent_addr ? r->useragent_addr : c->client_addr; >- >- while (remote) { >- >- /* verify user agent IP against the trusted proxy list >- */ >- if (config->proxymatch_ip) { >- int i; >- remoteip_proxymatch_t *match; >- match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts; >- for (i = 0; i < config->proxymatch_ip->nelts; ++i) { >- if (apr_ipsubnet_test(match[i].ip, temp_sa)) { >- if (internal) { >- /* Allow an internal proxy to present an external proxy, >- but do not allow an external proxy to present an internal proxy. >- In this case, the presented internal proxy will be considered external. >- */ >- internal = match[i].internal; >- } >- break; >- } >- } >- if (i && i >= config->proxymatch_ip->nelts) { >- break; >- } >- } >+ /* Loop through all entries the remoteip_header. >+ * For further use, flag the car trusted_proxy if a trusted proxy was seen. >+ */ >+ while ((trusted_proxy|=is_trusted_proxy(config, temp_sa, internal))==1 && remote) { > > if ((parse_remote = strrchr(remote, ',')) == NULL) { > parse_remote = remote; >@@ -389,38 +452,72 @@ > apr_sockaddr_ip_get(&req->useragent_ip, req->useragent_addr); > } > >- /* Nothing happened? */ >- if (!req) { >- return OK; >+ /* Is there a client IP to be set? */ >+ if (req) { >+ req->proxied_remote = remote; >+ req->proxy_ips = proxy_ips; >+ >+ if (req->proxied_remote) { >+ apr_table_setn(r->headers_in, config->header_name, >+ req->proxied_remote); >+ } >+ else { >+ apr_table_unset(r->headers_in, config->header_name); >+ } >+ if (req->proxy_ips) { >+ apr_table_setn(r->notes, "remoteip-proxy-ip-list", req->proxy_ips); >+ if (config->proxies_header_name) { >+ apr_table_setn(r->headers_in, config->proxies_header_name, >+ req->proxy_ips); >+ } >+ } >+ >+ r->useragent_addr = req->useragent_addr; >+ r->useragent_ip = req->useragent_ip; >+ >+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, >+ req->proxy_ips >+ ? "Using %s as client's IP by proxies %s via" >+ : "Using %s as client's IP by internal proxies %s", >+ req->useragent_ip, >+ (req->proxy_ips ? req->proxy_ips : "")); > } > >- req->proxied_remote = remote; >- req->proxy_ips = proxy_ips; >+ /* Handle the secure_header_name if the request was sent via a trusted proxy. >+ * As the request object may be reused without resetting the scheme and >+ * server port, we'll always have to set port and scheme. >+ */ >+ if (config->secure_header_name && trusted_proxy == 1) { >+ pchar = (char *) apr_table_get(r->headers_in, config->secure_header_name); >+ if (pchar && 0 == strcmp(pchar, config->secure_header_value)) { >+ secure = 1; >+ } >+ } > >- if (req->proxied_remote) { >- apr_table_setn(r->headers_in, config->header_name, >- req->proxied_remote); >+ if (secure) { >+ apr_table_setn(r->subprocess_env, "HTTPS", "on"); >+ r->server->port = config->secure_port; >+ r->server->server_scheme = config->secure_scheme; >+ r->parsed_uri.port = r->server->port; >+ >+ /* Header available, matched and processed. May be unset now. */ >+ apr_table_unset(r->headers_in, config->secure_header_name); >+ >+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, >+ "Setting scheme https and server's port %d", >+ r->server->port); > } > else { >- apr_table_unset(r->headers_in, config->header_name); >- } >- if (req->proxy_ips) { >- apr_table_setn(r->notes, "remoteip-proxy-ip-list", req->proxy_ips); >- if (config->proxies_header_name) { >- apr_table_setn(r->headers_in, config->proxies_header_name, >- req->proxy_ips); >- } >+ r->server->port = config->orig_port; >+ r->server->server_scheme = config->orig_scheme; > } > >- r->useragent_addr = req->useragent_addr; >- r->useragent_ip = req->useragent_ip; >+ /* In order not to malloc on each request, the config* >+ * holds a buffer for taking the server port number. >+ */ >+ snprintf(config->buffer, 5, "%d", r->server->port); >+ apr_table_setn(r->subprocess_env, "SERVER_PORT", config->buffer); > >- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, >- req->proxy_ips >- ? "Using %s as client's IP by proxies %s" >- : "Using %s as client's IP by internal proxies%s", >- req->useragent_ip, >- (req->proxy_ips ? req->proxy_ips : "")); > return OK; > } > >@@ -447,6 +544,12 @@ > RSRC_CONF | EXEC_ON_READ, > "The filename to read the list of internal proxies, " > "see the RemoteIPInternalProxy directive"), >+ AP_INIT_TAKE2("SecureIndicatorHeader", secure_header_set, NULL, RSRC_CONF, >+ "Specifies a request header and value that indicates a secure connection, " >+ "e.g. \"X-Forwarded-Proto https\" or \"X-Secure-Connection on\""), >+ AP_INIT_TAKE1("SecureIndicatorSSLPort", secure_port_set, NULL, RSRC_CONF, >+ "Port to be used for redirections if SecureIndicatorHeader is set, " >+ "Default is \"SecureInidcatorSSLPort 443\" "), > { NULL } > }; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 59829
:
34024
|
34249
|
34495
|
34496
|
34504
|
34506
|
34507
|
34518
|
34709
|
34711
|
34741
|
34774
|
34781