Many sites running proftpd
have the need to limit/reject
connections from known bad addresses, or to accept connections only from
known good addresses. ProFTPD supports several different mechanisms for
implementing FTP connection ACLs.
However, there is one important thing to note: ProFTPD is not a firewall.
Never forget this. You cannot prevent TCP connections from ever
reaching proftpd
in the first place by using proftpd
itself. This means that for many sites with connection ACL needs, their
system's firewall capabilities may be a better mechanism for implementing ACLs.
<Limit LOGIN>
, and Whitelists versus Blacklists
The easiest way of accepting/rejecting connections is to use ProFTPD's
<Limit>
syntax, particularly
<Limit LOGIN>
.
For example, you can simply reject all connections to your proftpd
instance by using:
<Limit LOGIN> DenyAll </Limit>A more practical example would look like:
<Limit LOGIN> # These are trusted addresses Allow from 1.2.3.4 5.6.7.8 Allow from trusted-domain.com # Everyone else is denied DenyAll </Limit>
The above configuration demonstrates the concept of a whitelist: known trusted (i.e. "white") addresses are explicitly listed and allowed, and all others are denied. Conversely, you might use a blacklist, where known bad/malicious/untrusted (i.e. "black") addresses are explicitly listed and denied, and all others are allowed:
<Limit LOGIN> Order deny,allow # These are known bad addresses Deny from 1.2.3.4 5.6.7.8 Deny from evil-domain.com # Everyone else is allowed AllowAll </Limit>
It is useful to know about whitelists versus blacklists, as it can affect how large your ACLs become. Sites which run publicly available FTP servers but which need to weed out bad clients tend to use blacklists; over time, these blacklists can become quite large. Sites which know who will be using their FTP server and only want those people to be able to connect will use whitelists; these whitelists tend to remain fairly small/short.
Large Blacklists
Let's assume that you are running a public FTP server, and that you are using
a <Limit LOGIN>
section to make a blacklist. Your site
may even have some script which detects bad clients, and automatically adds
them to your blacklist, e.g.:
<Limit LOGIN>
Order deny,allow
# -- Add blacklisted addresses here --
Deny from ...
Deny from ...
# Many more Deny from
lines
# Allow everyone not explicitly blacklisted
AllowAll
</Limit>
Over time, your number of blacklisted IP addresses starts to become large
and unwieldy. You might have thousands of such addresses; you notice that
proftpd
starts acting strangely, and starts slowing down.
When this happens, you should start looking for ways to make your list shorter. If your list is comprised of entries for each individual IP address, you should think about using glob expressions and netmasks to reduce the number of entries. For example, rather than using something like this:
Deny from 1.2.3.4 Deny from 1.2.3.5 Deny from 1.2.3.6 Deny from 1.2.3.7 Deny from 1.2.3.8 Deny from 1.2.3.9you could (as of
proftpd-1.3.4rc1
and later) use a range:
Deny 1.2.3.[4-9]or even use a glob wildcard such as this, which makes for even fewer entries in your address lists:
Deny 1.2.3.*Or you could use netmasks such as:
Deny 1.2.3.0/8
Using Classes
Now let's assume that at this point you have used glob ranges and wildcards
and netmasks to make your ACL shorter, but it is still large, and
proftpd
is still slow. It is time for you to use ProFTPD's
connection classes.
To do this, you would rewrite your large <Limit LOGIN>
section to look something like this:
<Class blacklist>
# Put all of your blacklisted address/range lines here, as From
lines
From ...
From ...
From ...
</Class>
<Limit LOGIN>
Order deny,allow
# Rejected blacklisted clients
DenyClass blacklist
# Allow everyone else
AllowAll
</Limit>
Why does using classes like this make things faster? When using classes, the
label (i.e. the class name in the <Class>
section,
like "blacklist" in the above example) is determined when the client
first connects to proftpd
, before any comands are sent.
That is when all of the various netmasks and such are checked -- and
only at that time. After that, all of the configuration-based ACLs
are evaluated just using that label.
When you do not use classes, then proftpd scans each configuration, each netmask/address for each command. That's why things slow down so much.
Alternatives
There are a couple of other ways in which to implement connection ACLs; these
alternatives may be more efficient and/or better suited to your site's needs.
You can use a module like
mod_wrap2
, particular its
support for storing ACLs in SQL tables. SQL lookups can be very quick, and
can easily support large numbers of addresses efficiently.
And if you find yourself starting to block large blocks of addresses from
countries/regions, you should start thinking about connection ACLs in terms of
geolocation information. For this, the mod_geoip
module for ProFTPD is quite useful.