mod_geoip2_1.2.8/ 000775 000775 000024 00000000000 12073026120 013402 5 ustar 00bz staff 000000 000000 mod_geoip2_1.2.8/Changes 000664 000775 000024 00000011010 12073026120 014666 0 ustar 00bz staff 000000 000000 1.2.8 Jan 8th 2013
- Add GeoIPUseUseFirstNunPrivateXForwardedForIP option ( Boris Zentner )
- Support Aapche 2.4 ( Boris Zentner )
- Use GeoIP_id_by_addr_v6 instead of GeoIP_country_id_by_addr_v6 ( Boris Zentner )
- Include util_script.h to silence warning about ap_add_common_vars ( Boris Zentner )
1.2.7 Aug 23th 2011
- Add support for GEOIP_NETSPEED_REV1 ( Boris Zentner )
- Experimental support for GEOIP_COUNTRY_EDITION_V6 ( Boris Zentner )
- Add GEOIP_DOMAIN_EDITION support ( Boris Zentner )
1.2.6 Sep 11th 2008
- GEOIP_METRO_CODE replace the depreciated GEOIP_DMA_CODE ( Boris Zentner )
1.2.5 Aug 13th 2008
! Fix GEOIP_REGION and GEOIP_COUNTRY_CODE when used with the GeoIPRegion database. Both are only set if a region or country was found. Previously a empty string was assigned to both ( Boris Zentner )
- Add GEOIP_REGION_NAME for City and Region databases ( Boris Zentner )
1.2.4 Jun 10th 2008
! mod_geoip2 has sets GEOIP_COUNTRY_CODE to -- for unknown countries when used with the country database. But for any other database ( City for example ) GEOIP_COUNTRY_CODE is unset for unknown countries. This is fixed now. Same for GEOIP_CONTINENT_CODE and GEOIP_COUNTRY_NAME. ( Boris Zentner )
- Add GEOIP_ADDR. That's the address used to compute the geoip information. Exported as env, notes or both as usual ( Jason Caldwell )
- Try to run always before mod_setenvif and mod_rewrite. ( Boris Zentner )
1.2.3 Apr 26th 2008
- Skip files that we can not open for some reason ( permission/typo ). Check and skip empty slots in geoip_header_parser ( Boris Zentner )
- Slight performance increase - don't make per_dir ap_get_module_config call where we return DECLINED because cfg->GeoIPEnabled is true (Guenter Knauf)
- NetWare/Win32 compilation fixes, since can't declare vars in middle of code (Guenter Knauf)
1.2.2 Mar 18th 2008
- Fix race condition for IO based caches like Standard. MMapCache and MemoryCache are not affected. ( Boris Zentner )
1.2.1 Dec 17th 2007
! Notice, that all directives are _only_ valid in server context. Expect GeoIPEnabled. Check you configuraion with apachectl configtest ( Boris Zentner )
- Added MMapCache option (Boris Zentner)
- Change GeoIPEnabled from a serverwide option to a server/directory/location keyword. (Boris Zentner)
- Fix a small memleak per child. Allocated in geoip_child_init free in geoip_cleanup (Boris Zentner)
- GeoIP databases get used serverwide now. Not per child. See the README. (Boris Zentner)
- Update README with more examples (Boris Zentner)
- Added support for UTF8 output for GeoIP City databases (Boris Zentner)
1.2.0 Aug 30th 2007
- Fix segfault issue if GeoIP.dat file cannot be opened (Vladimir Sedlacek)
- Added support for GEOIP_CONTINENT_CODE for GeoIP Country and City (Frank Mather)
- Added GeoIPScanProxyHeaders directive to handle X-Forwarded-For headers (Frank Mather)
- Updated documentation to specify that GeoIPFlags need to be passed
as second parameter to GeoIPDBFile, instead of using the GeoIPFlags directive
1.1.8 Apr 28th 2006
- Updated README file with GeoIPFlags docs and performance tips
- Added apr_strings.h include (Dann Frazier, Fixes Debian #357387)
- Added support for IndexCache
1.1.7 Aug 1st 2005
- Copied docs in mod_geoip1.3 in README on how to redirect and block by country
- Fixed Garbage characters appearing in GeoIP Postal Code field, this
bug was introduced in 1.1.3
1.1.6 May 17th 2005
- Fixed empty fields for GeoIP Region fields, this bug
was introduced in 1.1.3
1.1.5 Apr 19th 2005
- Removed dependence on DNS resolver for GeoIP Region and Netspeed databases
1.1.4 Dec 23rd 2004
- Fixed Garbage characters appearing in GeoIP City/Region field, this
bug was introduced in 1.1.3
1.1.3 Dec 9th 2004
- Added support for GeoIPOutput
- Changed command setup to AP_INIT_TAKE12 from AP_INIT_TAKE1 GeoIPDBFile (merv)
- Memory Leak fix when using GeoIP Region database
- Memory Leak fix when using GeoIP City database (Shane Nelson)
1.1.2 Aug 12th 2004
- Added support for GeoIP Netspeed Edition ( Frank Mather )
- Added support for GeoIP City setting GEOIP_DMA_CODE, GEOIP_AREA_CODE, GEOIP_LATITUDE,
GEOIP_LONGITUDE, and GEOIP_POSTAL_CODE ( Frank Mather )
1.1.1 Jul 12th 2004
- Added more documentation for using from PHP
- Fixed compile errors and warnings
1.1.0 Apr 19th 2004
- Added support for GeoIP Region, City, ISP and Organization ( Frank Mather )
1.0.6 Aug 30th 2002
- Added GeoIP_delete upon cleanup ( Corris Randall )
1.0.5 Aug 29th 2002
- Initial Release ( Corris Randall )
mod_geoip2_1.2.8/INSTALL 000644 000775 000024 00000003760 12073026120 014437 0 ustar 00bz staff 000000 000000 ===========================================================================
Requirements:
Apache 2.0.40 or higher installed If using RPM, the httpd-devel package containing apxs may need to be installed
GeoIP 1.4.3 or higher installed, download from http://maxmind.com/download/geoip/api/c
===========================================================================
To build mod_geoip as a dynamically loadable module:
apxs -i -a -L/usr/local/lib -I/usr/local/include -lGeoIP -c mod_geoip.c
-I/usr/local/include is where the GeoIP.h header file is installed
-L/usr/local/lib is where the libGeoIP library is located
This will put the correct LoadModule statement.
You will need to add:
===========================================================================
Configuration
To enable the module, place
GeoIPEnable On
inside your httpd.conf file. ( You don't have to have the block,
but it's always a good idea.
( You can optionally specify the data file by using:
GeoIPEnable On
GeoIPDBFile /usr/tmp/GeoIP.dat
)
See the README file for more details on the configuration
===========================================================================
Troubleshooting
On RedHat 9, apxs places
LoadModule geoip_module /usr/lib/httpd/modules/mod_geoip.so
Inside a
Block.
If mod_geoip doesn't work, try taking the LoadModule geoip_module line outside
the block.
If you get the following errors:
parse error before "geoip_module"
warning: data definition has no type or storage class
Or
syntax error before "geoip_module"
Make sure that the apxs script belongs to the Apache server you are using.
These error messages result from using a Apache 1.3 apxs script with
a Apache 2.x server.
If you get a "libGeoIP.so.1: cannot open shared object file: No such file or
directory" error, add /usr/local/lib to /etc/ld.so.conf then run
/sbin/ldconfig /etc/ld.so.conf
mod_geoip2_1.2.8/mod_geoip.c 000664 000775 000024 00000122236 12073026120 015516 0 ustar 00bz staff 000000 000000 /* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2004 MaxMind LLC. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* MaxMind (http://www.maxmind.com/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "MaxMind" and "GeoIP" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact support@maxmind.com.
*
* 5. Products derived from this software may not be called "GeoIP",
* nor may "MaxMind" appear in their name, without prior written
* permission of the MaxMind.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
*/
/* geoip module
*
* Version 1.2.8
*
* This module sets an environment variable to the remote country
* based on the requestor's IP address. It uses the GeoIP library
* to lookup the country by IP address.
*
* Copyright 2004, MaxMind LLC
* July 12th 2004
*
* Initial port Contributed by Corris Randall
*
*/
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "ap_config.h"
#include "apr_strings.h"
#include "util_script.h"
#include
#include
#include
typedef struct {
int GeoIPEnabled;
} geoip_dir_config_rec;
typedef struct {
GeoIP **gips;
int numGeoIPFiles;
char **GeoIPFilenames;
int GeoIPEnabled;
int GeoIPEnableUTF8;
char GeoIPOutput;
int GeoIPFlags;
int *GeoIPFlags2;
int scanProxyHeaders;
int proxyHeaderMode;
} geoip_server_config_rec;
static const int GEOIP_PROXY_HEADER_MODE_FIRST_IP = 0;
static const int GEOIP_PROXY_HEADER_MODE_LAST_IP = 1;
static const int GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP = 2;
static const int GEOIP_PROXY_HEADER_MODE_DEFAULT = 0;
static const int GEOIP_NONE = 0;
static const int GEOIP_DEFAULT = 1;
static const int GEOIP_NOTES = 2;
static const int GEOIP_ENV = 4;
static const int GEOIP_ALL = 6;
static const int GEOIP_INIT = 7;
static const int GEOIP_UNKNOWN = -1;
char metrocodestr[100];
char areacodestr[100];
char latstr[100];
char lonstr[100];
const char *netspeedstring;
module AP_MODULE_DECLARE_DATA geoip_module;
uint32_t _private_ipv4_networks[] = {
167772160U, 184549375U, // 10.0.0.0/8
2130706432U, 2147483647U, // 127.0.0.1/8
2886729728U, 2887778303U, // 172.16.0.0/12
3221225984U, 3221226239U, // 192.0.2.0/24
3227017984U, 3227018239U, // 192.88.99.0/24
3232235520U, 3232301055U, // 192.168.0.0/16
2851995648U, 2852061183U, // 169.254.0.0/16
0U, 0U
};
static int _is_private(uint32_t ipnum)
{
uint32_t min, max;
uint32_t *p = _private_ipv4_networks;
while ((min = *p++)) {
max = *p++;
if (ipnum < min || ipnum > max)
continue;
return 1;
}
return 0;
}
char *_get_ip_from_xff(const char *xffheader)
{
char *xff = strdup(xffheader);
char *xff_ip, *break_ptr;
uint32_t ipnum;
if (xff) {
for (xff_ip = strtok_r(xff, " \t,", &break_ptr); xff_ip;
xff_ip = strtok_r(NULL, " \t,", &break_ptr)) {
if (1 != inet_pton(AF_INET, xff_ip, &ipnum))
continue;
ipnum = htonl(ipnum);
if (!_is_private(ipnum)) {
char *found = strdup(xff_ip);
free(xff);
return found;
}
}
free(xff);
}
return NULL;
}
/* create a disabled directory entry */
static void *geoip_create_dir_config(apr_pool_t * p, char *d)
{
geoip_dir_config_rec *dcfg;
dcfg =
(geoip_dir_config_rec *) apr_pcalloc(p, sizeof(geoip_dir_config_rec));
dcfg->GeoIPEnabled = 0;
return dcfg;
}
/* create a standard disabled server entry */
static void *create_geoip_server_config(apr_pool_t * p, server_rec * d)
{
geoip_server_config_rec *conf =
apr_pcalloc(p, sizeof(geoip_server_config_rec));
if (!conf) {
return NULL;
}
conf->gips = NULL;
conf->numGeoIPFiles = 0;
conf->GeoIPFilenames = NULL;
conf->GeoIPEnabled = 0;
conf->GeoIPEnableUTF8 = 0;
conf->GeoIPOutput = GEOIP_INIT;
conf->GeoIPFlags = GEOIP_STANDARD;
conf->GeoIPFlags2 = NULL;
conf->scanProxyHeaders = 0;
conf->proxyHeaderMode = 0;
return (void *)conf;
}
static apr_status_t geoip_cleanup(void *cfgdata)
{
int i;
geoip_server_config_rec *cfg = (geoip_server_config_rec *) cfgdata;
if (cfg->gips) {
for (i = 0; i < cfg->numGeoIPFiles; i++) {
if (cfg->gips[i]) {
GeoIP_delete(cfg->gips[i]);
cfg->gips[i] = NULL;
}
}
free(cfg->gips);
cfg->gips = NULL;
}
return APR_SUCCESS;
}
/* initialize geoip once per server ( even virtal server! ) */
static void geoip_server_init(apr_pool_t * p, server_rec * s)
{
geoip_server_config_rec *cfg;
int i;
cfg = (geoip_server_config_rec *)
ap_get_module_config(s->module_config, &geoip_module);
if (!cfg->gips) {
if (cfg->GeoIPFilenames != NULL) {
cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles);
for (i = 0; i < cfg->numGeoIPFiles; i++) {
cfg->gips[i] =
GeoIP_open(cfg->GeoIPFilenames[i],
(cfg->GeoIPFlags2[i] ==
GEOIP_UNKNOWN) ? cfg->GeoIPFlags
: cfg->GeoIPFlags2[i]);
if (cfg->gips[i]) {
if (cfg->GeoIPEnableUTF8) {
GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
}
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
s,
"[mod_geoip]: Error while opening data file %s",
cfg->GeoIPFilenames[i]);
continue;
}
}
} else {
cfg->gips = malloc(sizeof(GeoIP *));
cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
if (!cfg->gips[0]) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"[mod_geoip]: Error while opening data file");
}
cfg->numGeoIPFiles = 1;
}
}
apr_pool_cleanup_register(p, (void *)cfg, geoip_cleanup, geoip_cleanup);
}
static void geoip_child_init(apr_pool_t * p, server_rec * s)
{
geoip_server_config_rec *cfg;
int i, flags;
cfg = (geoip_server_config_rec *)
ap_get_module_config(s->module_config, &geoip_module);
if (cfg->gips) {
if (cfg->GeoIPFilenames != NULL) {
for (i = 0; i < cfg->numGeoIPFiles; i++) {
flags =
(cfg->GeoIPFlags2[i] ==
GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i];
if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE))
continue;
if (cfg->gips[i]) {
GeoIP_delete(cfg->gips[i]);
}
cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], flags);
if (cfg->gips[i]) {
if (cfg->GeoIPEnableUTF8) {
GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
}
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
s,
"[mod_geoip]: Error while opening data file %s",
cfg->GeoIPFilenames[i]);
continue;
}
}
} else {
if (cfg->gips[0])
GeoIP_delete(cfg->gips[0]);
cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
if (!cfg->gips[0]) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"[mod_geoip]: Error while opening data file");
}
cfg->numGeoIPFiles = 1;
}
}
}
/* map into the first apache */
static int
geoip_post_config(apr_pool_t * p, apr_pool_t * plog,
apr_pool_t * ptemp, server_rec * s)
{
geoip_server_init(p, s);
return OK;
}
static int geoip_header_parser(request_rec * r);
static int geoip_post_read_request(request_rec * r)
{
geoip_server_config_rec *cfg;
cfg = ap_get_module_config(r->server->module_config, &geoip_module);
if (!cfg)
return DECLINED;
if (!cfg->GeoIPEnabled)
return DECLINED;
return geoip_header_parser(r);
}
static int geoip_per_dir(request_rec * r)
{
geoip_dir_config_rec *dcfg;
geoip_server_config_rec *cfg =
ap_get_module_config(r->server->module_config, &geoip_module);
if (cfg && cfg->GeoIPEnabled)
return DECLINED;
dcfg = ap_get_module_config(r->per_dir_config, &geoip_module);
if (!dcfg)
return DECLINED;
if (!dcfg->GeoIPEnabled)
return DECLINED;
return geoip_header_parser(r);
}
char *_get_client_ip(request_rec * r)
{
# if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER == 4
return r->connection->client_ip;
# else
return r->connection->remote_ip;
#endif
}
static int geoip_header_parser(request_rec * r)
{
char *orgorisp;
char *ipaddr;
char *free_me = NULL;
short int country_id;
const char *continent_code;
const char *country_code;
const char *country_name;
const char *region_name;
geoip_server_config_rec *cfg;
unsigned char databaseType;
GeoIPRecord *gir;
GeoIPRegion *giregion;
int i;
int netspeed;
/* For splitting proxy headers */
char *ipaddr_ptr = NULL;
char *comma_ptr;
cfg = ap_get_module_config(r->server->module_config, &geoip_module);
if (!cfg)
return DECLINED;
if (!cfg->scanProxyHeaders) {
ipaddr = _get_client_ip(r);
} else {
ap_add_common_vars(r);
if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP");
} else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env,
"HTTP_X_FORWARDED_FOR");
} else if (apr_table_get(r->headers_in, "X-Forwarded-For")) {
ipaddr_ptr =
(char *)apr_table_get(r->headers_in, "X-Forwarded-For");
} else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) {
ipaddr_ptr =
(char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR");
}
if (!ipaddr_ptr) {
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
r->server,
"[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR.");
ipaddr = _get_client_ip(r);
} else {
/* Found XFF like header */
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr);
if (cfg->proxyHeaderMode ==
GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) {
ipaddr = free_me = _get_ip_from_xff(ipaddr_ptr);
if (!ipaddr)
ipaddr = _get_client_ip(r);
} else {
ipaddr = free_me = (char *)calloc(8 * 4 + 7 + 1, sizeof(char));
/* proxyHeaderMode is
* GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP
*/
/*
* Check to ensure that the HTTP_CLIENT_IP or
* X-Forwarded-For header is not a comma separated
* list of addresses, which would cause mod_geoip to
* return no country code. If the header is a comma
* separated list, return the first IP address in the
* list, which is (hopefully!) the real client IP.
*/
if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) {
comma_ptr = strrchr(ipaddr_ptr, ',');
if (comma_ptr) {
/* skip over whitespace */
ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t");
}
}
strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7);
comma_ptr = strchr(ipaddr, ',');
if (comma_ptr != 0)
*comma_ptr = '\0';
}
}
}
/* this block should be removed! */
#if 1
if (!cfg->gips) {
if (cfg->GeoIPFilenames != NULL) {
cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles);
for (i = 0; i < cfg->numGeoIPFiles; i++) {
cfg->gips[i] =
GeoIP_open(cfg->GeoIPFilenames[i],
(cfg->GeoIPFlags2[i] ==
GEOIP_UNKNOWN) ? cfg->GeoIPFlags
: cfg->GeoIPFlags2[i]);
if (cfg->gips[i]) {
if (cfg->GeoIPEnableUTF8) {
GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
}
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
r->server,
"[mod_geoip]: Error while opening data file %s",
cfg->GeoIPFilenames[i]);
return DECLINED;
}
}
} else {
cfg->gips = malloc(sizeof(GeoIP *));
cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
if (!cfg->gips[0]) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
r->server,
"[mod_geoip]: Error while opening data file");
return DECLINED;
}
cfg->numGeoIPFiles = 1;
}
}
#endif
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_set(r->notes, "GEOIP_ADDR", ipaddr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_set(r->subprocess_env, "GEOIP_ADDR", ipaddr);
}
for (i = 0; i < cfg->numGeoIPFiles; i++) {
/*
* skip database handles that can not be opned for some
* reason
*/
if (cfg->gips[i] == NULL)
continue;
databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value"
* in case file not
* found */
switch (databaseType) {
case GEOIP_NETSPEED_EDITION_REV1:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
if (orgorisp != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_NETSPEED", orgorisp);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_NETSPEED", orgorisp);
}
}
break;
case GEOIP_NETSPEED_EDITION:
netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr);
if (netspeed == GEOIP_UNKNOWN_SPEED) {
netspeedstring = "unknown";
} else if (netspeed == GEOIP_DIALUP_SPEED) {
netspeedstring = "dialup";
} else if (netspeed == GEOIP_CABLEDSL_SPEED) {
netspeedstring = "cabledsl";
} else if (netspeed == GEOIP_CORPORATE_SPEED) {
netspeedstring = "corporate";
}
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_NETSPEED", netspeedstring);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_NETSPEED", netspeedstring);
}
break;
case GEOIP_COUNTRY_EDITION_V6:
/* Get the Country ID */
country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr);
if (country_id > 0) {
/* Lookup the Code and the Name with the ID */
continent_code = GeoIP_country_continent[country_id];
country_code = GeoIP_country_code[country_id];
country_name = GeoIP_country_name[country_id];
if (cfg->numGeoIPFiles == 0) {
cfg->numGeoIPFiles = 0;
}
if (cfg->GeoIPFilenames == 0) {
cfg->GeoIPFilenames = 0;
}
/* Set it for our user */
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes,
"GEOIP_CONTINENT_CODE_V6", continent_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_CODE_V6", country_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_NAME_V6", country_name);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_CONTINENT_CODE_V6", continent_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_CODE_V6", country_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_NAME_V6", country_name);
}
}
break;
case GEOIP_COUNTRY_EDITION:
/* Get the Country ID */
country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr);
if (country_id > 0) {
/* Lookup the Code and the Name with the ID */
continent_code = GeoIP_country_continent[country_id];
country_code = GeoIP_country_code[country_id];
country_name = GeoIP_country_name[country_id];
if (cfg->numGeoIPFiles == 0) {
cfg->numGeoIPFiles = 0;
}
if (cfg->GeoIPFilenames == 0) {
cfg->GeoIPFilenames = 0;
}
/* Set it for our user */
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes,
"GEOIP_CONTINENT_CODE", continent_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_CODE", country_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_NAME", country_name);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_CONTINENT_CODE", continent_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_CODE", country_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_NAME", country_name);
}
}
break;
case GEOIP_REGION_EDITION_REV0:
case GEOIP_REGION_EDITION_REV1:
giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr);
if (giregion != NULL) {
region_name = NULL;
if (giregion->country_code[0]) {
region_name =
GeoIP_region_name_by_code
(giregion->country_code, giregion->region);
}
if (cfg->GeoIPOutput & GEOIP_NOTES) {
if (giregion->country_code[0]) {
apr_table_set(r->notes,
"GEOIP_COUNTRY_CODE",
giregion->country_code);
}
if (giregion->region[0]) {
apr_table_set(r->notes,
"GEOIP_REGION", giregion->region);
}
if (region_name != NULL) {
apr_table_set(r->notes,
"GEOIP_REGION_NAME", region_name);
}
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
if (giregion->country_code[0]) {
apr_table_set(r->subprocess_env,
"GEOIP_COUNTRY_CODE",
giregion->country_code);
}
if (giregion->region[0]) {
apr_table_set(r->subprocess_env,
"GEOIP_REGION", giregion->region);
}
if (region_name != NULL) {
apr_table_set(r->subprocess_env,
"GEOIP_REGION_NAME", region_name);
}
}
GeoIPRegion_delete(giregion);
}
break;
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr);
if (gir != NULL) {
if (gir->country_code != NULL) {
region_name =
GeoIP_region_name_by_code
(gir->country_code, gir->region);
}
sprintf(metrocodestr, "%d", gir->dma_code);
sprintf(areacodestr, "%d", gir->area_code);
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes,
"GEOIP_CONTINENT_CODE_V6",
gir->continent_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_CODE_V6", gir->country_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_NAME_V6", gir->country_name);
if (gir->region != NULL) {
apr_table_set(r->notes, "GEOIP_REGION_V6", gir->region);
if (region_name != NULL) {
apr_table_set(r->notes,
"GEOIP_REGION_NAME_V6", region_name);
}
}
if (gir->city != NULL) {
apr_table_set(r->notes, "GEOIP_CITY_V6", gir->city);
}
apr_table_setn(r->notes, "GEOIP_DMA_CODE_V6", metrocodestr);
apr_table_setn(r->notes,
"GEOIP_METRO_CODE_V6", metrocodestr);
apr_table_setn(r->notes, "GEOIP_AREA_CODE_V6", areacodestr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_CONTINENT_CODE_V6",
gir->continent_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_CODE_V6", gir->country_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_NAME_V6", gir->country_name);
if (gir->region != NULL) {
apr_table_set(r->subprocess_env,
"GEOIP_REGION_V6", gir->region);
if (region_name != NULL) {
apr_table_set
(r->subprocess_env,
"GEOIP_REGION_NAME_V6", region_name);
}
}
if (gir->city != NULL) {
apr_table_set(r->subprocess_env,
"GEOIP_CITY_V6", gir->city);
}
apr_table_setn(r->subprocess_env,
"GEOIP_DMA_CODE_V6", metrocodestr);
apr_table_setn(r->subprocess_env,
"GEOIP_METRO_CODE_V6", metrocodestr);
apr_table_setn(r->subprocess_env,
"GEOIP_AREA_CODE_V6", areacodestr);
}
sprintf(latstr, "%f", gir->latitude);
sprintf(lonstr, "%f", gir->longitude);
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_LATITUDE_V6", latstr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_LATITUDE_V6", latstr);
}
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_LONGITUDE_V6", lonstr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_LONGITUDE_V6", lonstr);
}
if (gir->postal_code != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_set(r->notes,
"GEOIP_POSTAL_CODE_V6", gir->postal_code);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_set(r->subprocess_env,
"GEOIP_POSTAL_CODE_V6", gir->postal_code);
}
}
GeoIPRecord_delete(gir);
}
break;
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr);
if (gir != NULL) {
if (gir->country_code != NULL) {
region_name =
GeoIP_region_name_by_code
(gir->country_code, gir->region);
}
sprintf(metrocodestr, "%d", gir->dma_code);
sprintf(areacodestr, "%d", gir->area_code);
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes,
"GEOIP_CONTINENT_CODE", gir->continent_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_CODE", gir->country_code);
apr_table_setn(r->notes,
"GEOIP_COUNTRY_NAME", gir->country_name);
if (gir->region != NULL) {
apr_table_set(r->notes, "GEOIP_REGION", gir->region);
if (region_name != NULL) {
apr_table_set(r->notes,
"GEOIP_REGION_NAME", region_name);
}
}
if (gir->city != NULL) {
apr_table_set(r->notes, "GEOIP_CITY", gir->city);
}
apr_table_setn(r->notes, "GEOIP_DMA_CODE", metrocodestr);
apr_table_setn(r->notes, "GEOIP_METRO_CODE", metrocodestr);
apr_table_setn(r->notes, "GEOIP_AREA_CODE", areacodestr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_CONTINENT_CODE", gir->continent_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_CODE", gir->country_code);
apr_table_setn(r->subprocess_env,
"GEOIP_COUNTRY_NAME", gir->country_name);
if (gir->region != NULL) {
apr_table_set(r->subprocess_env,
"GEOIP_REGION", gir->region);
if (region_name != NULL) {
apr_table_set
(r->subprocess_env,
"GEOIP_REGION_NAME", region_name);
}
}
if (gir->city != NULL) {
apr_table_set(r->subprocess_env,
"GEOIP_CITY", gir->city);
}
apr_table_setn(r->subprocess_env,
"GEOIP_DMA_CODE", metrocodestr);
apr_table_setn(r->subprocess_env,
"GEOIP_METRO_CODE", metrocodestr);
apr_table_setn(r->subprocess_env,
"GEOIP_AREA_CODE", areacodestr);
}
sprintf(latstr, "%f", gir->latitude);
sprintf(lonstr, "%f", gir->longitude);
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_LATITUDE", latstr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE", latstr);
}
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_LONGITUDE", lonstr);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_LONGITUDE", lonstr);
}
if (gir->postal_code != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_set(r->notes,
"GEOIP_POSTAL_CODE", gir->postal_code);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_set(r->subprocess_env,
"GEOIP_POSTAL_CODE", gir->postal_code);
}
}
GeoIPRecord_delete(gir);
}
break;
case GEOIP_ORG_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
if (orgorisp != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_ORGANIZATION", orgorisp);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env,
"GEOIP_ORGANIZATION", orgorisp);
}
}
break;
case GEOIP_ISP_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
if (orgorisp != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_ISP", orgorisp);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env, "GEOIP_ISP", orgorisp);
}
}
break;
case GEOIP_DOMAIN_EDITION:
orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
if (orgorisp != NULL) {
if (cfg->GeoIPOutput & GEOIP_NOTES) {
apr_table_setn(r->notes, "GEOIP_DOMAIN", orgorisp);
}
if (cfg->GeoIPOutput & GEOIP_ENV) {
apr_table_setn(r->subprocess_env, "GEOIP_DOMAIN", orgorisp);
}
}
break;
}
}
if (free_me)
free(free_me);
return OK;
}
static const char *geoip_use_first_non_private_x_forwarded_for_ip(cmd_parms *
cmd,
void *dummy,
int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP :
GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_use_first_x_forwarded_for_ip(cmd_parms * cmd,
void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_FIRST_IP :
GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_use_last_x_forwarded_for_ip(cmd_parms * cmd,
void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->proxyHeaderMode =
arg ? GEOIP_PROXY_HEADER_MODE_LAST_IP : GEOIP_PROXY_HEADER_MODE_DEFAULT;
return NULL;
}
static const char *geoip_scanproxy(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->scanProxyHeaders = arg;
return NULL;
}
static const char *set_geoip_enable(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf;
/* is per directory config? */
if (cmd->path) {
geoip_dir_config_rec *dcfg = dummy;
dcfg->GeoIPEnabled = arg;
return NULL;
}
/* no then it is server config */
conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->GeoIPEnabled = arg;
return NULL;
}
static const char *set_geoip_enable_utf8(cmd_parms * cmd, void *dummy, int arg)
{
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!conf)
return "mod_geoip: server structure not allocated";
conf->GeoIPEnableUTF8 = arg;
return NULL;
}
static const char *set_geoip_filename(cmd_parms * cmd, void *dummy,
const char *filename, const char *arg2)
{
int i;
geoip_server_config_rec *conf = (geoip_server_config_rec *)
ap_get_module_config(cmd->server->module_config, &geoip_module);
if (!filename)
return NULL;
i = conf->numGeoIPFiles;
conf->numGeoIPFiles++;
conf->GeoIPFilenames =
realloc(conf->GeoIPFilenames, conf->numGeoIPFiles * sizeof(char *));
conf->GeoIPFilenames[i] = (char *)apr_pstrdup(cmd->pool, filename);
conf->GeoIPFlags2 =
realloc(conf->GeoIPFlags2, conf->numGeoIPFiles * sizeof(int));
if (arg2 == NULL) {
conf->GeoIPFlags2[i] = GEOIP_UNKNOWN;
} else if (!strcmp(arg2, "Standard")) {
conf->GeoIPFlags2[i] = GEOIP_STANDARD;
} else if (!strcmp(arg2, "MemoryCache")) {
conf->GeoIPFlags2[i] = GEOIP_MEMORY_CACHE;
} else if (!strcmp(arg2, "CheckCache")) {
conf->GeoIPFlags2[i] = GEOIP_CHECK_CACHE;
} else if (!strcmp(arg2, "IndexCache")) {
conf->GeoIPFlags2[i] = GEOIP_INDEX_CACHE;
} else if (!strcmp(arg2, "MMapCache")) {
conf->GeoIPFlags2[i] = GEOIP_MMAP_CACHE;
}
return NULL;
}
static const char *set_geoip_output(cmd_parms * cmd, void *dummy,
const char *arg)
{
geoip_server_config_rec *cfg =
(geoip_server_config_rec *) ap_get_module_config(cmd->server->
module_config,
&geoip_module);
if (cfg->GeoIPOutput & GEOIP_DEFAULT) {
/* was set to default, clear so can be reset with user specified values */
cfg->GeoIPOutput = GEOIP_NONE;
}
if (!strcmp(arg, "Notes")) {
cfg->GeoIPOutput |= GEOIP_NOTES;
} else if (!strcmp(arg, "Env")) {
cfg->GeoIPOutput |= GEOIP_ENV;
} else if (!strcmp(arg, "All")) {
cfg->GeoIPOutput |= GEOIP_ALL;
}
return NULL;
}
static void *make_geoip(apr_pool_t * p, server_rec * d)
{
geoip_server_config_rec *dcfg;
dcfg =
(geoip_server_config_rec *) apr_pcalloc(p,
sizeof
(geoip_server_config_rec));
dcfg->gips = NULL;
dcfg->numGeoIPFiles = 0;
dcfg->GeoIPFilenames = NULL;
dcfg->GeoIPEnabled = 0;
dcfg->GeoIPEnableUTF8 = 0;
dcfg->GeoIPOutput = GEOIP_INIT;
dcfg->GeoIPFlags = GEOIP_STANDARD;
dcfg->GeoIPFlags2 = NULL;
return dcfg;
}
static const command_rec geoip_cmds[] = {
AP_INIT_FLAG("GeoIPScanProxyHeaders", geoip_scanproxy, NULL, RSRC_CONF,
"Get IP from HTTP_CLIENT IP or X-Forwarded-For"),
AP_INIT_FLAG("GeoIPUseFirstNonPrivateXForwardedForIP",
geoip_use_first_non_private_x_forwarded_for_ip, NULL,
RSRC_CONF,
"For more IP's in X-Forwarded-For, use the first non private IP"),
AP_INIT_FLAG("GeoIPUseFirstXForwardedForIP",
geoip_use_first_x_forwarded_for_ip, NULL, RSRC_CONF,
"For more IP's in X-Forwarded-For, use the first"),
AP_INIT_FLAG("GeoIPUseLastXForwardedForIP",
geoip_use_last_x_forwarded_for_ip, NULL, RSRC_CONF,
"For more IP's in X-Forwarded-For, use the last"),
AP_INIT_FLAG("GeoIPEnable", set_geoip_enable, NULL,
RSRC_CONF | OR_FILEINFO, "Turn on mod_geoip"),
AP_INIT_FLAG("GeoIPEnableUTF8", set_geoip_enable_utf8, NULL, RSRC_CONF,
"Turn on utf8 characters for city names"),
AP_INIT_TAKE12("GeoIPDBFile", set_geoip_filename, NULL, RSRC_CONF,
"Path to GeoIP Data File"),
AP_INIT_ITERATE("GeoIPOutput", set_geoip_output, NULL, RSRC_CONF,
"Specify output method(s)"),
{NULL}
};
static void geoip_register_hooks(apr_pool_t * p)
{
/* make sure we run before mod_rewrite's handler */
static const char *const aszSucc[] =
{ "mod_setenvif.c", "mod_rewrite.c", NULL };
/* we have two entry points, the header_parser hook, right before
* the authentication hook used for Dirctory specific enabled geoiplookups
* or right before directory rewrite rules.
*/
ap_hook_header_parser(geoip_per_dir, NULL, aszSucc, APR_HOOK_FIRST);
/* and the servectly wide hook, after reading the request. Perfecly
* suitable to serve serverwide mod_rewrite actions
*/
ap_hook_post_read_request(geoip_post_read_request, NULL, aszSucc,
APR_HOOK_MIDDLE);
/* setup our childs GeoIP database once for every child */
ap_hook_child_init(geoip_child_init, NULL, NULL, APR_HOOK_MIDDLE);
/* static const char * const list[]={ "mod_geoip.c", NULL }; */
/* mmap the database(s) into the master process */
ap_hook_post_config(geoip_post_config, NULL, NULL, APR_HOOK_MIDDLE);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA geoip_module = {
STANDARD20_MODULE_STUFF,
geoip_create_dir_config, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
make_geoip, /* create per-server config structures */
NULL, /* merge per-server config structures */
geoip_cmds, /* table of config file commands */
geoip_register_hooks /* register hooks */
};
mod_geoip2_1.2.8/README 000664 000775 000024 00000042011 12073026120 014260 0 ustar 00bz staff 000000 000000 mod_geoip2 1.2.8
----------------
The mod_geoip2 module embeds GeoIP database lookups into the Apache web
server. It is only capable of looking up the IP of a client that
connects to the web server, as opposed to looking up arbitrary
addresses.
Version
-------
The latest version of mod_geoip2 is version 1.2.8.
Installation
------------
You can [download
mod_geoip2](http://www.maxmind.com/download/geoip/api/mod_geoip2/) from
our download server. See the `INSTALL` file in the tarball for
installation details.
Overview
--------
The mod_geoip2 module uses the libGeoIP library to look up geolocation
information for a client as part of the http request process. This
module is free software, and is licensed under the [Apache
license](http://www.apache.org/licenses/LICENSE-2.0.html).
To compile and install this module, you must first install [libGeoIP
1.4.3](http://www.maxmind.com/download/geoip/api/c/) or newer.
The mod_geoip2 module takes effect either during request header parsing
phase or the post read request phase, depending on whether it is
configured for server-wide use or for a specific location/directory.
When enabled, the module looks at the incoming IP address and sets some
variables which provide geolocation information for that IP. The
variables it set depend on the specific GeoIP database being used
(Country, City, ISP, etc.). These variables can be set in either the
request notes table, the environment or both depending on the server
configuration.
Configuration
-------------
GeoIP configuration directives can be placed in either an `.htaccess`
file or in the main server config. After installing the module, make
sure that
GeoIPEnable On
is set in your Apache configuration file. This will call the GeoIP
Country database from its default location (e.g.
/usr/local/share/GeoIP/GeoIP.dat)
If you want to specify options, for example to use a different database
or to pass caching options, you can use the `GeoIPDBFile` directive:
### File and Caching Directives
GeoIPDBFile /path/to/GeoIP.dat [GeoIPFlag]
For example:
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPOrg.dat Standard
The default GeoIPFlag value is Standard, which does not perform any
caching, but uses the least memory. To turn on memory caching use:
GeoIPDBFile /path/to/GeoIP.dat MemoryCache
The memory cache option can use a large amount of memory. We recommend
that you use Memory Caching only for the smaller database files, such as
GeoIP Country and GeoIP ISP.
Another MemoryCache option is MMapCache, which uses the the `mmap`
system call to map the database file into memory.
If you would like the API to check to see if your local GeoIP files have
been updated, set the `CheckCache` flag:
GeoIPDBFile /path/to/GeoIP.dat CheckCache
Before making a call to the database, geoip will check the GeoIP.dat
file to see if it has changed. If it has it, then it will reload the
file. With this option, you do not have to restart Apache when you
update your GeoIP databases.
If you would like to turn on partial memory caching, use the
`IndexCache` flag:
GeoIPDBFile /path/to/GeoIP.dat IndexCache
The IndexCache option caches the most frequently accessed index portion
of the database, resulting in faster lookups than StandardCache, but
less memory usage than MemoryCache. This is especially useful for larger
databases such as GeoIP Organization and GeoIP City. For the GeoIP
Country, Region and Netspeed databases, setting the IndexCache option
just causes the C API to use the MemoryCache.
Currently, multiple GeoIPFlags options can not be combined.
### Enabling UTF-8 Output
You may change the output charset from ISO-8859-1 (Latin-1) to UTF-8 with
this directive:
GeoIPEnableUTF8 On
By default mod_geoip2 sets variables in both the notes table and
environment. For performance reasons you may want to set only the one
you use. To do so, use the `GeoIPOutput` configuration directive:
### Output Variable Location
GeoIPOutput Notes # Sets the Apache notes table only
GeoIPOutput Env # Sets environment variables only
GeoIPOutput All # Sets both (default behaviour)
### Proxy-Related Directives
By default, this module will simply look at the IP address of the
client. However, if the client is using a proxy, this will be the
address of the proxy. You can use the `GeoIPScanProxyHeaders` directive
to look at proxy-related headers.
GeoIPScanProxyHeaders On
When this is set, the module will look at several other sources for the
IP address, in this order:
- The `HTTP_CLIENT_IP` environment variable (set by Apache).
- The `HTTP_X_FORWARDED_FOR` environment variable (set by Apache).
- The `X-Forwarded-For` for header (set by a proxy).
- The `HTTP_REMOTE_ADDR` environment variable (set by Apache).
This module will use the first IP address it finds in one of these
locations *instead* of the IP address the client connected from.
Some of these variables may contain a comma-separate list of IP
addresses (when a client goes through multiple proxies). In this case,
the default behavior is to use the first IP address. You can set the
`GeoIPUseLastXForwardedForIP` directive to use the last address instead:
GeoIPUseLastXForwardedForIP On
Or use `GeoIPUseFirstNonPrivateXForwardedForIP` to use the first
non private IP Address.
GeoIPUseFirstNonPrivateXForwardedForIP On
Output Variables
----------------
As noted above, these variables can be set in either the Apache request
notes table, the environment, or both. The specific variables which are
set depend on the database you are using.
### GeoIP Country Edition Output Variables
Name
Description
GEOIP_ADDR
The address used to calculate the GeoIP output.
GEOIP_CONTINENT_CODE
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](http://dev.maxmind.com/faq/geoip#anonproxy).
- **A2** - a [satellite provider](http://dev.maxmind.com/faq/geoip#satellite).
- **EU** - an IP in a block used by multiple
[European](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
GEOIP_COUNTRY_NAME
The country name associated with the IP address.
### GeoIP Region Edition Output Variables
Name
Description
GEOIP_ADDR
The address used to calculate the GeoIP output.
GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](http://dev.maxmind.com/faq/geoip#anonproxy).
- **A2** - a [satellite provider](http://dev.maxmind.com/faq/geoip#satellite).
- **EU** - an IP in a block used by multiple
[European](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
GEOIP_REGION_NAME
The region name associated with the IP address.
GEOIP_REGION
A two character [ISO-3166-2](http://en.wikipedia.org/wiki/ISO_3166-2) or
[FIPS 10-4](http://en.wikipedia.org/wiki/FIPS_10-4) code for the
state/region associated with the IP address.
For the US and Canada, we return an ISO-3166-2 code. In addition to the
standard ISO codes, we may also return one of the following:
- **AA** - Armed Forces America
- **AE** - Armed Forces Europe
- **AP** - Armed Forces Pacific
We return a FIPS code for all other countries.
We provide a [CSV file which maps our region codes to region
names](http://dev.maxmind.com/static/maxmind-region-codes.csv). The columns are ISO country
code, region code (FIPS or ISO), and the region name.
### GeoIP City Edition Output Variables
Name
Description
GEOIP_ADDR
The address used to calculate the GeoIP output.
GEOIP_CONTINENT_CODE
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
GEOIP_COUNTRY_CODE
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](http://dev.maxmind.com/faq/geoip#anonproxy).
- **A2** - a [satellite provider](http://dev.maxmind.com/faq/geoip#satellite).
- **EU** - an IP in a block used by multiple
[European](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
GEOIP_REGION
A two character [ISO-3166-2](http://en.wikipedia.org/wiki/ISO_3166-2) or
[FIPS 10-4](http://en.wikipedia.org/wiki/FIPS_10-4) code for the
state/region associated with the IP address.
For the US and Canada, we return an ISO-3166-2 code. In addition to the
standard ISO codes, we may also return one of the following:
- **AA** - Armed Forces America
- **AE** - Armed Forces Europe
- **AP** - Armed Forces Pacific
We return a FIPS code for all other countries.
We provide a [CSV file which maps our region codes to region
names](http://dev.maxmind.com/static/maxmind-region-codes.csv). The columns are ISO country
code, region code (FIPS or ISO), and the region name.
GEOIP_REGION_NAME
The region name associated with the IP address.
GEOIP_CITY
The city or town name associated with the IP address. See our [list of
cities](http://www.maxmind.com/GeoIPCity-534-Location.csv) to see all
the possible return values. This list is updated on a regular basis.
GEOIP_METRO_CODE
The metro code associated with the IP address. These are only available
for IP addresses in the US. MaxMind returns the [same metro codes as the
Google AdWords
API](https://developers.google.com/adwords/api/docs/appendix/metrocodes).
GEOIP_AREA_CODE
The telephone area code associated with the IP address. These are only
available for IP addresses in the US.
GEOIP_LATITUDE
The latitude associated with the IP address.
GEOIP_LONGITUDE
The longitude associated with the IP address.
GEOIP_POSTAL_CODE
The postal code associated with the IP address. These are available for
some IP addresses in the US, Canada, Germany, and United Kingdom.
### GeoIP ISP Edition Output Variables
Name Description
------------- -----------------------------------------------------
GEOIP_ADDR The address used to calculate the GeoIP output.
GEOIP_ISP The name of the ISP associated with the IP address.
### GeoIP Organization Edition Output Variables
Name Description
--------------------- --------------------------------------------------------------
GEOIP_ADDR The address used to calculate the GeoIP output.
GEOIP_ORGANIZATION The name of the organization associated with the IP address.
### GeoIP Netspeed Edition Output Variables
Name
Description
GEOIP_ADDR
The address used to calculate the GeoIP output.
GEOIP_NETSPEED
The network speed associated with the IP address. This can be one of the
following values:
- **Dialup**
- **Cable/DSL**
- **Corporate**
- **Cellular**
### GeoIPv6 Edition (experimental) Output Variables
Name
Description
GEOIP_ADDR
The address used to calculate the GeoIP output.
GEOIP_CONTINENT_CODE_V6
A two-character code for the continent associated with the IP address.
The possible codes are:
- **AF** - Africa
- **AS** - Asia
- **EU** - Europe
- **NA** - North America
- **OC** - Oceania
- **SA** - South America
GEOIP_COUNTRY_CODE_V6
A two-character [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1)
country code for the country associated with the IP address. In addition
to the standard codes, we may also return one of the following:
- **A1** - an [anonymous proxy](http://dev.maxmind.com/faq/geoip#anonproxy).
- **A2** - a [satellite provider](http://dev.maxmind.com/faq/geoip#satellite).
- **EU** - an IP in a block used by multiple
[European](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
- **AP** - an IP in a block used by multiple [Asia/Pacific
region](http://dev.maxmind.com/faq/geoip#euapcodes) countries.
The **US** country code is returned for IP addresses associated with
overseas US military bases.
GEOIP_COUNTRY_NAME_V6
The country name associated with the IP address.
Examples
--------
Here are some examples of how you can use mod_geoip2.
### Redirecting a client based on country
This example show you how to redirect a client based on the country code
that GeoIP sets.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
# Redirect one country
RewriteEngine on
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CA$
RewriteRule ^(.*)$ http://www.canada.com$1 [R,L]
# Redirect multiple countries to a single page
RewriteEngine on
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(CA|US|MX)$
RewriteRule ^(.*)$ http://www.northamerica.com$1 [R,L]
### Blocking a client based on country
This example show you how to block clients based on the country code
that GeoIP sets.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
# ... place more countries here
Deny from env=BlockCountry
### Allowing clients based on country
This example show you how to allow only clients from specific countries.
GeoIPEnable On
GeoIPDBFile /path/to/GeoIP.dat
SetEnvIf GEOIP_COUNTRY_CODE US AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE CA AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE MX AllowCountry
# ... place more countries here
Deny from all
Allow from env=AllowCountry
### Server vs Directory context
All directives except GeoIPEnable are server config only, i.e., you type
it only once per server config. Otherwise the latest wins.
GeoIPEnable Off
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPCity.dat MemoryCache
GeoIPDBFile /usr/local/share/GeoIP/GeoIPOrg.dat MemoryCache
GeoIPEnable is useful in server or directory context. For example:
GeoIP is only available for a specific location:
GeoIPEnable Off
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
# GeoIP information is avail only inside /xxx
GeoIPEnable On
...
...
GeoIP is available for all locations:
GeoIPEnable On
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat MemoryCache
# This doesn't work, because it's already been enabled in the server-wide
# config!
GeoIPEnable On
GeoIPEnable Off
Memory Usage
------------
Starting at mod_geoip2 version 1.2.1, all Apache child processes share
the same database when you set the MemoryCache or MMapCache flag.
Memory usage is about the same as the database file size, no matter how
many child processes Apache spawns. The only thing to remember is ask
Apache to update if your database changes. Use the graceful restart
option to do so without stopping Apache.
Performance
-----------
For improved performance, you may want to enable mod_geoip only for
specific HTML pages. If you want to use the mod_geoip module site-wide,
you may still be able to only use it for HTML pages and not images. To
restrict the pages where mod_geoip2 is used, place the `GeoIPEnable On`
directive inside a , or directive, see:
[httpd.apache.org/docs/2.0/sections.html](http://httpd.apache.org/docs/2.0/sections.html)
Troubleshooting
---------------
If the module is not working, make sure that the httpd user (e.g.
nobody) has read access to the GeoIP database file(s) you are using.
If the GeoIP variables do not show up please make sure that the client
IP address is not on a private network such as 10.0.0.0/8, 172.16.0.0/12
or 192.168.0.0/16. GeoIP can only look up public IP addresses.
----
This file was generated by running
pandoc --from html --to markdown
Using http://dev.maxmind.com/geoip/mod_geoip2 as the HTML input.
mod_geoip2_1.2.8/README.php 000644 000775 000024 00000001275 12073026120 015053 0 ustar 00bz staff 000000 000000 To use from PHP, use something like:
GeoIP Country:
GeoIP Region:
GeoIP City:
==================================================
Redirection with PHP
$country_code = apache_note("GEOIP_COUNTRY_CODE");
if ( $country_code == "DE" )
{
header ("Location: http://www.google.de" );
}
else
{
header ("Location: http://www.yoursite.com" );
}