You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2009/02/27 21:48:01 UTC

svn commit: r748690 - in /httpd/sandbox/mod_remoteip: README mod_remoteip.c

Author: wrowe
Date: Fri Feb 27 20:48:01 2009
New Revision: 748690

URL: http://svn.apache.org/viewvc?rev=748690&view=rev
Log:
Initial import of mod_remoteip.c as demonstrated at people.apache.org/~wrowe

Added:
    httpd/sandbox/mod_remoteip/README   (with props)
    httpd/sandbox/mod_remoteip/mod_remoteip.c   (with props)

Added: httpd/sandbox/mod_remoteip/README
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_remoteip/README?rev=748690&view=auto
==============================================================================
--- httpd/sandbox/mod_remoteip/README (added)
+++ httpd/sandbox/mod_remoteip/README Fri Feb 27 20:48:01 2009
@@ -0,0 +1,59 @@
+The X-Forwarded-For header (or really, any arbitrary header) can be passed
+by a proxy server to provide the backend application server the identity of
+the remote (origin) client.
+
+Apache identifies the client by the conn_rec->remote_ip header, with the
+conn_rec->remote_host and conn_rec->remote_logname derived from this value.
+These fields play a role in authentication, authorization and logging.
+
+mod_remoteip replaces the true remote_ip with the advertised remote_ip as
+provided by a proxy, for every evaluation of the client that occurs in the
+server.  Therefore, it's critical to only enable this behavior when the
+immediate client (proxy) is trusted by this server.
+
+In the case of a gateway/reverse proxy under the control of the same admin,
+this is a simple case provided that all previous X-Forwarded-For headers
+are stripped at the gateway and replaced by the immediate apparent client
+IP address to that gateway.  However, context is lost in doing so.  The
+obvious alternative is to have the gateway/reverse proxy use another header
+field name, such as X-Client-IP, and trust this header, preserving the 
+advertised X-Forwarded-For value to the application for its evalution.
+
+
+TODO: the immediate improvement in this module on my plate is to add the
+following processing...
+
+Because the proxy may aggregate requests; the connection remote_ip values 
+should be reset between keep-alive requests.
+
+The convention is for proxies to append to this header, such that;
+
+  X-Forwarded-For: origin-client, proxy1, proxy2
+
+offers a list of these proxies.  So starting from the true remote IP address
+reading from R-T-L, for each trusted proxy IP address, we will present the
+immediate parent IP address to the application.
+
+The context of the trusted IP should be preserved, and the untrusted IP
+address preserved in the X-Forwarded-For header.  If we treat the true
+remote client IP at the backend server as the 'gateway', and both gateway
+and proxy2 are known/trusted, then we should transform
+
+  X-Forwarded-For: origin-client, proxy1, proxy2
+
+into an apparent client IP address of 'proxy1', a new value that applies
+to X-Forwarded-For (note proxy1 wasn't trusted to resolve origin-client);
+
+  X-Forwarded-For: origin-client
+
+and a request notes field value of;
+
+  resolved-forwarded-by: proxy2, gateway
+
+However, when using the advertised client IP address, there is absolutely
+no trust that the origin of that data.  It becomes necessary to build a list
+of trust for a particular application.  Public, maintained lists have been
+developed by the following projects;
+
+ * http://meta.wikimedia.org/wiki/XFF_project
+

Propchange: httpd/sandbox/mod_remoteip/README
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/sandbox/mod_remoteip/mod_remoteip.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/mod_remoteip/mod_remoteip.c?rev=748690&view=auto
==============================================================================
--- httpd/sandbox/mod_remoteip/mod_remoteip.c (added)
+++ httpd/sandbox/mod_remoteip/mod_remoteip.c Fri Feb 27 20:48:01 2009
@@ -0,0 +1,132 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ap_config.h"
+#include "ap_mmn.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_connection.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "apr_strings.h"
+#define APR_WANT_BYTEFUNC
+#include "apr_want.h"
+#include "apr_network_io.h"
+
+module AP_MODULE_DECLARE_DATA remoteip_module;
+
+typedef struct {
+    const char *remoteip_header;
+} remoteip_config_t;
+
+static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s)
+{
+    remoteip_config_t *config = apr_palloc(p, sizeof *config);
+    config->remoteip_header = NULL;
+    return config;
+}
+
+static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv,
+                                          void *serverv)
+{
+    remoteip_config_t *global = (remoteip_config_t *) globalv;
+    remoteip_config_t *server = (remoteip_config_t *) serverv;
+    remoteip_config_t *config;
+
+    config = (remoteip_config_t *) apr_palloc(p, sizeof(*config));
+    if (server->remoteip_header)
+        config->remoteip_header = server->remoteip_header;
+    else
+        config->remoteip_header = global->remoteip_header;
+    return config;
+}
+ 
+static const char *remoteip_header_set(cmd_parms *cmd, void *dummy,
+                                       const char *arg)
+{
+    remoteip_config_t *config = ap_get_module_config(cmd->server->module_config,
+                                                     &remoteip_module);
+    config->remoteip_header = apr_pstrdup(cmd->pool, arg);
+    return NULL;
+}
+
+static int modify_connection(request_rec *r)
+{
+    conn_rec *c = r->connection;
+    remoteip_config_t *config = ap_get_module_config(r->server->module_config,
+                                                     &remoteip_module);
+    char *remote;
+
+    if (!config->remoteip_header) 
+        return OK;
+
+    remote = (char*)apr_table_get(r->headers_in, config->remoteip_header);
+    if (!remote)
+        return OK;
+
+    /* Decode remote_addr - sucks; apr_sockaddr_vars_set isn't 'public' */
+    if (inet_pton(AF_INET, remote, 
+                  &c->remote_addr->sa.sin.sin_addr) > 0) {
+        apr_sockaddr_vars_set(c->remote_addr, APR_INET, 0);
+    }
+#if APR_HAVE_IPV6
+    else if (inet_pton(AF_INET6, remote, 
+                       &c->remote_addr->sa.sin6.sin6_addr) > 0) {
+        apr_sockaddr_vars_set(c->remote_addr, APR_INET6, 0);
+    }
+#endif
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,  apr_get_netos_error(), r,
+                      "Header %s value of %s doesn't appear to be a client IP",
+                      config->remoteip_header, remote);
+        return OK;
+    }
+
+    /* Set remote_ip string */
+    remote = apr_pstrdup(c->pool, remote);
+    c->remote_ip = remote;
+
+    /* Unset remote_host string DNS lookups */
+    c->remote_host = NULL;
+    c->remote_logname = NULL;
+
+    ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
+                  "Using header %s value %s as client's IP",
+                  config->remoteip_header, remote);
+    return OK;
+}
+
+static const command_rec remoteip_cmds[] =
+{
+    AP_INIT_TAKE1("RemoteIPHeader", remoteip_header_set, NULL, RSRC_CONF,
+                  "Specifies a request header to trust as the client IP, e.g. X-Forwarded-For."),
+    { NULL }
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+    ap_hook_post_read_request(modify_connection, NULL, NULL, APR_HOOK_FIRST);
+}
+
+module AP_MODULE_DECLARE_DATA remoteip_module = {
+    STANDARD20_MODULE_STUFF,
+    NULL,                          /* create per-directory config structure */
+    NULL,                          /* merge per-directory config structures */
+    create_remoteip_server_config, /* create per-server config structure */
+    merge_remoteip_server_config,  /* merge per-server config structures */
+    remoteip_cmds,                 /* command apr_table_t */
+    register_hooks                 /* register hooks */
+};

Propchange: httpd/sandbox/mod_remoteip/mod_remoteip.c
------------------------------------------------------------------------------
    svn:eol-style = native