Re: Issues with IPFW skipto Rule and Whitelisting Logic
Date: Sun, 13 Jul 2025 20:55:45 UTC
I haven't had a chance to read this in detail, but what about UDP? Most DNS traffic is UDP. And these lines are subtly wrong: *$cmd 10031 allow tcp from me to any dst-port 443 out via $pif setup keep-state$cmd 10033 allow tcp from any to me dst-port 443 in via $pif setup keep-state* because 'via' causes these rules to catch packets twice as they're processed by the kernel. IMHO these should be $cmd 10031 allow tcp from me to any dst-port 443 out xmit $pif setup keep-state $cmd 10033 allow tcp from any to me dst-port 443 in recv $pif setup keep-state I'll have more comments when I get a chance to peruse fully. On Sun, Jul 13, 2025 at 4:41 PM Christos Chatzaras <chris@cretaforce.gr> wrote: > I am using ipfw with these rules: > > ---------------- > #!/bin/sh > > # Set rules command prefix > cmd="ipfw -q add " > cmd2="ipfw -q " > > # Public interface > pif=`ifconfig -l | awk '{ print $1 }'` > > # Flush all rules > ipfw -q -f flush > > # Flush all tables > $cmd2 table 1 flush > $cmd2 table 3 flush > > # Allow loopback and deny loopback spoofing > $cmd 00010 allow ip from any to any via lo0 > $cmd 00020 deny ip from any to 127.0.0.0/8 > $cmd 00030 deny ip from 127.0.0.0/8 to any > > # Catch spoofing from outside. > $cmd 00031 deny ip from any to any not antispoof via $pif > > # Checks stateful rules > $cmd 00050 check-state > $cmd 00060 deny tcp from any to any established > > # ALLOW WHITELIST - IGNORE RULE 00100 > $cmd2 00070 add skipto 00101 ip from 'table(3)' to any > > # DENY INCOMING LIST > $cmd 00100 reset ip from 'table(1)' to any > > # ICMP > $cmd 01010 allow icmp from any to any out via $pif keep-state > $cmd 01011 allow icmp from any to any in via $pif > > # WWW > $cmd 10031 allow tcp from me to any dst-port 443 out via $pif setup > keep-state > $cmd 10033 allow tcp from any to me dst-port 443 in via $pif setup > keep-state > > # Deny everything else, and log it > $cmd 56599 deny log all from any to any > ---------------- > > And ipfw list includes: > > ---------------- > 00070 skipto 101 ip from table(3) to any > 00100 reset ip from table(1) to any > ---------------- > > Currently, table(1) holds about 1.9 million entries (both individual IPs > and subnets), while table(3) contains about 10,000 entries (also a mix of > single IPs and subnets). > > These tables are populated using this script few times per day: > > ---------------- > #!/bin/sh > > tempdir=$(mktemp -d /tmp/ipfw.XXXXXX) > trap "rm -rf $tempdir" EXIT > > fetch -q -o "$tempdir/allow.txt" https://example.com/ipfw/allow.txt || > exit 1 > fetch -q -o "$tempdir/deny.txt" https://example.com/ipfw/deny.txt || exit > 1 > > update_table() { > table=$1 > file=$2 > current_file="$tempdir/current_table_$table.txt" > ipfw -q table "$table" list | awk '{print $1}' | sed 's/\/32$//' | > sort > "$current_file" > cat "$file" | sed 's/\/32$//' | sort | uniq > > "$tempdir/new_table_$table.txt" > > comm -13 "$tempdir/new_table_$table.txt" "$current_file" | while read > -r ip; do > [ -n "$ip" ] && ipfw -q table "$table" delete "$ip" > done > > comm -23 "$tempdir/new_table_$table.txt" "$current_file" | while read > -r ip; do > [ -n "$ip" ] && ipfw -q table "$table" add "$ip" > done > } > > update_table 3 "$tempdir/allow.txt" > update_table 1 "$tempdir/deny.txt" > ---------------- > > My intended logic is that any IP present in table(3) should always be > allowed, even if it or its subnet also appears in table(1). > > For instance, 175.178.167.241 is in table(3), while 175.178.0.0/16 is > present in table(1). > > After rebooting the server and populating the tables by running the update > script for the first time, access from 175.178.167.241 works correctly. > However, after subsequent runs of the update script - which only updates > unrelated entries and does not modify 175.178.167.241 or 175.178.0.0/16 - > access from 175.178.167.241 is no longer permitted. > > Additionally, when this issue arises, adding 175.178.0.0/16 to table(3) > allows access again. Even after removing that entry, as long as > 175.178.167.241 remains in table(3) and I wait for any active sessions to > clear, access continues to work. > > Does anyone have any ideas about what could be causing this behavior? >