Hi, I'd like to request the implementation of a new feature in pfctl. This new feature, as stated in the subject, would allow resetting the statistics for a single IP address. The resetting of statistics for all IP addresses in a specified table is already implemented (`pfctl -t sometable -T zero'). However, resetting the statistics for a single IP address in a table would allow me to continuously block repeat offenders, while releasing one-time offenders. The scenario I'm thinking about is as follows: An offender is added to a certain table, let's call it <blocked>, either by PF using the 'overload' feature, an external tool like blacklistd or fail2ban, or manually. A cronjob expires addresses in table <blocked> after a time period X (`pfctl -t blocked -T expire 1209600'). An external tool like blacklistd or fail2ban (or something home-brewn) tracks the PF log, and resets the statistics for offending hosts that are already in table <blocked>. This way, repeat offenders will remain in table <blocked> indefinitely, while hosts that attacked my server 'by accident' will get a retry. PF already supports the necessary ioctl command DIOCRCLRASTATS, which does exactly what I want. So only pfctl would need to be patched for this feature to be implemented. Actually, thinking FreeBSD pfctl was the same as OpenBSD pfctl, I requested this feature on the OpenBSD bugs mailing list yesterday. The request was accepted, and a patch was committed this afternoon. However, after all this, they told me that the 2 are not the same, and I should make a new feature request here. So, here it is. More info can be found on the OpenBSD bugs and tech mailing lists: https://marc.info/?l=openbsd-bugs&m=173206758904599&w=2 https://marc.info/?l=openbsd-tech&m=173210109222862&w=2 And the definitive OpenBSD patch is here: https://marc.info/?l=openbsd-tech&m=173210375324534&w=2 Thank you for considering this feature request. Sincerely, Rob LA LAU
Please find the patch ported to FreeBSD here https://reviews.freebsd.org/D47698 . It also lead to finding a bug https://reviews.freebsd.org/D47697 , so you probably want to apply both patches. I've developed them on the main branch, but they apply to FreeBSD 14 too, however I have not tested them on 14.
Thank you so much for your quick response. Will take a few days to get back to you with results (working today and this weekend).
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=6463b6b59152fb1695bbe0de78f6e2675c5a765a commit 6463b6b59152fb1695bbe0de78f6e2675c5a765a Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2024-11-21 20:33:41 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2024-11-22 11:22:16 +0000 pfctl: clear statistic for specified addresses The ioctl DIOCRCLRASTATS provides the functionality of clearing stats not only for the whole table for for addresses stored in that table. The functionality was missing from pfctl, though. Add it now. PR: 282877 Obtained from: OpenBSD, kirill <kirill@openbsd.org>, e496dff3a7 MFC after: 3 weeks sbin/pfctl/pfctl.8 | 6 ++--- sbin/pfctl/pfctl.h | 1 + sbin/pfctl/pfctl_radix.c | 23 +++++++++++++++++ sbin/pfctl/pfctl_table.c | 17 +++++++++++-- tests/sys/netpfil/pf/table.sh | 57 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 5 deletions(-)
Created attachment 255439 [details] pfctl -T makezero > An external tool like blacklistd or fail2ban (or something home-brewn) > tracks the PF log, and resets the statistics for offending hosts > that are already in table <blocked>. That's certainly an existing pattern for pf table management. E.g. https://forums.freebsd.org/threads/pf-firewall-expiretable.61827/ discusses that as well. I'd like to suggest one more patch, that makes alike pattern easier to implement for home-brewers. Feeding pflog to blacklistd is fine, but `pf` tables also have counters those can be used for the same purpose. So this policy might be implemented using either pflog or pf table counters and these solutions might have different performance and reliability characteristics. As far as I understand, `counter` is always incremented on a match, but pflog might be dropping packets in case of consumer being somewhat slow. So I suggest to add a table command "makezero" that combines semantics of `make` (doing things incrementally and as-necessary) and `zero` clearing statistics. :-) In the case of table counters having an acceptable overhead, the cron-job would be as simple as pfctl -t blocked -T makezero && pfctl -t blocked -T expire 1209600
Leonid, I think that should be a separate feature request. I have some thoughts about your idea, but I won't post them in this feature request. Rob
(In reply to Rob LA LAU from comment #5) Thanks, Rob. I agree, that would be closer to the due process. I've submitted the patch to #282984 WBR, Leonid.
Back to the original feature request. The patch works as expected on 14.1-RELEASE. Thank you so much!