Re: RFC: Fam/Python based script for bruteforce blocking
On 2009-12-19 (Sat) at 03:38:26 -0900, Mel Flynn wrote: Well, my first problem with it is obviously that I now need python, where I don't want python. In fact, my firewalls/gateways only have /bin/sh and /bin/csh as scripting languages. It's one reason I switched from custom sysutils/grok rules to using security/sshguard - it got me rid of perl. That makes sense -- I'm using it on a general purpose server as opposed to a dedicated firewall box. Secondly, you have matching rules coded in the script. If there would be one reason to prefer this script over sshguard, it would be that I can add attack patterns more easily, in config file with a syntax that's not too obscure. Interesting thought, I will definitely make the matching rules configurable and potentially make possible to monitor multiple logfiles for attack patterns (potentially configurable per-logfile). Last but not least, you assume that once an IP is at fault, I want that IP blocked permanently. In practice you end up with an extremely large table that might eventually be too big for a default PF table and recurring scans from the same IP are not that common (you see the IP in a 12-24 hour window, then not again). You've misread the script. IPs are expired after a configurable number of seconds. Hope this helps. Thanks kindly for the feedback! --Brandon ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org
Re: RFC: Fam/Python based script for bruteforce blocking
On Thursday 17 December 2009 16:34:22 Brandon Low wrote: I'd love to hear other people's feedback on this approach of using FAM + auth.log to implement this and/or to hear of other superior approaches to achieving this result. Well, my first problem with it is obviously that I now need python, where I don't want python. In fact, my firewalls/gateways only have /bin/sh and /bin/csh as scripting languages. It's one reason I switched from custom sysutils/grok rules to using security/sshguard - it got me rid of perl. Secondly, you have matching rules coded in the script. If there would be one reason to prefer this script over sshguard, it would be that I can add attack patterns more easily, in config file with a syntax that's not too obscure. Last but not least, you assume that once an IP is at fault, I want that IP blocked permanently. In practice you end up with an extremely large table that might eventually be too big for a default PF table and recurring scans from the same IP are not that common (you see the IP in a 12-24 hour window, then not again). Hope this helps. -- Mel ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org
Re: RFC: Fam/Python based script for bruteforce blocking
Robert Huff wrote: Brandon Low writes: Not sure why this didn't attach the first time. The FreeBSD mailing list software is set to scrub all attachments as a security measure. To makew material available, post it in-line, or post a URL. The attachment eater doesn't actually eat *all* attachments. Just the ones with MIME types it thinks are tasty. You can generally get stuff through if it's marked as something innocuous like text/plain Cheers, Matthew -- Dr Matthew J Seaman MA, D.Phil. 7 Priory Courtyard Flat 3 PGP: http://www.infracaninophile.co.uk/pgpkey Ramsgate Kent, CT11 9PW signature.asc Description: OpenPGP digital signature
Re: RFC: Fam/Python based script for bruteforce blocking
Matthew Seaman writes: The FreeBSD mailing list software is set to scrub all attachments as a security measure. To makew material available, post it in-line, or post a URL. The attachment eater doesn't actually eat *all* attachments. Just the ones with MIME types it thinks are tasty. You can generally get stuff through if it's marked as something innocuous like text/plain Point taken. Robert Huff ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org
RFC: Fam/Python based script for bruteforce blocking
Hi, I'm pretty new to FreeBSD, but when I saw how neatly it supported file-backed tables for IP blocking I knew I'd finally want to build a bruteforce blocking script that I'd long wanted to create on Linux. This script is loosely based on the perl script for the same purpose from http://home.earthlink.net/~valiantsoul/pf.html . My script, in contrast to the above, runs as a daemon and is completely self contained other than the blacklist file. Of course it's up to the user to create the bruteforce table in pf and to do something useful with it, but once that's done just running the bruteforce.py daemon will take care of the rest. I've attached the script and my pf.conf. The only other requirements other than python are py-fam and (of course) a configured fam. I'd love to hear other people's feedback on this approach of using FAM + auth.log to implement this and/or to hear of other superior approaches to achieving this result. Thanks for reading, --Brandon table bruteforce persist file /var/db/blacklist table safe persist file /var/db/friendlist block in all pass in on nfe0 proto tcp from any to any port 22 keep state pass in on nfe0 proto tcp from any to any port 80 keep state pass in on nfe0 proto tcp from any to any port 443 keep state pass in on nfe0 proto tcp from any to any port 25 keep state pass in on nfe0 proto tcp from any to any port 465 keep state pass in on nfe0 proto tcp from any to any port 993 keep state pass in on nfe0 proto udp from any to any port 53 pass in on nfe0 proto tcp from any to any port 53 keep state pass in on nfe0 proto udp from any to any port 123 pass in on nfe0 proto icmp block from bruteforce pass from safe pass on lo0 pass out all keep state ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org
Re: RFC: Fam/Python based script for bruteforce blocking
Not sure why this didn't attach the first time. #!/usr/bin/env python import errno import logging import optparse import os import re import select import signal import subprocess import sys import time import datetime import _fam def getUpdateBlocks(pfctl, expire_seconds, blacklist_filename, table, limit_n): expire=str(expire_seconds) blacklist=blacklist_filename limit=limit_n baseArgs=(pfctl, '-t', table, '-T') def callAndLog(*args, **kwargs): c=subprocess.Popen(baseArgs + args, stderr=subprocess.PIPE, stdout=kwargs.get('stdout',subprocess.PIPE)) stdout,stderr=c.communicate() if stdout: logging.info(stdout) for line in (stderr if stderr else '').split('\n'): if not line: continue getattr(logging,'info' if line.find('ALTQ') 0 else 'debug')(line) reParts=('(.*) erudite sshd\[[0-9]+\]: ', '(?:', '|'.join(('Invalid user .* from', 'Did not receive identification string from', 'error: PAM: authentication error for root from')), ') ', '(', '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}', '(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', ')\n?') r=re.compile(''.join(reParts)) df='%b %d %H:%M:%S' oneDay=datetime.timedelta(days=1) def processFile(now, ips, filename): with open(filename, 'r') as f: for line in f: m=r.match(line) if not m: continue d=datetime.datetime.strptime(m.group(1),df).replace(now.year) if d now: d=d.replace(now.year-1) if now-d oneDay: ips[m.group(2)]=ips.get(m.group(2),0) + 1 def updateBlocks(filename): logging.info(Updating blacklist...) ips={} now=datetime.datetime.now() processFile(now, ips, filename) logging.debug(Found %s IPs, len(ips)) logging.debug(Adding ips to pf table) callAndLog('add', *tuple(k for k,v in ips.iteritems() if v = limit)) logging.debug(Expiring ips from pf table) callAndLog('expire', expire) logging.debug(Saving table state to file) with open(blacklist,'w') as blacklistFile: callAndLog('show', stdout=blacklistFile) logging.debug(Done) return updateBlocks def main(): parser=optparse.OptionParser() parser.add_option(-d, --debug, action=store_true, help=Enable debug logging) parser.add_option(-a, --auth_log, default=/var/log/auth.log, help=Authentication log filename) parser.add_option(-b, --blacklist, default=/var/db/blacklist, help=Blacklist filename) parser.add_option(-l, --log_file, default=/var/log/bruteforce.log, help=Log filename) parser.add_option(-p, --pfctl, default=/sbin/pfctl, help=pfctl binary) parser.add_option(-e, --expire, type=int, default=604800, help=Seconds to hold a grudge) parser.add_option(-t, --table, default=bruteforce, help=Name of pf table to work on) parser.add_option(-i, --limit, type=int, default=2, help=Number of invalid logins to get blacklisted) (opts, args)=parser.parse_args() if args: optparse.error(No non-option arguments expected) logging.basicConfig(filename=opts.log_file, level=logging.DEBUG if opts.debug else logging.INFO) fc=_fam.open() p=select.poll() p.register(fc, select.POLLIN|select.POLLPRI) fr=fc.monitorFile(opts.auth_log, None) updateBlocks=getUpdateBlocks( opts.pfctl, opts.expire, opts.blacklist, opts.table, opts.limit) while True: p.poll(60) update=False while fc.pending(): fe=fc.nextEvent() if fe.code in (_fam.Exists,_fam.Changed,_fam.Created): update=True if not fe.filename==opts.auth_log: raise FAM event: wrong file if update: updateBlocks(fe.filename) if __name__ == __main__: main() ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org
Re: RFC: Fam/Python based script for bruteforce blocking
Brandon Low writes: Not sure why this didn't attach the first time. The FreeBSD mailing list software is set to scrub all attachments as a security measure. To makew material available, post it in-line, or post a URL. Robert Huff ___ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org