FreeBSD SSH port security 3

From JonDonym Wiki
Jump to: navigation, search

JonDos GmbH thanks for the right to publish the following article. We made some changes in it but the original text was provided by

navigation: Main Page | FreeBSD and Jails


Setting up fail2ban

Fail2ban can be installed from the ports collection. Enter:

cd /usr/ports/security/py-fail2ban
make install

At the time of this writing, the fail2ban version in the ports collection was 0.8.4 and during installation it relies on python 2.5.

However, with some older versions of fail2ban there's a bug occurring when python 2.6 gets used (as python 2.5 and python 2.6 are not compatible). Therefore, try to use python 2.5 to avoid any issues. But usually, python 2.5 will get built anyway by building fail2ban (managed by the dependency mechanism of the ports collection).

After installation through „make install“, the fail2ban server once needs to get started with


Then, stop the server again by

/usr/local/etc/rc.d/d/fail2ban stop

(from now on, the program can be controlled by /usr/local/etc/rc.d/fail2ban start | stop | restart)

Fail2bans configuration files reside in /usr/local/etc/fail2ban and its subdirectories. We need to edit and adapt some of them now.

First edit the main configuration file.

vi /usr/local/etc/fail2ban/fail2ban.conf

Make sure, the following four lines are included (and nothing else):

loglevel 	= 3
logtarget 	= /var/log/fail2ban.log
socket 		= /var/run/fail2ban/fail2ban.sock

Save and exit.

Then, edit the „jail“ file (please do not get confused with this naming and the BSD jails, both are completely different things).

vi /usr/local/etc/fail2ban/jail.conf

Make sure the following lines are included (and nothing else):

backend 	= auto
# bantime of -1 means forever, otherwise insert a time period in seconds
bantime	= -1
# time span for which to increment the counter for login failures, 604800 seconds equals 1 week
findtime	= 604800
maxretry	= 5
# replace by the email address to which you'd like to get notes
destemail	= <youremail@yourdomain.tld>
# replace by your own IP addresses you do not want fail2ban to apply to, CIDR format possible too
ignoreip	= <Another IP> <Yet another IP>
logtargets	= /var/log/fail2ban.log
# this „fail2ban-jail“ is switched on and it combines the filter.d/sshd.conf with action.d/pf.conf
enabled	= true
filter		= sshd
action		= pf
logpath	= /var/log/auth.log
maxretry	= 5
# this „fail2ban-jail“ is switched on and it combines the filter.d/sshd-ddos.conf with action.d/pf.conf
enabled	= true
filter		= sshd-ddos
action		= pf
logpath	= /var/log/auth.log
maxretry	= 3

Ensure again nothing else is in the file (or comment out the other lines). Then save and exit.

Next, create a new file in the action.d subdirectory:

vi /usr/local/etc/fail2ban/action.d/pf.conf

Make sure the following lines get inserted there:

actionstart	= 
actionstop	=
actioncheck	=
actionban	= pfctl -t fail2ban -T add <ip>
actionunban	= pfctl -t fail2ban -T delete `pfctl -t fail2ban -T show 2>/dev/null | grep <ip>`
port		= ssh
localhost	= 

Please make sure you got the right „ticks“ for the actionunban line!

Save and exit. Surely you did recognize both of the pfctl commands as we had something similar in the chapter about PF.

You may now start fail2ban again:

/usr/local/etc/rc.d/fail2ban start

Watch the fail2ban logfile to check for any issues occurring via:

tail -f /var/log/fail2ban.log

Last work: We now also want fail2ban to automatically start up at boot time.

vi /etc/rc.conf

Add the following line there:


Done. The combined setup of PF and fail2ban is up and working. It will get automatically started and go ahead working at boot time.

Hints for production usage


Please do in no case forget to comment the line in /etc/crontab which we earlier used to regularly switch off PF!

vi /etc/crontab

Search for the entry disabling PF every five minutes and insert a comment sign (#) in the first column. Do NOT comment the other line (writing the table content to disk every minute). Save the /etc/crontab file again and exit the editor.

On the lifetime of IP entries in the table of banned IP addresses:

The setup described above bans IP addresses „forever“. There is no mechanism included to release banned IP addresses from the ban table. But as the host we are talking about is a host dedicated to run mixes we almost certainly do not need to take care for dynamic IP addresses. That way, banning IP addresses forever is no problem.

System maintenance

The FreeBSD „periodic“ mechanism will send you Emails about the systems health in defined intervals. Some sort of information on PF will be enclosed by default when PF is working.

Additionally, you can watch the growing collection of banned IPs from the fail2ban table by a cronjob driven shell script regularly counting the number of lines in the /etc/pf.table.fail2ban file (which equals the number of banned IP entries).

Example shell script

pfstat=$(pfctl -s info 2>/dev/null | grep „Status:“ | awk '{ print $2 „ „ $3 „ „ $4 „ „ $5 „ „ $6 }'  )
echo „Packet Filter: $pfstat“
bannedIPs=$(cat /etc/pf.table.fail2ban | wc -l | awk '{ print $1 }' )
echo „banned IP entries: $bannedIPs“

Save this script in a directory included in $PATH for root and make it executable.

chmod 700 filename
chown root:wheel filename

Then add a line to /etc/crontab:

0	8	*	*	*	root	/path/scriptname

From then on, you will each day at 8 a.m. get a status Email about PF looking similar to this:

Packet Filter: Enabled for 17 days 05:57:03
Banned IP entries: 326

Enhanced configuration for protecting services run within jails additionally

As fail2ban runs on the host system and as such it can „reach“ also logfiles from within Jails you easily could enhance fail2ban's configuration to also scan further logfiles residing in the filesystem of Jails. That does not make sense as long as you have only Mixes running in your Jails but there might be additional Jails with other services running. This way you can use the whole setup very easily to also protect services running in Jails. The fail2ban wiki and the default configuration files contain a list of adaptions for various well known server daemons. You also could build your own fail2ban scanner if you are familiar with Regex.

Using blacklists of earlier banned IP addresses from other sources

In case you have lists of earlier banned IPs from other sources you easily could start the /etc/pf.table.failban file with filling those IPs in the /etc/pf.table.failban file. To do so, first prepare your list – it is needed in the form with one IP per line and no content else. Please take care for identical charsets when preparing the file.

Then stop PF

pfctl -d

Concatenate, sort and merge both lists:

cat /etc/pf.table.fail2ban /path/oldfile | sort | uniq > /etc/pf.table.fail2ban

Then re-enable PF

pfctl -e

Merging ban lists from various hosts

In case you run various hosts, each protected by the setup described above, you also could merge all the different /etc/pf.table.fail2ban files from all hosts into one file and then redistribute the resulting file back to all hosts.

Use the command line to get the merged file:

cat file1 file2 | sort | uniq  > mergefile

To collect the files from all hosts automatically, merge them and redistribute them again you, of course, will need some sort of certificate based SSH or VPN authentication.

Geolocalization of banned IP addresses

Finally, you could geolocalize the list of IP addresses by a script using any GeoIP service. But this is more for entertainment. It depends on /dev/random which bunch of script kiddies at a given time gets your hosts IP in their hands. Serious attackers anyway will spoof or hide their own IP address the one or other way.

Attacks for which this setup is sufficent

The setup in this HowTo is a solid measure against the vast majority of attacks against hosts. You can easily protect your machine against those attacks. However, in case you expect serious and heavy attacks by experienced blackhats focused on your host, FreeBSD offers a wide range of additional security measures strictly recommended then.

Personal tools