]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Update PROXY handling by removing Optional processing
authorDaniel Ruggeri <druggeri@apache.org>
Sat, 1 Apr 2017 13:51:44 +0000 (13:51 +0000)
committerDaniel Ruggeri <druggeri@apache.org>
Sat, 1 Apr 2017 13:51:44 +0000 (13:51 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1789800 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_remoteip.xml
modules/metadata/mod_remoteip.c

index 81c4c683e3fc1a484cf076e843784d0d90e14898..fba09fa608aed7c4fc3ab853775a4a0268bcf802 100644 (file)
@@ -223,19 +223,19 @@ RemoteIPProxiesHeader X-Forwarded-By
 
 <directivesynopsis>
 <name>RemoteIPProxyProtocol</name>
-<description>Enable, optionally enable or disable the PROXY protocol handling</description>
-<syntax>RemoteIPProxyProtocol On|Optional|Off</syntax>
+<description>Enable or disable PROXY protocol handling</description>
+<syntax>RemoteIPProxyProtocol On|Off</syntax>
 <contextlist><context>server config</context><context>virtual host</context>
 </contextlist>
 <compatibility>RemoteIPProxyProtocol is only available in httpd 2.4.26 and newer</compatibility>
 
 <usage>
-    <p>The <directive>RemoteIPProxyProtocol</directive> enables or 
+    <p>The <directive>RemoteIPProxyProtocol</directive> directive enables or 
     disables the reading and handling of the PROXY protocol connection header.
     If enabled with the <code>On</code> flag, the upstream client <em>must</em>
     send the header every time it opens a connection or the connection will
-    be aborted. If enabled with the <code>Optional</code> flag, the upstream
-    client <em>may</em> send the header.</p>
+    be aborted unless it is in the list of disabled hosts provided by <directive
+    module="mod_remoteip">RemoteIPProxyProtocolDisableHosts</directive> directive.
 
     <p>While this directive may be specified in any virtual host, it is
     important to understand that because the PROXY protocol is connection
@@ -247,45 +247,52 @@ RemoteIPProxiesHeader X-Forwarded-By
     in the other, that won't work; in such a case the last one wins and a
     notice will be logged indicating which setting was being overridden.</p>
 
-    <note type="hint">When multiple virtual hosts on the same IP and port are
-    configured with a combination of <code>On</code> and <code>Optional</code>
-    flags, connections will not be aborted if the header is not sent.
-    Instead, enforcement will happen after the request is read so virtual
-    hosts configured with <code>On</code> will return a 400 Bad Request.
-    Virtual hosts configured with <code>Optional</code> will continue as
-    usual but without replacing the client IP information</note>
-    
     <highlight language="config">
 Listen 80
-&lt;VirtualHost *:80&gt;
-    ServerName www.example.com
-    RemoteIPProxyProtocol Optional
-
-    #Requests to this virtual host may optionally not have
-    # a PROXY protocol header provided
-&lt;/VirtualHost&gt;
-
 &lt;VirtualHost *:80&gt;
     ServerName www.example.com
     RemoteIPProxyProtocol On
 
     #Requests to this virtual host must have a PROXY protocol
-    # header provided. If it is missing, a 400 will result
+    # header provided. If it is missing, the connection will
+    # be aborted
 &lt;/VirtualHost&gt;
 
 Listen 8080
 &lt;VirtualHost *:8080&gt;
     ServerName www.example.com
     RemoteIPProxyProtocol On
+    RemoteIPProxyProtocolDisableHosts 127.0.0.1 10.0.0.0/8
 
     #Requests to this virtual host must have a PROXY protocol
     # header provided. If it is missing, the connection will
-    # be aborted
+    # be aborted except when coming from localhost or the
+    # 10.x.x.x RFC1918 range
 &lt;/VirtualHost&gt;
     </highlight>
 </usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>RemoteIPProxyProtocolDisableHosts</name>
+<description>Disable processing of PROXY header for certain hosts or networks</description>
+<syntax>RemoteIPProxyProtocolDisableHosts host|range [host|range] [host|range]</syntax>
+<contextlist><context>server config</context><context>virtual host</context>
+</contextlist>
+<compatibility>RemoteIPProxyProtocolDisableHosts is only available in httpd 2.4.26 and newer</compatibility>
+
+<usage>
+    <p>The <directive>RemoteIPProxyProtocol</directive> directive enables or
+    disables the reading and handling of the PROXY protocol connection header.
+    Sometimes it is desirable to require clients to provide the PROXY header, but
+    permit other clients to connect without it. This directive allows a server 
+    administrator to configure a single host or CIDR range of hosts that may do
+    so. This is generally useful for useful for monitoring and administrative
+    traffic to a virtual host direct to the server behind the upstream load 
+    balancer.</p>
+</usage>
+</directivesynopsis>
+
 <directivesynopsis>
 <name>RemoteIPTrustedProxy</name>
 <description>Restrict client IP addresses trusted to present the RemoteIPHeader value</description>
index ca985913fa45dd3a7a22dff6132ad138210c16a1..573adadbb2842d90487e738a3e653b894c6ff184 100644 (file)
@@ -61,14 +61,9 @@ typedef struct {
     apr_array_header_t *proxymatch_ip;
 
     remoteip_addr_info *proxy_protocol_enabled;
-    remoteip_addr_info *proxy_protocol_optional;
     remoteip_addr_info *proxy_protocol_disabled;
 
-    /** A flag indicating whether or not proxyprotocol
-     * is optoinal for this specific server
-     */
-    int pp_optional;
-
+    apr_array_header_t *disabled_subnets;
     apr_pool_t *pool;
 } remoteip_config_t;
 
@@ -150,22 +145,18 @@ typedef struct {
     apr_sockaddr_t *client_addr;
     /** Character representation of the client */
     char *client_ip;
-    /** Flag indicating that the PROXY header may be omitted on this
-      connection (do not abort if it is missing). */
-    int proxy_protocol_optional;
 } remoteip_conn_config_t;
 
-typedef enum { HDR_DONE, HDR_ERROR, HDR_MISSING, HDR_NEED_MORE } remoteip_parse_status_t;
+typedef enum { HDR_DONE, HDR_ERROR, HDR_NEED_MORE } remoteip_parse_status_t;
 
 static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s)
 {
-    remoteip_config_t *config = apr_pcalloc(p, sizeof *config);
+    remoteip_config_t *config = apr_pcalloc(p, sizeof(*config));
+    config->disabled_subnets = apr_array_make(p, 1, sizeof(apr_ipsubnet_t *));
     /* config->header_name = NULL;
      * config->proxies_header_name = NULL;
      * config->proxy_protocol_enabled = NULL;
-     * config->proxy_protocol_optional = NULL;
      * config->proxy_protocol_disabled = NULL;
-     * config->pp_optional = 0;
      */
     config->pool = p;
     return config;
@@ -188,9 +179,6 @@ static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv,
     config->proxymatch_ip = server->proxymatch_ip
                           ? server->proxymatch_ip
                           : global->proxymatch_ip;
-    config->pp_optional = server->pp_optional
-                          ? server->pp_optional
-                          : global->pp_optional;
     return config;
 }
 
