This post is a fairly comprehensive reference to Advanced Policy Firewall (apf-firewall
), a user-friendly interface of iptables
. We will also cover BFD (bfd
), a script that automates IP blocking using APF.
Technical Context: Ubuntu 14.04, APF v9.7, BFD v1.5-2
Installation
$ apt-get install apf-firewall
$ wget http://rfxnetworks.com/downloads/bfd-current.tar.gz
$ tar xfz bfd-current.tar.gz
$ cd bfd-1.5-2
$ ./install.sh
Basic Usage
apf -s - Start
apf -f - Stop
apf -r - Restart
apf -e - Refresh APF rules
apf -a <IP> - manually allow IP
apf -d <IP> - manually block IP
apf -u <IP> - manually unblock IP (works for BFD too)
What -a
actually does is add the IP entry to the allow_hosts.rules
file. -d
does the same thing for deny_hosts.rules
. -u
removes the IP entry from either allow_hosts.rules
or deny_hosts.rules
, if it exists. All three commands will call apf -e
as well.
APF supports CIDR notation for specifying rules for IP blocks, as well as fully qualified domain names (FQDR)1.
There are basically three ways to use APF:
- Restrict on a per-IP basis
- Restrict on a per-port basis
- Restrict on a IP-port combination basis
Restrict on a per-IP basis
The most straightforward to do this is, as mentioned earlier, by using -a
, -d
and -u
. Of course, you can edit allow_hosts.rules
or deny_hosts.rules
directly as well (specify each IP address on a new line).
Restrict on a per-port basis
By default, APF blocks a number of known malicious ports (see the main config file for an exhaustive list). To allow all incoming or outgoing connections on a per-port basis, we can edit the IG_TCP_CPORTS
or EG_TCP_CPORTS
setting respectively in APF’s main config file /etc/apf-firewall/conf.apf
:
# incoming connections
IG_TCP_CPORTS="22,80,443"
IG_UDP_CPORTS=""
# outgoing connections
EG_TCP_CPORTS="21,25,80,443,43"
EG_UDP_CPORTS="20,21,53"
Notably, these settings are overriden by rules in allow_hosts.rules
and deny_hosts.rules
.
Restrict on a IP-port combination basis
The allow_hosts.rules
and deny_hosts.rules
is very well commented regarding the syntax for specifying granular restrictions, so I’ll cover them only briefly here:
# Syntax:
# proto:flow:[s/d]=port:[s/d]=ip(/mask)
# s – source , d – destination , flow – packet flow in/out
For example:
tcp:in:d=22:s=192.168.2.1
in allow_hosts.rules
will allow incoming connections from 192.168.2.1
to port 22.
Multiple IPs to the same port need to be specified on separate lines:
tcp:in:d=22:s=192.168.2.1
tcp:in:d=22:s=192.168.31.4
...
APF Configuration
Some other noteworthy APF configuration settings in /etc/apf-firewall/conf.apf
that you should change:
Development Mode
DEVEL_MODE="1"
When set to "1"
, APF will deactivate itself after every 5 minutes. This prevents you from setting stupid rules and cutting yourself out from a remote machine.
Remember to set this to "0"
once APF is determined to be functioning as desired.
Monokernel
SET_MONOKERN="0"
It might be an issue in situations where iptables
is installed into the kernel rather than as a package. In those cases, you’ll see something like:
Unable to load iptables module (ip_tables), aborting.
or
$ apf -s
apf(17079): {glob} activating firewall
apf(17120): {glob} kernel version not equal to 2.4.x or 2.6.x, aborting.
Setting it to SET_MONOKERN="1"
will fix the problem.
Ban Duration
RAB_TIMER="300"
I recommend setting this a lot higher than the default of 300 seconds. 21600 (6 hours), maybe?
Reactive Address Blocking
RAB="0"
Set this to “1” to activate APF’s reactive address blocking.
Subscriptions
APF can subscribe to known lists of bad IP addresses. The below is an abridged portion of the config file that deals with this:
##
# [Remote Rule Imports]
##
# Project Honey Pot is the first and only distributed system for identifying
# spammers and the spambots they use to scrape addresses from your website.
# This aggregate list combines Harvesters, Spammers and SMTP Dictionary attacks
# from the PHP IP Data at: http://www.projecthoneypot.org/list_of_ips.php
DLIST_PHP="0"
DLIST_PHP_URL="rfxn.com/downloads/php_list"
DLIST_PHP_URL_PROT="http"
# The Spamhaus Don't Route Or Peer List (DROP) is an advisory "drop all
# traffic" list, consisting of stolen 'zombie' netblocks and netblocks
# controlled entirely by professional spammers. For more information please
# see http://www.spamhaus.org/drop/.
DLIST_SPAMHAUS="0"
DLIST_SPAMHAUS_URL="www.spamhaus.org/drop/drop.lasso"
DLIST_SPAMHAUS_URL_PROT="http"
# DShield collects data about malicious activity from across the Internet.
# This data is cataloged, summarized and can be used to discover trends in
# activity, confirm widespread attacks, or assist in preparing better firewall
# rules. This is a list of top networks that have exhibited suspicious activity.
DLIST_DSHIELD="0"
DLIST_DSHIELD_URL="feeds.dshield.org/top10-2.txt"
DLIST_DSHIELD_URL_PROT="http"
BFD Configuration
BFD barely has any configuration (which is A Good Thing™). The below is pretty much it:
$ vim /usr/local/bfd/conf.bfd
You can set the threshold for the number of attempts before an IP address is blocked:
TRIG="15"
The default number of 15 is quite generous - I’d lower it to at most 5 or 6.
BFD also has email alerts:
EMAIL_ALERTS="1"
EMAIL_ADDRESS="wow@example.com"
We can add whitelisted IP addresses in:
$ vim /usr/local/bfd/ignore.hosts
IP addresses whitelisted by BFD are still subjected to APF’s rules - they do not have any influence on each other.
Finally, and most importantly, BFD is started with:
$ bfs -s
which will also start a cron job2 that goes through your access log files every 3 minutes and tells APF to ban any IP addresses that goes beyond the specified threshold in TRIG
.
BFD Logs
BFD logs to /var/log/bfd_log
.