Rules order randomly changes
-
Hmm...
It looks like everything revolves around two functions:
filter_rules_sort() and filter_rules_compare(), along with pfBlockerNG.It seems that if the 'seq' number—which appears to be a temporary sequential rule number—matches one of pfBlockerNG's numbers, issues arise. I discovered this after modifying the code to save those numbers into config.xml instead of just handling them in RAM.
After trial and error, I ended up with...
function filter_rules_compare($a, $b) { // 1️⃣ If both rules have `seq`, use it as the primary sorting criterion if (isset($a['seq']) && isset($b['seq'])) { return $a['seq'] - $b['seq']; } // 2️⃣ Ensure Floating and Ethernet rules are placed above standard rules $a_is_special = isset($a['floating']) || isset($a['ethernet']); $b_is_special = isset($b['floating']) || isset($b['ethernet']); if ($a_is_special && !$b_is_special) { return -1; // Floating/Ethernet rule comes first } if ($b_is_special && !$a_is_special) { return 1; // Standard rule comes after special rules } // 3️⃣ If both rules belong to the same interface, sort by `seq` if available if ($a['interface'] == $b['interface']) { if (isset($a['seq']) && isset($b['seq'])) { return $a['seq'] - $b['seq']; } } // 4️⃣ As a last resort, compare interface names return compare_interface_friendly_names($a['interface'], $b['interface']); }
and
function filter_rules_sort() { $rules = config_get_path('filter/rule', []); /* Step 1: Collect all existing `seq` values */ $existing_seq = []; foreach ($rules as $rule) { if (isset($rule['seq']) && is_numeric($rule['seq'])) { $existing_seq[] = $rule['seq']; } } /* Step 2: Find the next available unique `seq` */ $max_seq = empty($existing_seq) ? 0 : max($existing_seq); $used_seq = array_flip($existing_seq); /* Step 3: Assign unique `seq` only to new rules */ foreach ($rules as &$rule) { if (!isset($rule['seq']) || !is_numeric($rule['seq']) || isset($used_seq[$rule['seq']])) { do { $max_seq++; } while (isset($used_seq[$max_seq])); // Ensure `seq` is unique $rule['seq'] = $max_seq; $used_seq[$max_seq] = true; } } /* Step 4: Sort rules strictly by `seq` */ usort($rules, "filter_rules_compare"); /* ✅ Save `seq` in `config.xml` */ config_set_path('filter/rule', $rules); write_config("Updated firewall rule order"); }
I'm not sure if that's everything or if there's still something left to do—I'm still testing it as it is for now.
Of course, I'm not a real programmer—it's just ChatGPT and my pathetic attempts.
-
@w0w And this was on 25.03?
Recently I found one of our routers had several rules moved from near the top to the bottom of the list…still in order but last. I was upgrading from 24.03 to 24.11 and I’m not sure if it happened before or after.
Two others the separator bar had moved slightly but IIRC that was a bug a while back for that if adding or maybe copying rules, so I didn’t think much of that since the order was the same.
-
-
Not the same but perhaps related, rule numbers are not a fixed thing
And separator lines do not stay on their place. That is not new I did discover that I think two years ago.
One of the reasons I was looking into that is that I am exporting the rule list in favor of a GrayLog lookup table. I Graylog I like to see the rule description
I am still exporting that rule list now and than, but the rule numbers are unfortunately not completely stable.
One of the ways I did test this, in favor of the list but also in favor of rule groups, is that I did add a recognizable dummy rule at the to of each interface and interface group and on at the bottum. Those dummy rules (doing nothing) had an interface ID and a begin / start identifier hidden in the rule port number like "port is <90001> at the beginning of interface 9 and <90002> at the end of the rules related to inteface 9.
Perhaps this helps to track problems
-
@louis2
What packages you have installed? PfBlockerNG? -
@w0w My recent/only experience was on 24.11. We do have pfBlocker but have for years. I tried to compare the rule order of different backup config files but they seem basically the same. So it may have just happened at the time which might imply a rare issue/race condition/upgrade issue. Haven't noticed it on any other routers and I've upgraded 6 or so to 24.11 recently.
-
After further testing, another bug was found with sorting: when a user changes the order and deletes a rule, the next rule added to the list appears in the same position where the last deleted rule was placed. Corrected code below.
function filter_rules_sort() { $rules = config_get_path('filter/rule', []); /* Step 1: Find the highest existing `seq` value */ $max_seq = 0; foreach ($rules as $rule) { if (isset($rule['seq']) && is_numeric($rule['seq'])) { $max_seq = max($max_seq, $rule['seq']); } } /* Step 2: Ensure rules are stored in the order they appear in the GUI */ $new_seq = 0; foreach ($rules as &$rule) { $rule['seq'] = ++$new_seq; // Assign sequential order based on GUI order } /* Step 3: Sort rules strictly by `seq` */ usort($rules, "filter_rules_compare"); /* ✅ Save the correct order in `config.xml` */ config_set_path('filter/rule', $rules); write_config("Updated firewall rule order based on user-defined sorting."); }
-
@SteveITS
I rarely change anything in the rule settings, but almost every time I do—whether it's modifying, deleting, or moving something—this mess with movements happens often. -
I noticed the described behavoir on a system without any packages which can influence the rules at all. So it is just plain pf and related pfSense behavoir.
-
Thanks for the report and testing. A fix has been committed:
https://redmine.pfsense.org/issues/16076Use the commit ID
c181ebe180017116626da28f30407a1da3cba061
to apply the fix as a System Patch.Please report back if that does not address the issue.