mod_ban
The mod_ban
module is designed to add dynamic "ban"
lists to proftpd
. A ban prevents the banned user, host, or
class from logging in to the server; it does not prevent the banned
user, host, or class from connecting to the server.
mod_ban
is not a firewall. The module also provides
automatic bans that are triggered based on configurable criteria.
This module is contained in the mod_ban.c
file for
ProFTPD 1.2.x/1.3.x, and is not compiled by default.
Installation instructions are discussed here.
Detailed documentation on mod_ban
usage can be found
here.
The most current version of mod_ban
is distributed with the
proftpd source.
Please contact TJ Saunders <tj at castaglia.org> with any questions, concerns, or suggestions regarding this module.
<VirtualHost>
, <Global>
The BanCache
directive configures a driver to use for
caching ban entries. Depending on the compile-time options, the following
drivers are supported:
<VirtualHost>
, <Global>
The BanCacheOptions
directive is used to configure various optional
caching behavior of mod_ban
. Note: all of the configured
BanCacheOptions
parameters must appear on the same line in
the configuration; only the first BanCacheOptions
directive that
appears in the configuration is used.
Example:
BanCacheOptions UseJSON
The currently implemented options are:
MatchServer
This option tells mod_ban
to ignore cached entries unless
they match the IP address/port of the server handling the FTP
session. There might be other servers adding their own entries to
a common cache, for example; it is for these situations that the
MatchServer
option should be used, to avoid false positives.
UseJSON
This option tells mod_ban
to store the ban rules in the
cache as JSON-formatted data. This makes it possible for other tools
to discover/display the cached ban rules.
Note that this option first appeared in
proftpd-1.3.6rc2
.
The BanControlsACLs
directive configures access lists of
users or groups who are allowed (or denied) the ability to
use the actions implemented by mod_ban
. The default
behavior is to deny everyone unless an ACL allowing access has been explicitly
configured.
If "allow" is used, then list, a comma-delimited list
of users or groups, can use the given actions; all
others are denied. If "deny" is used, then the list of
users or groups cannot use actions all others are
allowed. Multiple BanControlsACLs
directives may be used to
configure ACLs for different control actions, and for both users and groups.
The actions provided by mod_ban
are "ban"
and "permit".
Examples:
# Allow only user root to ban and permit users BanControlsACLs all allow user root
The BanEngine
directive enables or disables the banning of
sessions by mod_ban
. If it is set to off this module
does no banning. Use this directive to disable the module instead of
commenting out all mod_ban
directives.
<Global>
The BanLog
directive is used to specify a log file for
mod_ban
reporting and debugging. The path parameter
must be the full path to the file to use for logging. Note that this path must
not be to a world-writeable directory and, unless
AllowLogSymlinks
is explicitly set to on
(generally a bad idea), the path must not be a symbolic link.
If path is "none", no logging will be done at all.
<Global>
The BanMessage
directive configures a message that will be
sent to clients that have been banned. This message may contain the
following variables:
%a
: client IP address
%c
: client class (if none, will be empty)
%u
: USER name (if none, will be empty)
Example:
BanMessage "Host %a has been banned"
<Global>
The BanOnEvent
directive is used to configure a "rule"
that is triggered whenever the named event occurs. The currently
supported events are:
Directive | Class/Host/User Ban |
AnonRejectPasswords |
Host ban |
BadProtocol |
Host ban |
ClientConnectRate |
Host ban |
EmptyPassword |
Host ban |
MaxClientsPerClass |
Class ban |
MaxClientsPerHost |
Host ban |
MaxClientsPerUser |
User ban |
MaxCommandRate |
Host ban |
MaxConnectionsPerHost |
Host ban |
MaxHostsPerUser |
User ban |
MaxLoginAttempts |
Host ban |
MaxLoginAttemptsFromUser |
User@Host ban |
RootLogin |
Host ban |
TimeoutIdle |
Host ban |
TimeoutLogin |
Host ban |
TimeoutNoTransfer |
Host ban |
TLSHandshake |
Host ban |
UnhandledCommand |
Host ban |
An event is generated whenever one of these limits is reached by a client.
The freq parameter should be formatted as:
N/hh:mm:sswhere N is the number of occurrences, and
hh:mm:ss
specifies a number of hours, minutes, and seconds. This parameter says
that if N occurrences of event happen within the given
time interval, then a ban is automatically added. The IP address of
the connecting client is banned when the following event rules are
triggered: AnonRejectPasswords
, BadProtocol
,
MaxCommandRate
, MaxClientsPerHost
,
MaxConnectionsPerHost
, MaxLoginAttempts
,
TimeoutIdle
, TimeoutNoTransfer
, and
UnhandledCommand
. The class of the connected client, if any, is
banned when a rule for MaxClientsPerClass
is triggered. Rules for
MaxClientsPerUser
and MaxHostsPerUser
will cause
the connected username to be banned.
The duration should be formatted as:
hh:mm:ssand specifies the numbers of hours, minutes, and seconds that the automatic ban generated a
BanOnEvent
rule lasts. Unlike bans added via the
ban ftpdctl
control action, automatic bans do
not have infinite lifetimes.
An optional message, to be displayed to banned clients, can be configured.
If no such optional message is configured using the BanOnEvent
directive, then any BanMessage
message will be displayed.
For example:
# Configure a rule to automatically ban scripts looking for anonymous # servers to which they can upload BanOnEvent AnonRejectPasswords 1/01:00:00 99:99:99 # Ban clients which connect too frequently. This rule bans clients # which connect more than 5 times within one minute. Include a special # message just for them. BanOnEvent ClientConnectRate 5/00:01:00 04:00:00 "Stop connecting frequently"
See also: BanMessage
<VirtualHost>
, <Global>
The BanOptions
directive is used to configure various optional
behavior of mod_ban
.
Example:
BanOptions MatchAnyServer
The currently implemented options are:
MatchAnyServer
By default, any ban entries are valid only for the
<VirtualHost>
handling the banned clients. This is
intentional; the assumption is that there will be different clients,
different use cases for the different <VirtualHost>
sections.
However, some sites would like ban entries to be valid across
<VirtualHost>
, to match, or apply to
any server. Use this option to enable this behavior.
The BanTable
directive configures a path to a file
that mod_ban
uses for handling its ban data. The given
path must be an absolute path. Note: this directive is
required for mod_ban
to function. It is recommended
that this file not be on an NFS mounted partition.
Note that ban data is not kept across daemon stop/starts. That is,
once proftpd
is shutdown, all current ban data is lost.
ban
The ban
action is used to add bans to the mod_ban
lists. For example, to ban a user:
ftpdctl ban user daveThis will create a ban rule for user 'dave' for all virtual servers in your
proftpd.conf
. If you want to create such a ban rule, but
only for one specific <VirtualHost>
, use the -s
command-line option, e.g.:
ftpdctl ban user -s 1.2.3.4#21 daveThis example will create the user 'dave' ban rule for the
<VirtualHost>
handling IP address 1.2.3.4, port 21.
The -s
command-line option applies to host and
class bans as well.
To ban specific hosts, you can use either IP addresses or DNS names:
ftpdctl ban host 1.2.3.4 5.6.7.8 ftpdctl ban host gw.evil.comBanning a class works the same way:
ftpdctl ban class anonftp
The info parameter is used to view information on current bans. Example listing:
# ftpdctl ban info ftpdctl: Banned Hosts: ftpdctl: 127.0.0.1Or, if you wish to see more information, use the
-v
option:
# ftpdctl ban info -v ftpdctl: Banned Hosts: ftpdctl: 127.0.0.1 ftpdctl: Reason: MaxLoginAttempts autoban at Wed May 19 14:59:25 2004 ftpdctl: Expires: Wed May 19 14:59:55 2004 (in 24 seconds) ftpdctl: <VirtualHost> ServerName (1.2.3.4#21)It is also possible to see the state of ban event rules, using the
-e
option:
# ftpdctl ban info -e ftpdctl: No bans ftpdctl: ftpdctl: Ban Event Entries: ftpdctl: Event: MaxLoginAttempts ftpdctl: Source: 127.0.0.1 ftpdctl: Occurrences: 1/2 ftpdctl: Entry Expires: 589 secondsThis shows that no bans are currently in effect, and that a
BanOnEvent
has been configured for the
MaxLoginAttempts
event. That event has occurred once, and
will need to happen one more time within 589 seconds in order for an
automatic ban to be added.
See also: permit
permit
The permit
action is used to remove a ban for users, hosts,
and classes:
# ftpdctl permit user dave # ftpdctl permit user -s 1.2.3.4#21 dave # ftpdctl permit host 1.2.3.4 gw.evil.com # ftpdctl permit class anonftp
See also: ban
mod_ban
module is distributed with ProFTPD. Simply follow
the normal steps for using third-party modules in ProFTPD, making sure to
include the --enable-ctrls
configure option, which
mod_ban
requires:
$ ./configure --enable-ctrls --with-modules=mod_banTo build
mod_ban
as a DSO module:
$ ./configure --enable-ctrls --enable-dso --with-shared=mod_banThen follow the usual steps:
$ make $ make install
For those with an existing ProFTPD installation, you can use the
prxs
tool to add mod_ban
, as a DSO module, to
your existing server:
$ prxs -c -i -d mod_ban.c
mod_ban
module implements its bans by checking if a client
is banned, either by host or by class, when that client
connects to the server. Banned clients are immediately disconnected.
Banned users are checked after the client has sent the USER
and PASS
commands; if that user has been banned, the client is
immediately disconnected.
Here is an example mod_ban
configuration, demonstrating how
to configure an automatic ban for MaxLoginAttempts
:
MaxLoginAttempts 1 <IfModule mod_ban.c> BanEngine on BanLog /var/log/proftpd/ban.log BanTable /var/data/proftpd/ban.tab # If the same client reaches the MaxLoginAttempts limit 2 times # within 10 minutes, automatically add a ban for that client that # will expire after one hour. BanOnEvent MaxLoginAttempts 2/00:10:00 01:00:00 # Allow the FTP admin to manually add/remove bans BanControlsACLs all allow user ftpadm </IfModule>
By default, the mod_ban
module allocate size for 512 bans.
In practice, this has seemed to work well. However, if you need to allocate
space for more bans, you will need to recompile proftpd, and use the
CFLAGS
environment variable like so:
./configure CFLAGS="-DBAN_LIST_MAXSZ=1024" ...or whatever your necessary ban list size is.
Logging
The mod_ban
module supports trace logging, via the module-specific log channels:
proftpd.conf
:
TraceLog /path/to/ftpd/trace.log Trace ban:20This trace logging can generate large files; it is intended for debugging use only, and should be removed from any production configuration.
Frequently Asked Questions
Question: Why does mod_ban
not store ban
data across daemon stop/starts?
Answer: The mod_ban
module was not
designed to add yet another ACL mechanism to proftpd
. For
persistent access control, there is the <Limit LOGIN>
section, the mod_wrap
module, the /etc/ftpusers
file, and various other mechanisms. The purpose of mod_ban
is to provide dynamic, short-lived bans.
Question: What about having proftpd
delay
sending responses to clients, say by 30 seconds or so?
Answer: This is a bad idea. It would allow
malicious clients, who knew they were banned, to tie up your
proftpd
processes, since those processes would be taking up
space, waiting before sending responses back to the client. This makes it
possible for those clients to use the delaying as a Denial of Service attack,
eventually tying up your available system resources with waiting
proftpd
processes.
Question: I have the following, taken from
the example config above, configured for
The above
The default
Question: It looks like the
Answer: A
Question: How can I configure a whitelist of IP
addresses, to be excluded from the effects of
It is also important that for the above to work, when using shared/DSO
modules, that
Question: I would like to ban clients which try to
login as root. How would I do this?mod_ban
, but it does not
appear to be working. Why not?
# If the same client reaches the MaxLoginAttempts limit 2 times
# within 10 minutes, automatically add a ban for that client that
# will expire after one hour.
BanOnEvent MaxLoginAttempts 2/00:10:00 01:00:00
Answer: The most common reason is that the
MaxLoginAttempts
directive does not function the way that many
assume it does.
BanOnEvent
rule says that the same client (i.e.
source IP address) which reaches the MaxLoginAttempts
limit
2 times within 10 minutes will be banned. If you test by connecting to
proftpd
, trying a bad password once, disconnecting, then
connecting again and trying the same bad password again, you will not
be hitting the MaxLoginAttempts
limit. Remember that the
MaxLoginAttempts
directive configures a limit to the number
of bad login attempts for the same connection; it does not
configure limit on the number of bad login attempts across multiple
connections.
MaxLoginAttempts
value for proftpd
is 3. Which means that simply connecting, trying a bad login attempt once,
then disconnecting, will not trigger the MaxLoginAttempts
limit.
This is why the example configuration given above explicitly configures
the MaxLoginAttempts
limit to be lower:
MaxLoginAttempts 1
in order to make mod_ban
behave the way that most administrators
assume it will. If you have not explicitly configured
MaxLoginAttempts
lower, then this is probably why your
BanOnEvent
rule is not taking effect as you expect.
BanTable
file
I configured is untouched:
-rw-r--r-- 1 ftp ftp 0 2007-01-13 23:18 ban.table
Does this mean that something is wrong, or that mod_ban
is not
using that file?
BanTable
file is needed,
just not in an obvious way. The mod_ban
module stores its ban
information in a SysV shared memory segment. The configured
BanTable
file is used a) to generate a unique name/ID for
the shared memory segment to use (and to see if a segment for that name/ID
already exists), and b) for locking, as when multiple sessions are
trying to update the shared memory segment at the same time. But
mod_ban
does not write any data into that file itself, and hence
the last-modified-time of the file, and the file size, does not change much.
mod_ban
?
Answer: This can be done using a combination of
Classes and the mod_ifsession
module. For example:
<Class whitelist>
From ...
</Class>
<IfClass whitelist>
# Turn the mod_ban module off for whitelisted clients
BanEngine off
</IfClass>
<IfClass !whitelist>
# Make sure the mod_ban module is on for clients that are not whitelisted
BanEngine on
</IfClass>
Note that it is important to have both
<IfClass>
sections in your configuration.
mod_ban
be loaded in your configuration
before mod_ifsession
:
LoadModule mod_ban.c
...
LoadModule mod_ifsession.c
Otherwise, when parsing the configuration, mod_ban
might not
set all of the proper internal state for implementing the whitelists.
Answer: You would use the
BanOnEvent
directive, with an
event name of "mod_auth.root-login", thus:
# Ban clients which try to login as root. This bans clients which
# try root logins twice within 10 minutes, banning them for 6 hours.
BanOnEvent mod_auth.root-login 2/00:10:00 06:00:00
© Copyright 2004-2022 TJ Saunders
All Rights Reserved