ProFTPD module mod_geoip2



The mod_geoip2 module uses the GeoIP library from MaxMind to look up various geographic information for a connecting client:

  https://github.com/maxmind/libmaxminddb
This information can be used to set access controls for the server.

This module is contained in the mod_geoip2.c file for ProFTPD 1.3.x, and is not compiled by default. Installation instructions are discussed here.

The most current version of mod_geoip2 can be found at:

  https://github.com/Castaglia/proftpd-mod_geoip2.git

This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com/.

Author

Please contact TJ Saunders <tj at castaglia.org> with any questions, concerns, or suggestions regarding this module.

Directives


GeoIPAllowFilter

Syntax: GeoIPAllowFilter filter1 pattern1 [filter2 pattern2 ...]
Default: none
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.3rc1 and later

The GeoIPAllowFilter directive is used to configure ACLs based on the geographic data provided by the GeoIP library.

Multiple GeoIPAllowFilter directives in the configuration are supported; if any filter matches the connecting client, the connection will be allowed.

The filter parameter specifies the GeoIP value to which to apply the configured pattern for matching. The possible filter values are:

The pattern parameter is case-insensitive regular expression that will be applied to the specified filter value, if available.

Note that as of proftpd-1.3.6rc3 and later, the GeoIPAllowFilter directive can also take a single parameter which specifies a SQL query (via mod_sql's SQLNamedQuery), which will be used to retrieve the filter and pattern values to use.

Examples:

  # Allow clients from Ireland
  GeoIPAllowFilter CountryCode IE

  # Reject clients connecting from North America or South America
  GeoIPDenyFilter Continent (NA|SA)
The following more complex configuration demonstrates what can be done using SQL querires:
  <IfModule mod_sql.c>
    ...
    SQLNamedQuery get-geo-allowed SELECT "filter_name, pattern FROM allowed_user_geo WHERE user_name = '%u'"
    SQLNamedQuery get-geo-denied SELECT "filter_name, pattern FROM denied_user_geo WHERE user_name = '%u'"
  </IfModule>

  <IfModule mod_geoip2.c>
    GeoIPEngine on

    GeoIPAllowFilter sql:/get-geo-allowed
    GeoIPDenyFilter sql:/get-geo-denied
  </IfModule>
The above assumes SQL tables with schema similar to the following (expressed using SQLite syntax):
  CREATE TABLE allowed_user_geo (
    user_name TEXT,
    filter_name TEXT,
    pattern TEXT
  );

  CREATE TABLE denied_user_geo (
    user_name TEXT,
    filter_name TEXT,
    pattern TEXT
  );

  # Note that we create separate indexes, to allow for multiple rows per user
  CREATE INDEX allowed_user_geo_name_idx ON allowed_user_geo (user_name);
  CREATE INDEX denied_user_geo_name_idx ON denied_user_geo (user_name);


GeoIPDenyFilter

Syntax: GeoIPDenyFilter filter1 pattern1 [filter2 pattern2 ...]
Default: none
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.3rc1 and later

The GeoIPDenyFilter directive is used to configure ACLs based on the geographic data provided by the GeoIP library.

Multiple GeoIPDenyFilter directives in the configuration are supported; if any filter matches the connecting client, the connection will be rejected.

Note that as of proftpd-1.3.6rc3 and later, the GeoIPDenyFilter directive can also take a single parameter which specifies a SQL query (via mod_sql's SQLNamedQuery), which will be used to retrieve the filter and pattern values to use.

See GeoIPAllowFilter for a description of the directive syntax and parameters.


GeoIPEngine

Syntax: GeoIPEngine on|off
Default: off
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.3rc1 and later

The GeoIPEngine directive enables or disables the module's lookup of geographic information for a connecting client, and subsequent enforcement of any configured ACLs.


GeoIPLog

Syntax: GeoIPLog file|"none"
Default: None
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.3rc1 and later

The GeoIPLog directive is used to specify a log file for mod_geoip2's reporting on a per-server basis. The file parameter given must be the full path to the file to use for logging.

Note that this path must not be to a world-writable directory and, unless AllowLogSymlinks is explicitly set to on (generally a bad idea), the path must not be a symbolic link.


GeoIPPolicy

Syntax: GeoIPPolicy "allow,deny"|"deny,allow"
Default: GeoIPPolicy allow,deny
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.5rc1 and later

The GeoIPPolicy directive determines whether the mod_geoip2 module will allow a connection by default or not.

If GeoIPPolicy is configured using "allow,deny" (which is the default setting), then the mod_geoip2 module will allow the connection, unless the connecting client is rejected by any GeoIPDenyFilter rules.

If GeoIPPolicy is configured using "deny,allow", then the mod_geoip2 module will reject any connection, unless the connecting client matches any configured GeoIPAllowFilter rules.


GeoIPTable

Syntax: GeoIPTable path [flags]
Default: None
Context: server config, <VirtualHost>, <Global>
Module: mod_geoip2
Compatibility: 1.3.3rc1 and later

The GeoIPTable directive is used to a GeoIP database file for use by the GeoIP library. The path parameter given must be the full path to the database file.

If no GeoIPTable directive is configured, then mod_geoip2 will not perform any geographical lookups.

Multiple GeoIPTable directives can be used to configure multiple different GeoIP database files for use at the same time.

Note that the flags parameter is currently supported for backward compatibility with mod_geoip, but is currently ignored.

Examples:

  GeoIPTable /path/to/GeoLite2-City.mmdb
  GeoIPTable /path/to/GeoLite2-Country.mmdb
  GeoIPTable /path/to/GeoLite2-ASN.mmdb


Installation

The mod_geoip2 module requires that the MaxMindDB library be installed. For including mod_geoip2 as a statically linked module:
  $ ./configure --with-modules=mod_geoip2
Alternatively, mod_geoip2 could be built as a DSO module:
  $ ./configure --with-shared=mod_geoip2
Then follow the usual steps:
  $ make
  $ make install
You may need to specify the location of the MaxMindDB header and library files in your configure command, e.g.:
  $ ./configure --with-modules=mod_geoip2 \
    --with-includes=/usr/local/maxminddb/include \
    --with-libraries=/usr/local/maxminddb/lib

Alternatively, if your proftpd was compiled with DSO support, you can use the prxs tool to build mod_geoip2 as a shared module:

  $ prxs -c -i -d mod_geoip2.c


Usage

mod_geoip Interactions
The mod_geoip2 module is meant to be, roughly, a drop-in replacement for the legacy mod_geoip module; it implements the same configuration directive, provides the same environment variables, etc. Thus mod_geoip2 will fail to start if it detects that the mod_geoip module is also being used. You must use only one of either mod_geoip or mod_geoip2 in ProFTPD, but not both.

Access Controls
If any GeoIPAllowFilter or GeoIPDenyFilter directives are configured, the mod_geoip2 module applies them against the geographic information retrieved from the GeoIP library. First any GeoIPAllowFilters are checked. If any of these filters matches the connecting client's information, the connection is allowed. Next, any GeoIPDenyFilters are checked. If any of these filters matches the connecting client's information, the connection is closed. Otherwise, the connection is allowed.

This means that if you wanted to reject connections from the US except for connections from California, you might use something like this:

  # Deny all connections from the US
  GeoIPDenyFilter CountryCode US

  # But allow connections from California
  GeoIPAllowFilter RegionCode CA

Environment Variables
The mod_geoip2 module will set the following environment variables whenever a client connects, assuming that the appropriate GeoIP tables have been configured and the values are known for the connecting client:

These values are also available in the session.notes table, under keys of the names above.

Example Configuration

  <IfModule mod_geoip2.c>
    GeoIPEngine on
    GeoIPLog /path/to/ftpd/geoip.log

    GeoIPTable /path/to/GeoLite2-City.mmdb

    # Add your GeoIPAllowFilter/GeoIPDenyFilter rules here
  </IfModule>

Logging
The mod_geoip2 module supports different forms of logging. The main module logging is done via the GeoIPLog directive. For debugging purposes, the module also uses trace logging, via the module-specific log channels:

Thus for trace logging, to aid in debugging, you would use the following in your proftpd.conf:
  TraceLog /path/to/ftpd/trace.log
  Trace geoip2:20
The geographic information retrieved from the GeoIP library for the connecting client is logged using this "geoip2" trace log channel. This trace logging can generate large files; it is intended for debugging use only, and should be removed from any production configuration.

Suggested Future Features
The following lists the features I hope to add to mod_geoip2, according to need, demand, inclination, and time:

Frequently Asked Questions

Question: What is the difference between mod_geoip2 and mod_geoip? Answer: The mod_geoip module uses the "legacy" GeoIP API from MaxMind, which was discontinued in early 2019. This mod_geoip2 module uses the newer MaxMindDB library from MaxMind.

Question: How I can whitelist specific clients from mod_geoip2's checking?
Answer: You should be able to easily do this using
classes and the mod_ifsession module. For example:

  <Class geoip-whitelist>
    From 1.2.3.4
  </Class>

  <IfModule mod_geoip2.c>
    # Add the normal mod_geoip2 directives here except GeoIPEngine
  </IfModule>

  <IfClass geoip-whitelist>
    # Disable mod_geoip2 for the whitelisted clients
    GeoIPEngine off
  </IfClass>

  <IfClass !geoip-whitelist>
    # Enable mod_geoip2 for all non-whitelisted clients
    GeoIPEngine on
  </IfClass>

Question: How I can require that a connection match multiple rules, e.g. both a RegionCode and a CountryCode?
Answer: In a given GeoIPAllowFilter or GeoIPDenyFilter, you can configure a list of filters/patterns. And all of these filters must be matched, in order for that GeoIPAllowFilter or GeoIPDenyFilter to be matched. Thus you can use:

  # Deny all connections, unless they are explicitly allowed
  GeoIPPolicy deny,allow

  # Allow only connections from TX, US
  GeoIPAllowFilter RegionCode TX CountryCode US

Question: Does mod_geoip2 support IPv6?
Answer: Yes.


© Copyright 2019 TJ Saunders
All Rights Reserved