Misunderstanding of behavior of pf?

From: Alexander Leidinger <Alexander_at_Leidinger.net>
Date: Fri, 13 Feb 2026 14:38:19 UTC
Hi,

it seems I have some kind of misunderstanding how PF is supposed to 
behave...

I have a persistent table ("bruteforce") which contains an IP. After a 
reboot the IP should not be allowed to reach any service (I validated 
that the IP is in the table after the reboot), but I still see this IP 
showing up in sshd auth logs (the usual probing).

The external interface (igb0) is a member of a bridge. The host-IP is on 
the bridge, no IP on the external interface. The pf rules are on the 
external interface. The sshd which is listening on the IP of the bridge 
is still logging the IP. Config below.

The packets enter the system via igb0, no other NIC configured or 
attached. To my understanding the rules below should block IPs in the 
bruteforce table and sshd should not see connections from those IPs.

ifconfig vswitch0 | head -5:
---snip---
vswitch0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> 
metric 0 mtu 1500
         description: VNET jails switch
         options=10<VLAN_HWTAGGING>
         ether a:b:c:d:e:f
         inet 192.168.x.y netmask 0xffffff00 broadcast 192.168.x.255
---snip---

ifconfig vswitch0 | grep igb0:
---snip---
         member: igb0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
---snip---

sysctl net.link.bridge:
---snip---
net.link.bridge.ipfw: 0
net.link.bridge.member_ifaddrs: 1
net.link.bridge.log_mac_flap: 1
net.link.bridge.allow_llz_overlap: 0
net.link.bridge.inherit_mac: 1
net.link.bridge.log_stp: 0
net.link.bridge.pfil_local_phys: 0
net.link.bridge.pfil_member: 0
net.link.bridge.ipfw_arp: 0
net.link.bridge.pfil_bridge: 0
net.link.bridge.pfil_onlyip: 1
---snip---

I also tried with net.link.bridge.pfil_member=1, same behavior.

pf.conf:
---snip---
ext_if = "igb0"

set loginterface $ext_if
set skip on lo0
#set skip on vswitch0
set block-policy return
set reassemble yes

# tables
table <bruteforce> persist file "/var/db/pf/bruteforce.table"
table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \
         100.64.0.0/10 192.88.99.0/24 \
         172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \
         192.168.128.0/17 192.168.64.0/18 192.168.32.0/19 192.168.16.0/20 
\
         192.168.8.0/21 192.168.4.0/22 192.168.2.0/23 192.168.0.0/24 \
         198.18.0.0/15 198.51.100.0/24 \
         203.0.113.0/24 }
table <martians6> { 100::/64  2001:db8::/32 3fff::/20 }
table <crowdsec-blocklists> persist file 
"/var/db/pf/crowdsec-ipv4.blocklist"
table <crowdsec6-blocklists> persist  file 
"/var/db/pf/crowdsec-ipv6.blocklist"

# hygiene
scrub in all

# blacklistd
anchor "blacklistd/*" in on $ext_if

# hygiene
block in quick log on $ext_if from <martians> to any
block in quick log on $ext_if from <martians6> to any
block in quick log on $ext_if from <bruteforce> to any
block return out quick log on $ext_if from any to <martians>
block drop in quick on $ext_if from <crowdsec-blocklists> to any
block drop in quick on $ext_if from <crowdsec6-blocklists> to any
---snip---

Bye,
Alexander.

-- 
http://www.Leidinger.net Alexander@Leidinger.net: PGP 0x8F31830F9F2772BF
http://www.FreeBSD.org    netchild@FreeBSD.org  : PGP 0x8F31830F9F2772BF