ipfw Table Organization

Michael Sierchio kudzu at tenebras.com
Thu Aug 26 21:58:26 UTC 2021


On Thu, Aug 26, 2021 at 2:12 PM Tim Daneliuk via freebsd-questions <
freebsd-questions at freebsd.org> wrote:

>
>
> As I thought about this, it led to a followup question.  Imagine
> I have populated a table and then run this command:
>
>     ipfw add deny all from table\(10\) to any via em0
>
>
> If I then later update the contents of table 10, will those changes go live
> on the firewall, or is the binding of table content to firewall rules only
> relevant at the time the "add deny" is invoked?
>

The answer is an unequivocal yes.  You can start with an empty table, and
keep modifying it  on the basis of events, on a cronjob, etc. The rule does
the table lookup at the time of execution, and the table contents can be
changing all the time.

If you have a blocklist, have a whitelist.  Not kidding.  For example, so
many useful things
don't work in AWS if you block 169.254.0.0/16 – 169.254.169.254 is metadata
service,
.253 is DNS, .123 is NTP, etc.

Yes. I recommend you write that as two rules so it doesn't get matched 4
times. ;-)

ipfw add deny ip from table\(10\) to any in recv em0

# warn internal hosts

ipfw add unreach filter-prohib from any to table\(10\) out xmit em0


The answer is an unequivocal yes.  You can start with an empty table, and
keep modifying it  on the basis of events, on a cronjob, etc. The rule does
the table lookup at the time of execution, and the table contents can be
changing all the time.

I fetch the full bogons list hourly.

To change the table contents atomically, swap the tables – with I do this:

Assumptions:


   - For every table X, there is a table named X-alt.  The have the same
   contents except when being changed.
   - The database consists of .txt files in /var/db/ipfw/X/cidr (there is a
   /var/db/ipfw/X/src, more on that later).
   - The .txt files contain entries like

   223.247.130.195/32 4295

   223.247.153.244/32 4295

   223.247.194.119/32 4295

   2001:558:6045:52:f093:7192:8eb6:7cb7/128 4295

   2001:912:800:212::61/128 4295

   (the table arg says what file it's from, which may mean a particular
   blocklist)

Script:

#!/bin/sh



PATH=/etc/ipfw:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin

export PATH


BASEDIR="/var/db/ipfw"


if [ $# -lt 1 ]; then

        echo "usage: ipfw-table-update <list-name>"

        exit 64

fi


LIST=$1 ; export LIST


IPFW="/sbin/ipfw -q" ; export IPFW


################################################################################

# GUSTY WINDS MAY EXIST

#

$IPFW table ${LIST} create >/dev/null 2>&1

$IPFW table ${LIST}-alt create >/dev/null 2>&1


cd ${BASEDIR}/${LIST}/cidr


################################################################################

# combine lists

#

cat *.txt | awk '/^[^ #-]/ { print $1, $2 }' > .X


################################################################################

# split into files of no more than 8192 entries

#

PFX=".${LIST}-tmp" ; export PFX

split -l 8192 .X $PFX


################################################################################

# swap table with table-alt, flush alt, load alt

#

$IPFW  table ${LIST} swap ${LIST}-alt ; $IPFW  table ${LIST}-alt flush

for f in ${PFX}* ; do

        $IPFW table ${LIST}-alt add `cat $f`

done


################################################################################

# repeat to load other table

#

$IPFW  table ${LIST} swap ${LIST}-alt ; $IPFW  table ${LIST}-alt flush

for f in ${PFX}* ; do

        $IPFW table ${LIST}-alt add `cat $f`

done

rm -f ${PFX}* .X


More information about the freebsd-questions mailing list