Not long ago I’ve talked about two ways of making a good IP filter with pf. The first methods involved a pf table created after failed ssh attempts, but the table was not persistent after reboot, and the second method had a static text file from where pf could load unwanted IP for filtering. Let’s merge the two methods.
Let’s say that we already have a text file, manually created, with a selection of unwanted IPs, called /etc/pf.blocked.ip.conf and you also want to filter the ones that keep knowcking on your ssh door. You’ll have to have this in your /etc/pf.conf:
# static text file
table <blockedips> persist file “/etc/pf.blocked.ip.conf”
block in on bnx0 from <blockedips> to any
# not persistent pf table
table <bruteforce> persist
block quick from <bruteforce>
pass inet proto tcp from any to any port \
ssh flags S/SA keep state (max-src-conn 5, \
max-src-conn-rate 5/30, overload <bruteforce> flush global)
Now we would like to dump the bruteforce table into the /etc/blocked.ip.conf file, to have a record of our unwated IPs. A simple dump command is this one:
# pfctl -t bruteforce -T show
but this creates unwanted spaces that must be eliminated. We’ll use sed for this:
# pfctl -t bruteforce -T show | sed ‘s/ //g’
Now the space is gone and we have a properly formatted list of blacklisted IPs. We cannot dumped it right into /etc/blocked.ip.conf, because there might be the same IPs on different lines and we don’t want to have a bloated file loaded by pf. Let’s crate a temporary file with both the content of the bruteforce table and /etc/blocked.ip.conf:
# pfctl -t bruteforce -T show | sed ‘s/ //g’ » /tmp/ip.conf
# cat /etc/blocked.ip.conf » /tmp/ip.conf
Not we have to eliminate the IPs that are found more than one time in that list. We can do this with uniq, but for this, our list have to be ordered with sort.
sort /tmp/ip.conf | uniq » /tmp/ip.final.conf
The file /tmp/ip.final.conf contains now a list with unique blacklisted IP form both out manual /etc/blocked.ip.conf and from what the system catched automatically. If an IP was found on both lists, at the end it will be present in our filter only once. So, after moving along some files and cleaning, we can have a nice procedure for pf IP filtering.
cp /tmp/ip.final.conf /etc/blocked.ip.conf
We can make a shell script out of these commands and have cron run it once a day for a manual and automatic, persistent pf IP filter.