Or: Monitoring a MySQL log table with Fail2ban
Cacti logs failed login attempts to a MySQL table, which Fail2ban can't read. By using MySQL's CSV storage engine we can write login attempts to an additional table, which on-disk format is ASCII or UTF-8, and thus readable by Fail2ban.
Note: This includes at least a trigger and and an optional scheduled event inside the database. I consider this "dirty", especially within a replication scenario.
$ mysql cacti
mysql> CREATE TABLE fail2ban (
-> `time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
-> ip varchar(40) NOT NULL DEFAULT '',
-> username varchar(50) NOT NULL DEFAULT '')
-> ENGINE=CSV;
mysql> delimiter |
mysql> CREATE DEFINER=cacti@localhost TRIGGER failed_logins
-> AFTER INSERT ON user_log FOR EACH ROW
-> BEGIN
-> IF NOT NEW.result = 1
-> THEN INSERT INTO fail2ban SET time=NEW.time, ip=NEW.ip, username=NEW.username;
-> END IF;
-> END; |
mysql> SET GLOBAL event_scheduler = 1 |
mysql> CREATE DEFINER=cacti@localhost EVENT delete_old_logs
-> ON SCHEDULE EVERY 1 hour COMMENT 'wipe old failed login attempts'
-> DO DELETE FROM fail2ban WHERE time <= subtime(now(), '01:00:00') |
mysql> quit|
Do not forget to set event_scheduler = 1 in your MySQL server's my.cnf.[Definition] failregex = ","<HOST>"," ignoreregex =Save it to a file called filter.d/cacti.local within your Fail2ban configuration directory, e.g. /etc/fail2ban, or /usr/local/etc/fail2ban on FreeBSD.
[cacti-ipfw]
enabled = yes
filter = cacti
action = bsd-ipfw
sendmail-whois-lines[name=cacti, logpath=/data/mysql/cacti/fail2ban.CSV]
logpath = /data/mysql/cacti/fail2ban.CSV
# fail2ban-client add cacti-ipfw # fail2ban-client start cacti-ipfw