mod_remoteip.c revision a221184be5b40f8349982d94cda02b98068ce0d8
/* 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
*
*
* 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"
#include "apr_lib.h"
#define APR_WANT_BYTEFUNC
#include "apr_want.h"
#include "apr_network_io.h"
typedef struct {
/** A proxy IP mask to match */
/** Flagged if internal, otherwise an external trusted proxy */
void *internal;
typedef struct {
/** The header to retrieve a proxy-via ip list */
const char *header_name;
/** A header to record the proxied IP's
* (removed as the physical connection and
* from the proxy-via ip header value list)
*/
const char *proxies_header_name;
/** A list of trusted proxies, ideally configured
* with the most commonly encountered listed first
*/
typedef struct {
char *useragent_ip;
/** The list of proxy ip's ignored as remote ip's */
const char *proxy_ips;
/** The remaining list of untrusted proxied remote ip's */
const char *proxied_remote;
{
/* config->header_name = NULL;
* config->proxies_header_name = NULL;
*/
return config;
}
void *serverv)
{
: global->header_name;
: global->proxymatch_ip;
return config;
}
const char *arg)
{
return NULL;
}
const char *arg)
{
return NULL;
}
/* Would be quite nice if APR exported this */
/* apr:network_io/unix/sockaddr.c */
static int looks_like_ip(const char *ipstr)
{
/* definitely not a hostname; assume it is intended to be an IPv6 address */
return 1;
}
/* simple IPv4 address string check */
ipstr++;
return (*ipstr == '\0');
}
const char *arg)
{
if (s) {
*s++ = '\0';
}
if (!config->proxymatch_ip) {
}
if (looks_like_ip(ip)) {
/* Note s may be null, that's fine (explicit host) */
}
else
{
if (s) {
" the subnet /", s, " is invalid for ",
}
while (rv == APR_SUCCESS)
{
break;
}
match = (remoteip_proxymatch_t *)
}
}
if (rv != APR_SUCCESS) {
char msgbuf[128];
}
return NULL;
}
const char *filename)
{
char lbuf[MAX_STRING_LEN];
char *arg;
const char *args;
const char *errmsg;
if (rv != APR_SUCCESS) {
}
break;
}
if (errmsg) {
return errmsg;
}
}
}
return NULL;
}
static int remoteip_modify_request(request_rec *r)
{
conn_rec *c = r->connection;
char *remote;
char *parse_remote;
char *eos;
unsigned char *addrbyte;
if (!config->header_name) {
return DECLINED;
}
if (!remote) {
return OK;
}
while (remote) {
/* verify c->peer_addr is trusted if there is a trusted proxy list
*/
if (config->proxymatch_ip) {
int i;
break;
}
}
break;
}
}
}
else {
*(parse_remote++) = '\0';
}
while (*parse_remote == ' ') {
++parse_remote;
}
*(eos--) = '\0';
}
if (eos < parse_remote) {
if (remote) {
}
else {
}
break;
}
/* We map as IPv4 rather than IPv6 for equivilant host names
* or IPV4OVERIPV6
*/
APR_IPV4_ADDR_OK, r->pool);
if (rv != APR_SUCCESS) {
"RemoteIP: Header %s value of %s cannot be parsed "
"as a client IP",
if (remote) {
}
else {
}
break;
}
/* For intranet (Internal proxies) ignore all restrictions below */
if (!internal
/* For internet (non-Internal proxies) deny all
* 10.0.0.0/8 169.254.0.0/16 192.168.0.0/16
* 127.0.0.0/8 172.16.0.0/12
*/
&& (addrbyte[0] == 10
|| addrbyte[0] == 127
#if APR_HAVE_IPV6
/* For internet (non-Internal proxies) we translated
* IPv4-over-IPv6-mapped addresses as IPv4, above.
* Accept only Global Unicast 2000::/3 defined by RFC4291
*/
#endif
)) {
"RemoteIP: Header %s value of %s appears to be "
"a private IP or nonsensical. Ignored",
if (remote) {
}
else {
}
break;
}
/* save away our results */
if (!req) {
}
/* Set peer_ip string */
if (!internal) {
if (proxy_ips) {
}
else {
}
}
}
/* Nothing happened? */
if (!req) {
return OK;
}
if (req->proxied_remote) {
}
else {
}
if (config->proxies_header_name) {
}
}
? "Using %s as client's IP by proxies %s"
: "Using %s as client's IP by internal proxies",
return OK;
}
static const command_rec remoteip_cmds[] =
{
"Specifies a request header to trust as the client IP, "
"e.g. X-Forwarded-For"),
"Specifies a request header to record proxy IP's, "
"e.g. X-Forwarded-By; if not given then do not record"),
"Specifies one or more proxies which are trusted "
"to present IP headers"),
"Specifies one or more internal (transparent) proxies "
"which are trusted to present IP headers"),
"The filename to read the list of trusted proxies, "
"see the RemoteIPTrustedProxy directive"),
"The filename to read the list of internal proxies, "
"see the RemoteIPInternalProxy directive"),
{ NULL }
};
static void register_hooks(apr_pool_t *p)
{
}
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 */
};