FreeBSD and DenyHosts to help against sshd brute force

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.

Configure Logging

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.

  1. Change syslogd to run with -c. That requires putting syslogd_flags="-c" in /etc/rc.conf
  2. Put a line in /etc/newsyslog.conf to rotate /var/log/denyhosts and look at /var/run/denyhosts.pid to find the process to signal.

    /var/log/denyhosts 644 7 1024 * J /var/run/denyhosts.pid

  3. I like to put a line in syslog.conf that sends all the tcpwrappers output (service local7) to /var/log/wrapper.log

    local7.info /var/log/wrapper.log

  4. I change the line in /etc/hosts.allow so that it looks at /etc/hosts.deniedssh and logs it to local7:

    ALL : /etc/hosts.deniedssh : severity local7.notice : deny

Customize DenyHosts

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[78490]: Failed password for root from 1.85.2.121 port 48308 ssh2

FTP login failures look like something else:

JulĀ  4 05:00:15 www ftpd[72158]: FTP LOGIN FAILED FROM 41.78.57.37, 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.