Go to file
john ff77f50dba Added fsckdns program 2019-12-02 10:19:22 -05:00
Jmakefile Added fsckdns program 2019-12-02 10:19:22 -05:00
LICENSE Initial commit 2019-11-22 22:38:11 -05:00
Makefile addresses reporting of log lines 2019-12-01 22:29:32 -05:00
README.md Change README to reflect current practice 2019-11-27 14:42:58 -05:00
TODO.txt make log file scan in natural order 2019-11-24 21:35:09 -05:00
addrRpt.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
addrRpt.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
ban2fail-cron.sh Improved iptables output parsing 2019-11-27 22:06:49 -05:00
ban2fail.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
ban2fail.cfg Added CIDR & ipv6 support 2019-11-23 21:22:37 -05:00
ban2fail.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
ban2fail.service Improvements to scripts, add cron script for report 2019-11-27 20:25:03 -05:00
ban2fail.sh Added fsckdns program 2019-12-02 10:19:22 -05:00
cfgmap.c Add files via upload 2019-11-22 22:40:23 -05:00
cfgmap.h Add files via upload 2019-11-22 22:40:23 -05:00
cntry.c Added CIDR & ipv6 support 2019-11-23 21:22:37 -05:00
cntry.h Add files via upload 2019-11-22 22:40:23 -05:00
es.c DNS working well now 2019-11-30 14:14:42 -05:00
es.h Added massively parallel reverse dns lookup 2019-11-30 00:10:25 -05:00
ez_es.c Added event server sources 2019-11-29 17:23:16 -05:00
ez_es.h Added event server sources 2019-11-29 17:23:16 -05:00
ez_libanl.c Added event server sources 2019-11-29 17:23:16 -05:00
ez_libanl.h Added event server sources 2019-11-29 17:23:16 -05:00
ez_libc.c Added fsckdns program 2019-12-02 10:19:22 -05:00
ez_libc.h Added fsckdns program 2019-12-02 10:19:22 -05:00
ez_libz.c Consolidate ez_* categories to library 2019-11-29 09:00:39 -05:00
ez_libz.h Consolidate ez_* categories to library 2019-11-29 09:00:39 -05:00
fsckdns.c Added fsckdns program 2019-12-02 10:19:22 -05:00
iptables.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
iptables.h Fixed bug not accounting for unjustly blocked addr 2019-11-26 06:42:23 -05:00
logFile.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
logFile.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
logType.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
logType.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
map.c Add files via upload 2019-11-22 22:40:23 -05:00
map.h Add files via upload 2019-11-22 22:40:23 -05:00
maxoff.c Added event server sources 2019-11-29 17:23:16 -05:00
maxoff.h Add files via upload 2019-11-22 22:40:23 -05:00
msgqueue.c DNS working well now 2019-11-30 14:14:42 -05:00
msgqueue.h DNS working well now 2019-11-30 14:14:42 -05:00
offEntry.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
offEntry.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
pdns.c addresses reporting of log lines 2019-12-01 22:29:32 -05:00
pdns.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
ptrvec.c Add files via upload 2019-11-22 22:40:23 -05:00
ptrvec.h addresses reporting of log lines 2019-12-01 22:29:32 -05:00
str.c Add files via upload 2019-11-22 22:40:23 -05:00
str.h Add files via upload 2019-11-22 22:40:23 -05:00
util.c Improved reporting features 2019-12-01 13:04:41 -05:00
util.h Improved reporting features 2019-12-01 13:04:41 -05:00

ban2fail

(C) 2019 John D. Robertson john@rrci.com

