I used to get tons of invalid login attempts to my hosted server. A single IP address would repeatedly connect and try hundreds of account names, filling up my logs with junk. A few people I know use sshit to automatically firewall addresses that have too many unsuccessful connections. However, I tried to set up sshit and its weird dependencies on Perl IPC stuff didn't work so well for me. (Multithreaded perl is evil.)
So I took the concept of sshit and rewrote it as a little Python script that does everything I need it to do in 41 lines of code (sshit is 354). It connects to the syslog mechanism through /etc/syslog.conf:
auth.info;authpriv.info |exec /usr/local/sbin/fwssh.py
The script just reads log entries from stdin as they happen, and looks for invalid login attempts, calling ipfw to firewall connections for a while if somebody's being annoying. Here's what it looks like in practice:
Mar 20 07:46:58 occam sshd[38074]: Invalid user test from 219.239.98.111 Mar 20 07:47:00 occam sshd[38076]: Invalid user guest from 219.239.98.111 Mar 20 07:47:03 occam sshd[38078]: Invalid user admin from 219.239.98.111 Mar 20 07:47:03 occam root: 29000 deny ip from 219.239.98.111 to any Mar 20 08:02:03 occam root: 29000 24 1852 deny ip from 219.239.98.111 to any Mar 20 16:10:21 occam sshd[48070]: Invalid user guest from 201.234.223.65 Mar 20 16:10:31 occam sshd[48076]: Invalid user adm from 201.234.223.65 Mar 20 16:10:34 occam sshd[48078]: Invalid user lp from 201.234.223.65 Mar 20 16:10:34 occam root: 29000 deny ip from 201.234.223.65 to any Mar 20 16:25:34 occam root: 29000 25 1924 deny ip from 201.234.223.65 to any Mar 20 17:42:10 occam sshd[49525]: Invalid user a from 68.191.193.82 Mar 20 17:42:14 occam sshd[49527]: Invalid user b from 68.191.193.82 Mar 20 17:42:20 occam sshd[49529]: Invalid user c from 68.191.193.82 Mar 20 17:42:20 occam root: 29000 deny ip from 68.191.193.82 to any Mar 20 17:57:20 occam root: 29000 9 532 deny ip from 68.191.193.82 to any
Notice how the third invalid login attempt triggers the deny rule, then 15 minutes later the output of ipfw show for that rule shows how many packets and bytes were blocked. The rule is deleted after that 15 minutes.
If you'd like the source, you can grab it here.
CPU states: 62.0% user, 24.4% nice, 13.2% system, 0.4% interrupt, 0.0% idle
Mem: 131M Active, 203M Inact, 105M Wired, 16M Cache, 60M Buf, 35M Free
Swap: 1024M Total, 872K Used, 1023M Free
PID USERNAME THR PRI NICE SIZE RES STATE TIME WCPU COMMAND
91680 root 1 132 0 4252K 3124K RUN 9:35 72.36% python
587 dnetc 1 134 20 1100K 684K RUN 354.9H 23.05% dnetc
tail -f /var/log/auth.log | python fwssh.py
2007-03-21T08:44:19Z