FreeBSD SSH port security 1

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


If you setup a FreeBSD host with BSD-Jails for JonDonym Mixes, there will only be very few ports open. There is no SSH port open on the mix jail systems as you do not need SSH within the mix jails (you access the mix jails from the host system). So, the only open ports of the mix jails will be the mix ports (plus Squid/Dante port in case of an exit (premium) mix).

The only open port on your host system will be the SSH port (port 22) as you need an SSH server there to access and administer the host as well as (from the host) the mix jails. If you followed the earlier BSD HowTo you already protected the host systems SSH port via TCP wrapper (by entries in the /etc/hosts.allow file). However, improvements are possible to protect your host system's SSH port. This is, what this additional HowTo is about: Securing your host's SSH server.

Before we begin, just check your host's open ports. To test open ports from outside, use the nmap port scanner (use nmap only to test your own hosts!):

  1. nmap <fqdn of your host>

nmap will run a minute or so and then lists your host's open ports. There should be only port 22 open.

To test your host from inside, use sockstat: SSH into your host. Then enter

# sockstat -4

sockstat will list your open ports as well then. Again, only port 22 should get named as open.

We're going to use the PF packet filter (originally developed by the OpenBSD folks but available too on FreeBSD systems) and the fail2ban python script to form additional protection for the SSH port. Both programs, PF and fail2ban, will collaborate to collect a common list of banned IP addresses. Both programs, PF and fail2ban, will watch out for „bad“ IP addresses trying to SSH into your host and decide (grounded on certain rules) whether or not to ban them. Fail2ban scans the auth.log logfile for this. PF works as a closed system (but does something similar with slightly different rules).

You'll be able to configure how long a certain banned IP will stay banned. You'll be able to delete a certain IP from the ban list. You'll also be able to add IPs by hand to the ban list. And you will be able to use various additional configuration options which might fit your needs.

And of course you always will have the option to enhance the whole setup to protect additional services/ports beyond SSH. This setup is suitable for many different computer setups (even desktops).

Documentation recommended

For FreeBSD in general please see the earlier HowTo documentation chapters. There are many links available for general FreeBSD information.

For the PF packet filter there are a bunch of webpages on OpenBSD's website. Visit to learn more on PF.

FreeBSD has a mailing list dedicated to PF as well. You may subscribe at and then post to

Please note the FreeBSD remarks on this list: „Discussion concerning the packet filter (pf) firewall system in terms of FreeBSD. Technical discussion and user questions are both welcome. This list is also a place to discuss the ALTQ QoS framework.“

There's also a text book dedicated to PF: „The book of PF“, by Peter N.M. Hansteen.

For fail2ban there's a wiki website available from the author of fail2ban, Cyril Jaquier, at and additionally you will find a lot of further HowTos there and on other websites.

Why we need TWO tools in combination

You might ask yourself why we need two tools to protect your SSH server – PF plus fail2ban. Here's the explanation:

The PF ruleset you will have in use reacts on any brute force like contact to the SSH server, no matter whether or not any usernames/passwords are given. The PF ruleset is perfect to block any IP address, flooding the SSH server in a brute force typical high speed way as it is common with, say, dictionary attacks. Again, the PF ruleset does NOT check whether or not a correct username/password was given. It simply reacts on – in simple words - the speed of sent login trials.

Beyond this, PF in general also blocks any contact to your SSH server whose IP address does not belong to a configured list of allowed IP addresses or IP subnets. The latter is an advanced version of the TCP wrapper blocking used in the basic FreeBSD host setup configuration.

Fail2ban works differently from PF, of course. Fail2ban is a python script scanning logfiles for login failure messages via regular expressions. If it finds login failure messages, it begins to count the failures of each IP found there. As soon as a configurable limit of failures was reached, it acts. Fail2ban's actions are configurable, too. You may use any shell command as it's action. In this HowTo we will configure fail2ban to add such an IP to PF's table of banned IPs.

Fail2ban proved as very helpful but nonetheless it's slow due to it's design as a logfile scanner script. There might be brute force attacks sending dozens or even hundreds of login trials before fail2ban realizes that it's limit of maximum trials (say a limit of three or five) was reached. In this case, the brute force attack gets caught by the PF ruleset due to the attack's speed.

Fail2ban additionally can catch slower login trials which (due to it's slow speed) do not get caught by the PF ruleset. That's why we use two tools in combination. As both, PF and fail2ban, do collaborate but work independently from each other, chances are pretty good that one of them will catch an attacker's IP very quickly.

Personal tools