I just discovered DenyHosts, a cool little program that monitors your logs for signs of brute-force login attacks and helps prevent them. I had to fix a few different things to get it to detect all the different attacks that I experience. I like it a lot, though it makes me nervous. I travel a lot and I can see this accidentally blocking me out of my own server.
Install from ports
It’s easy to get on FreeBSD. Just portupgrade -N denyhosts.
There’s a lot to do to configure logging correctly. Out-of-the-box, FreeBSD logs all the authorisation failures to /var/log/auth.log. That makes it easy.
- Change syslogd to run with -c. That requires putting
syslogd_flags="-c" in /etc/rc.conf
Put a line in
/etc/newsyslog.confto rotate /
var/log/denyhostsand look at
/var/run/denyhosts.pidto find the process to signal.
/var/log/denyhosts 644 7 1024 * J /var/run/denyhosts.pid
I like to put a line in
syslog.confthat sends all the tcpwrappers output (service local7) to
I change the line in
/etc/hosts.allowso that it looks at
/etc/hosts.deniedsshand logs it to local7:
ALL : /etc/hosts.deniedssh : severity local7.notice : deny
The standard configuration from FreeBSD ports is good. It looks in the right place and it parses the logs fine. You can set most of the values to be whatever you want. I had a slight problem, though. I have two services that get hammered: sshd and ftpd. I want to block any hosts that does a brute force against either one of them. What I love about DenyHosts is the possibility that I can block access to all services (including mysql, ssh, ftp, imap, pop, etc) as soon as the attacking host is detected on any one service.
SSH login failures look like one thing:
Jul 9 22:28:04 www sshd: Failed password for root from 18.104.22.168 port 48308 ssh2
FTP login failures look like something else:
Jul 4 05:00:15 www ftpd: FTP LOGIN FAILED FROM 22.214.171.124, charles
By default, DenyHosts only understands how to parse ssh log messages. I wanted to let it understand the FTP ones, too. It’s interesting because FreeBSD’s FTP daemon puts the user name after the host, instead of before like in SSH. I didn’t figure it out myself. I took a look at this Japanese web page, without understanding a word of it. The 3 lines that the recommend look sensible.
The first seems to tell it “if you see either sshd or ftpd on the beginning of the line, parse it for login failures.” The next two help it recognize the format of FTP login failures.
SSHD_FORMAT_REGEX=.* (sshd.*:|\[sshd\]|ftpd.*:) (?P<message>.*) USERDEF_FAILED_ENTRY_REGEX=FTP LOGIN FAILED FROM (?P<host>.*), (?P<user>.*) FAILED_ENTRY_REGEX6=FTP LOGIN FAILED FROM (?P<host>.*), (?P<user>.*)
That’s working. It’s parsing both sshd and ftpd errors now. I like this solution a lot.