ban2fail is a simple and efficient tool to coordinate log file scanning and iptables filtering. As the name implies, ban2fail was inspired by the popular fail2ban project (http://fail2ban.org).

ban2fail started with a few hours of frenzied C hacking after my mail server was exploited to deliver spam for others who had cracked a user's SMTP send password. After inspecting the log files I realized that crackers are now using widely distributed attacks, and that I would need an extremely efficient tool that could run in a fraction of a second on my rather modest Linode virtual server to have a chance of stopping them. Here are the timing results for a typical scan on my wimpy server:

real    0m0.269s
user    0m0.108s
sys     0m0.134s

Currently I am running ban2fail from a systemd service file which triggers ban2fail whenever a watched log file is modified. This gives attackers at most a 0.4 second window to do their worst. I hope you find this code useful.

Configuration

ban2fail works from a configuration file found at "/etc/ban2fail/ban2fail.cfg". The overarching premise is that if any REGEX appearing in a LOGTYPE clause matches a line in an associated log file, then by default that IP will be blocked.

LOGTYPE auth {
   DIR= /var/log
   PREFIX= auth.log

# imapd[20193]= Login failed user=redacted auth=redacted@nowhere.com host=[186.179.170.12]
   REGEX= imapd.*Login failed.*\[([0-9.a-f:]+)\]$

# sshd[6165]= Failed password for invalid user user from 185.224.137.201 port 44865 ssh2
   REGEX= sshd.*Failed password.*from ([0-9.a-f:]+) port [0-9]+ ssh2$

# Unable to negotiate with 193.188.22.188 port ...
#   REGEX= Unable to negotiate with ([0-9.]+) port
   REGEX= Unable to negotiate with ([0-9.a-f:]+) port

}

Syntax in the config file is pretty much the same as the nftables syntax. All keywords must be in upper case. Any values in the key=value pairs have whitespace stripped from the beginning and end of the line. Since there is little escaping of characters going on, regular expressions are mostly WYSIWYG. If you have a hash symbol '#' in your pattern (which is the comment character for the config file parser), you will need to escape it like so:

# Nov 27 02:03:03 srv named[764]: client @0x7fe6a0053420 1.192.90.183#27388 (www.ipplus360.com): query (cache) 'www.ipplus360.com/A/IN' denied
   REGEX= named.*client.* ([0-9.a-f:]+)\#.*denied$

Finding typos and so forth in the config file is easy; use the -v command flag to print all unrecognized content (besides comments).

ban2fail -v

The only way to alter the default blocking behavior is with a MAX_OFFENSES clause. This clause allows you specify how many offenses are tolerated before an IP is blocked. Offenses will naturally disappear as old logfiles are deleted by logrotate.

# Take it easy on home boys
MAX_OFFENSES 5 {
   COUNTRY= US
}

# GeoIP doesn't know the location of every IP address
MAX_OFFENSES 3 {
   COUNTRY= unknown
}

# This is your whitelist: -1 means no limit.
MAX_OFFENSES -1 {

# me from home
   IP= 205.144.171.37/20

# Some user
   IP= 173.236.196.36
}

If you recieve a complaint about an address unjustly getting blocked, place it in one of the MAX_OFFENSES blocks, and the IP will be unblocked the next time ban2fail runs in production mode.

Working with ban2fail

There are two primary modes in which ban2fail is used:

  • Production mode, where iptables rules are modified.

  • Testing mode, where modifications to blocking rules are merely indicated.

Production

In production mode it is expected that ban2fail is running from a cron job, and no output is printed unless addresses are (un)blocked. It is also possible to generate a listing of addresses, offense counts, and status with the -a command flag. Likewise, a listing of countries and offense counts is available with the -c flag.

Testing

In test mode (-t flag) the presumption is that you are testing a modified configuration which is not yet in place, and that you don't want to disturb the production setup. This is how you might do that:

ban2fail -t myNew.cfg -a

No iptables rules will be modified. You will be shown in the listing which addresses would be (un)blocked if the contents of "myNew.cfg" was in place, and ban2fail was running in production mode.

When you are happy with the new configuration, copy it into place, and the the iptable rule changes will be realized the next time ban2fail runs in production mode.

Building the Project

I've tested ban2fail only on Debian Buster, but it should compile on just about any modern Linux distro. It uses the following libraries:

  • libcrypto from the libssl package, for md5 checksums

  • libgeoip to identify the country of origin for IP addresses

  • libz to read compressed log files

Build and install like so:

make release
sudo make install

The executable will be placed in "/usr/local/bin".