@@ -363,7 +351,7 @@ static int remoteip_addr_in_list(remoteip_addr_info *list, apr_sockaddr_t *addr)
     return 0;
 }
 
-static void remoteip_warn_enable_conflict(remoteip_addr_info *prev, server_rec *new, const char* arg)
+static void remoteip_warn_enable_conflict(remoteip_addr_info *prev, server_rec *new, int flag)
 {
     char buf[INET6_ADDRSTRLEN];
 
@@ -376,62 +364,43 @@ static void remoteip_warn_enable_conflict(remoteip_addr_info *prev, server_rec *
                  buf, prev->addr->port, prev->source->server_hostname,
                  prev->source->addrs->host_port, prev->source->defn_name,
                  new->server_hostname, new->addrs->host_port, new->defn_name,
-                 arg);
+                 flag ? "On" : "Off");
 }
 
 static const char *remoteip_enable_proxy_protocol(cmd_parms *cmd, void *config,
-                                                  const char *arg)
+                                                  int flag)
 {
-    remoteip_config_t *global_conf;
-    remoteip_config_t *server_conf;
+    remoteip_config_t *conf;
     server_addr_rec *addr;
     remoteip_addr_info **add;
-    int list_len = 2;
-    remoteip_addr_info **rem_list[list_len];
+    remoteip_addr_info **rem;
     remoteip_addr_info *list;
-    int i;
 
-    global_conf = ap_get_module_config(ap_server_conf->module_config,
-                                &remoteip_module);
-    server_conf = ap_get_module_config(cmd->server->module_config,
+    conf = ap_get_module_config(ap_server_conf->module_config,
                                 &remoteip_module);
 
-    if (strcasecmp(arg, "On") == 0) {
-        add = &global_conf->proxy_protocol_enabled;
-        rem_list[0] = &global_conf->proxy_protocol_optional;
-        rem_list[1] = &global_conf->proxy_protocol_disabled;
-    }
-    else if (strcasecmp(arg, "Optional") == 0) {
-        add = &global_conf->proxy_protocol_optional;
-        rem_list[0] = &global_conf->proxy_protocol_enabled;
-        rem_list[1] = &global_conf->proxy_protocol_disabled;
-        server_conf->pp_optional = 1;
-    }
-    else if (strcasecmp(arg, "Off") == 0 ) {
-        add = &global_conf->proxy_protocol_disabled;
-        rem_list[0] = &global_conf->proxy_protocol_enabled;
-        rem_list[1] = &global_conf->proxy_protocol_optional;
+    if (flag) {
+        add = &conf->proxy_protocol_enabled;
+        rem = &conf->proxy_protocol_disabled;
     }
     else {
-        return apr_pstrcat(cmd->pool, "Unrecognized option for %s `%s'", cmd->cmd->name, arg, NULL);
+        add = &conf->proxy_protocol_disabled;
+        rem = &conf->proxy_protocol_enabled;
     }
 
     for (addr = cmd->server->addrs; addr; addr = addr->next) {
-        /* remove address from other lists */
-        for (i = 0; i < list_len ; i++) { 
-            remoteip_addr_info **rem = rem_list[i];
-            if (*rem) {
-                if (remoteip_sockaddr_equal((*rem)->addr, addr->host_addr)) {
-                    remoteip_warn_enable_conflict(*rem, cmd->server, arg);
-                    *rem = (*rem)->next;
-                }
-                else {
-                    for (list = *rem; list->next; list = list->next) {
-                        if (remoteip_sockaddr_equal(list->next->addr, addr->host_addr)) {
-                            remoteip_warn_enable_conflict(list->next, cmd->server, arg);
-                            list->next = list->next->next;
-                            break;
-                        }
+        /* remove address from opposite list */
+        if (*rem) {
+            if (remoteip_sockaddr_equal((*rem)->addr, addr->host_addr)) {
+                remoteip_warn_enable_conflict(*rem, cmd->server, flag);
+                *rem = (*rem)->next;
+            }
+            else {
+                for (list = *rem; list->next; list = list->next) {
+                    if (remoteip_sockaddr_equal(list->next->addr, addr->host_addr)) {
+                        remoteip_warn_enable_conflict(list->next, cmd->server, flag);
+                        list->next = list->next->next;
+                        break;
                     }
                 }
             }
@@ -439,7 +408,7 @@ static const char *remoteip_enable_proxy_protocol(cmd_parms *cmd, void *config,
 
         /* add address to desired list */
         if (!remoteip_addr_in_list(*add, addr->host_addr)) {
-            remoteip_addr_info *info = apr_palloc(global_conf->pool, sizeof(*info));
+            remoteip_addr_info *info = apr_palloc(conf->pool, sizeof(*info));
             info->addr = addr->host_addr;
             info->source = cmd->server;
             info->next = *add;
@@ -450,6 +419,45 @@ static const char *remoteip_enable_proxy_protocol(cmd_parms *cmd, void *config,
     return NULL;
 }
 
+static const char *remoteip_disable_networks(cmd_parms *cmd, void *d,
+                                             int argc, char *const argv[])
+{
+    int i;
+    apr_pool_t *ptemp = cmd->temp_pool;
+    apr_pool_t *p = cmd->pool;
+    remoteip_config_t *conf = ap_get_module_config(ap_server_conf->module_config,
+                                &remoteip_module);
+
+    if (argc == 0)
+        return "RemoteIPProxyProtocolDisableNetworks requires an argument";
+
+
+    for (i=0; i<argc; i++) {
+        char *addr = apr_pstrdup(ptemp, argv[i]);
+        char *mask;
+        apr_status_t rv;
+        apr_ipsubnet_t **ip = apr_pcalloc(p, sizeof(apr_ipsubnet_t *));
+
+        if ((mask = ap_strchr(addr, '/')))
+            *mask++ = '\0';
+
+        rv = apr_ipsubnet_create(ip, addr, mask, p);
+
+        if(APR_STATUS_IS_EINVAL(rv)) {
+            /* looked nothing like an IP address */
+            return apr_psprintf(p, "ip address '%s' appears to be invalid", addr);
+        }
+        else if (rv != APR_SUCCESS) {
+            return apr_psprintf(p, "ip address '%s' appears to be invalid: %pm",
+                                addr, &rv);
+        }
+
+        *(apr_ipsubnet_t**)apr_array_push(conf->disabled_subnets) = *ip;
+    }
+
+    return NULL;
+}
+
 static int remoteip_hook_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
                               apr_pool_t *ptemp)
 {
@@ -476,11 +484,6 @@ static int remoteip_hook_post_config(apr_pool_t *pconf, apr_pool_t *plog,
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(03492)
                      "RemoteIPProxyProtocol: enabled on %s:%hu", buf, info->addr->port);
     }
-    for (info = conf->proxy_protocol_optional; info; info = info->next) {
-        apr_sockaddr_ip_getbuf(buf, sizeof(buf), info->addr);
-        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(03493)
-                     "RemoteIPProxyProtocol: optional on %s:%hu", buf, info->addr->port);
-    }
     for (info = conf->proxy_protocol_disabled; info; info = info->next) {
         apr_sockaddr_ip_getbuf(buf, sizeof(buf), info->addr);
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(03494)
@@ -523,18 +526,10 @@ static int remoteip_modify_request(request_rec *r)
        protocol handling allowing it to take precedence and return
     */
     if (conn_config) {
-        /* We may have gotten here if processing was optional - check for that */
         if (!conn_config->client_addr) {
-            if (config->pp_optional) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03495)
-                              "RemoteIPProxyProtocol data is missing, but was optional. Allowing request.");
-                return OK;
-            }
-            else {
-                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03496)
-                              "RemoteIPProxyProtocol data is missing, but required! Aborting request.");
-                return HTTP_BAD_REQUEST;
-            }
+            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03496)
+                          "RemoteIPProxyProtocol data is missing, but required! Aborting request.");
+            return HTTP_BAD_REQUEST;
         }
 
         r->useragent_addr = conn_config->client_addr;
@@ -860,7 +855,7 @@ static int remoteip_hook_pre_connection(conn_rec *c, void *csd)
 {
     remoteip_config_t *conf;
     remoteip_conn_config_t *conn_conf;
-    int optional;
+    int i;
 
     /* Do not attempt to manipulate slave connections */
     if (c->master != NULL) {
@@ -870,16 +865,22 @@ static int remoteip_hook_pre_connection(conn_rec *c, void *csd)
     conf = ap_get_module_config(ap_server_conf->module_config,
                                 &remoteip_module);
 
-    /* Used twice - do the check only once */
-    optional = remoteip_addr_in_list(conf->proxy_protocol_optional, c->local_addr);
-
     /* check if we're enabled for this connection */
-    if ((!remoteip_addr_in_list(conf->proxy_protocol_enabled, c->local_addr)
-          && !optional )
+    if (!remoteip_addr_in_list(conf->proxy_protocol_enabled, c->local_addr)
         || remoteip_addr_in_list(conf->proxy_protocol_disabled, c->local_addr)) {
+
         return DECLINED;
     }
 
+    /* We are enabled for this IP/port, but check that we aren't
+       explicitly disabled */
+    for (i = 0; i < conf->disabled_subnets->nelts; i++) {
+        apr_ipsubnet_t *ip = ((apr_ipsubnet_t**)conf->disabled_subnets->elts)[i];
+
+        if (ip && apr_ipsubnet_test(ip, c->client_addr))
+            return DECLINED;
+    }
+
     /* mod_proxy creates outgoing connections - we don't want those */
     if (!remoteip_is_server_port(c->local_addr->port)) {
         return DECLINED;
@@ -898,12 +899,6 @@ static int remoteip_hook_pre_connection(conn_rec *c, void *csd)
     /* this holds the resolved proxy info for this connection */
     conn_conf = apr_pcalloc(c->pool, sizeof(*conn_conf));
 
-    /* Propagate the optional flag so the connection handler knows not to
-       abort if the header is mising. NOTE: This means we must check after
-       we read the request that the header was NOT optional, too.
-    */
-    conn_conf->proxy_protocol_optional = optional;
-
     ap_set_module_config(c->conn_config, &remoteip_module, conn_conf);
 
     return OK;
@@ -1036,31 +1031,20 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
     remoteip_parse_status_t psts = HDR_NEED_MORE;
     const char *ptr;
     apr_size_t len;
-    apr_size_t this_read = 0; /* Track bytes read in each brigade */
-    apr_size_t prev_read = 0;
 
     if (f->c->aborted) {
         return APR_ECONNABORTED;
     }
 
-    conn_conf = ap_get_module_config(f->c->conn_config, &remoteip_module);
-
     /* allocate/retrieve the context that holds our header */
     if (!ctx) {
         ctx = f->ctx = apr_palloc(f->c->pool, sizeof(*ctx));
         ctx->rcvd = 0;
         ctx->need = MIN_HDR_LEN;
         ctx->version = 0;
+        ctx->mode = AP_MODE_READBYTES;
         ctx->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
         ctx->done = 0;
-        if (conn_conf->proxy_protocol_optional) {
-            ctx->mode = AP_MODE_SPECULATIVE;
-            ctx->peeking = 1;
-        }
-        else {
-            ctx->mode = AP_MODE_READBYTES;
-            ctx->peeking = 0;
-        }
     }
 
     if (ctx->done) {
@@ -1071,6 +1055,8 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
         return ap_get_brigade(f->next, bb_out, mode, block, readbytes);
     }
 
+    conn_conf = ap_get_module_config(f->c->conn_config, &remoteip_module);
+
     /* try to read a header's worth of data */
     while (!ctx->done) {
         if (APR_BRIGADE_EMPTY(ctx->bb)) {
@@ -1084,23 +1070,9 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
             return block == APR_NONBLOCK_READ ? APR_SUCCESS : APR_EOF;
         }
 
-        if (ctx->peeking) {
-            ctx->rcvd = 0;
-            ctx->need = MIN_HDR_LEN;
-        }
-
         while (!ctx->done && !APR_BRIGADE_EMPTY(ctx->bb)) {
             b = APR_BRIGADE_FIRST(ctx->bb);
 
-            if (ctx->peeking && APR_BUCKET_IS_EOS(b)) {
-                /* Shortcut - we know no header was found yet and an
-                   EOS indicates we never will */
-                apr_brigade_destroy(ctx->bb);
-                ctx->bb = NULL;
-                ctx->done = 1;
-                return APR_SUCCESS;
-            }
-
             ret = apr_bucket_read(b, &ptr, &len, block);
             if (APR_STATUS_IS_EAGAIN(ret) && block == APR_NONBLOCK_READ) {
                 return APR_SUCCESS;
@@ -1112,10 +1084,6 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
             memcpy(ctx->header + ctx->rcvd, ptr, len);
             ctx->rcvd += len;
 
-            if (ctx->peeking && block == APR_NONBLOCK_READ) {
-                this_read += len;
-            }
-
             apr_bucket_delete(b);
             psts = HDR_NEED_MORE;
 
@@ -1123,45 +1091,15 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
                 /* reading initial chunk */
                 if (ctx->rcvd >= MIN_HDR_LEN) {
                     ctx->version = remoteip_determine_version(f->c, ctx->header);
-
-                    /* We've read enough to know that a header is present. In peek mode
-                       we purge the bb and can decide to step aside or switch to
-                       non-speculative read to consume the data */
-                    if (ctx->peeking) {
-                        if (ctx->version < 0) {
-                            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c, APLOGNO(03512)
-                                          "RemoteIPProxyProtocol: PROXY header is missing from "
-                                          "request. Stepping aside.");
-                            apr_brigade_destroy(ctx->bb);
-                            ctx->bb = NULL;
-                            ctx->done = 1;
-                            return ap_get_brigade(f->next, bb_out, mode, block, readbytes);
-                        }
-                        else {
-                            /* Rest ctx to initial values */
-                            ctx->rcvd = 0;
-                            ctx->need = MIN_HDR_LEN;
-                            ctx->version = 0;
-                            ctx->done = 0;
-                            ctx->mode = AP_MODE_READBYTES;
-                            ctx->peeking = 0;
-                            apr_brigade_cleanup(ctx->bb);
-
-                            ap_get_brigade(f->next, ctx->bb, ctx->mode, block,
-                                           ctx->need - ctx->rcvd);
-                        }
+                    if (ctx->version < 0) {
+                        psts = HDR_ERROR;
                     }
-                    else {
-                        if (ctx->version < 0) {
-                            psts = HDR_MISSING;
-                        }
-                        else if (ctx->version == 1) {
-                            ctx->mode = AP_MODE_GETLINE;
-                            ctx->need = sizeof(proxy_v1);
-                        }
-                        else if (ctx->version == 2) {
-                            ctx->need = MIN_V2_HDR_LEN;
-                        }
+                    else if (ctx->version == 1) {
+                        ctx->mode = AP_MODE_GETLINE;
+                        ctx->need = sizeof(proxy_v1);
+                    }
+                    else if (ctx->version == 2) {
+                        ctx->need = MIN_V2_HDR_LEN;
                     }
                 }
             }
@@ -1174,7 +1112,6 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
                 if (ctx->rcvd >= MIN_V2_HDR_LEN) {
                     ctx->need = MIN_V2_HDR_LEN +
                         remoteip_get_v2_len((proxy_header *) ctx->header);
-
                 }
                 if (ctx->rcvd >= ctx->need) {
                     psts = remoteip_process_v2_header(f->c, conn_conf,
@@ -1191,10 +1128,6 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
             }
 
             switch (psts) {
-                case HDR_MISSING:
-                    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(03510)
-                                 "RemoteIPProxyProtocol: no valid PROXY header found");
-                        /* fall through to error case */
                 case HDR_ERROR:
                     f->c->aborted = 1;
                     apr_brigade_destroy(ctx->bb);
@@ -1208,18 +1141,6 @@ static apr_status_t remoteip_input_filter(ap_filter_t *f,
                     break;
             }
         }
-
-        /* In SPECULATIVE mode, upstream will return all data on each brigade get - even data
-           we've seen.  For non blocking read, make sure we got new data or return early when
-           we haven't */
-        if (ctx->peeking && block == APR_NONBLOCK_READ) {
-            if (this_read == prev_read) {
-                return APR_SUCCESS;
-            }
-            else {
-                prev_read = this_read;
-            }
-        }
     }
 
     /* we only get here when done == 1 */
@@ -1268,8 +1189,11 @@ static const command_rec remoteip_cmds[] =
                   RSRC_CONF | EXEC_ON_READ,
                   "The filename to read the list of internal proxies, "
                   "see the RemoteIPInternalProxy directive"),
-    AP_INIT_TAKE1("RemoteIPProxyProtocol", remoteip_enable_proxy_protocol, NULL,
-                  RSRC_CONF, "Enable PROXY protocol handling (`on', `off', `optional')"),
+    AP_INIT_FLAG("RemoteIPProxyProtocol", remoteip_enable_proxy_protocol, NULL,
+                  RSRC_CONF, "Enable PROXY protocol handling (`on', `off')"),
+    AP_INIT_TAKE_ARGV("RemoteIPProxyProtocolDisableHosts",
+                  remoteip_disable_networks, NULL, RSRC_CONF, "Disable PROXY "
+                  "protocol handling for this list of networks in CIDR format"),
     { NULL }
 };