Date: 2007-03-21 19:38:00
three strikes and you're out

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.

[info]hoyhoy
2007-03-21T08:44:19Z
I gave-up the good fight and set PasswordAuthentication no in sshd_config about three months ago.
[info]ghewgill
2007-03-21T19:13:52Z
I often seem to need to be able to log in without having my SSH private key handy. Disabling password authentication is certainly another good approach to this problem though.
[info]cowbert
2007-03-21T14:21:08Z
Wouldn't deleting rule 29000 delete all rules with that number? So if one IP was blackholed in 29000 and you shitlist another IP before the 15 minutes are up, once you unblock the first IP wouldn't you have unblocked the second IP...?
[info]ghewgill
2007-03-21T18:56:47Z
Yes, that's true. That's why my script allocates a new rule number for each simultaneously blocked connection, so they can be individually deleted.
[info]cowbert
2007-03-21T21:06:36Z
oh cool.
[info]ivo : neat!
2007-03-21T14:28:29Z
You should package it and have dbaker make it into a port.
[info]decibel45 : Re: neat!
2007-03-21T15:50:04Z
+1
[info]decibel45 : Re: neat!
2007-03-21T15:50:26Z
Of course, you could always do the packaging (or me, for that matter).
[info]ivo
2007-03-21T21:52:42Z
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



It sure is quite busy...
[info]ghewgill
2007-03-21T22:04:37Z
That doesn't seem right. For debugging, I just did this sort of thing:

tail -f /var/log/auth.log | python fwssh.py

I'm curious why it might be spinning up like that on your machine.
(anonymous) : Change ports
2007-03-29T20:43:30Z
From my sshd_config:

#Port 22
Port 23

It's enough to confuse your average script kiddie, and it's not like there's anything else you're going to run on port 23.


-Nerf
Greg Hewgill <greg@hewgill.com>