Allowing connections from a specific country with pf

The DNSBL provides an easy way to allow or block access from IP addresses in specific countries for applications capable of using DNSBLs. Mail servers are the most popular example of this.

However, since you can rsync the rbldnsd zone files, it is possible to convert these into firewall tables that can be easily used to e.g. restrict ssh access to IP addresses in your own country. This page describes how to do precisely this.

I assume that you are running PF as your firewall.

Fetching and converting the zone

I have a user called "countries" that exists for the sole purpose of fetching the zone and its homedir is used for holding the zone data.

The perl script located in "/home/countries/bin/" takes care of fetching and converting:

#!/usr/bin/perl -w

use strict;

system "/usr/local/bin/rsync -v rsync:// /home/countries/zones/";

open (FILE1, "/home/countries/zones/") or die "Couldn't open /home/countries/zones/ for reading: $!";
open (FILE2, ">/home/countries/zones/dk.pftable") or die "Couldn't open /home/countries/zones/dk.pftable for writing: $!";

while (defined (my $line = <FILE1>)) {
        if ($line =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+)\s/) {
                print FILE2 $1, "\n";

close FILE2;
close FILE1;

The following entry in the crontab for the "countries" user makes it run every morning:

0 7 * * * /home/countries/bin/

Updating the firewall table

The table is simply called "dk" and updating it from the converted zone data is quite simple.

The following goes into the root crontab:

15 7 * * * /sbin/pfctl -t dk -T replace -f /home/countries/zones/dk.pftable

Using the table in the firewall rules

To allow ssh connections from entries in the "dk" table use a rule like this:

pass in proto tcp from <dk> to (self) port 22 keep state

If you want to list the currently loaded table, use this command:

pfctl -t dk -T show

E-mail Valid XHTML 1.1 Valid CSS!