Policy Chain
The policy chain is the final, ordered configuration that a device receives. It is assembled automatically by NetDefense from the templates assigned to the device’s organizational units.
Understanding how the policy chain is built is key to designing effective security policies across your organization.
How the Policy Chain is Built
Section titled “How the Policy Chain is Built”-
Collect — NetDefense gathers all snippets from every template assigned to every OU the device belongs to.
-
Deduplicate — If the same snippet appears in multiple templates (e.g., because two OUs share a template), it is included only once. If that snippet appears in both a PREPEND and an APPEND template, it is treated as PREPEND (the more restrictive position wins).
-
Sort by priority — All collected snippets are sorted by their absolute priority number (lowest first), regardless of which template they came from. Ties are broken alphabetically by snippet name.
-
Split by position — The sorted list is then split into two groups: PREPEND snippets and APPEND snippets.
-
Place — On the device, each firewall rule goes into the OPNsense rule section its interfaces put it in. Inside each section, the order is: PREPEND rules (in priority order) → the device’s own rules → APPEND rules (in priority order), with the device’s legacy rules, if any, last. See Where rules land on the device.
Key Insight: Snippets Are Interleaved by Priority, Not Grouped by Template
Section titled “Key Insight: Snippets Are Interleaved by Priority, Not Grouped by Template”This means you can control the exact ordering of rules across templates simply by choosing the right priority numbers. A snippet with priority 25 in corporate-services would be inserted between rate-limit-icmp (20) and anti-spoofing (30), even though they come from different templates. That order holds among rules in the same OPNsense rule section; across sections, OPNsense’s own order comes first — see Where rules land on the device.
Worked Example: Production OU
Section titled “Worked Example: Production OU”The production OU has three PREPEND templates: base-hardening (priorities 10—50), corporate-services (priorities 100—210), and intrusion-prevention (priorities 500—520). The resulting PREPEND section is a single sorted sequence:
Priority 10 → drop-invalid-state (from base-hardening)Priority 20 → rate-limit-icmp (from base-hardening)Priority 30 → anti-spoofing (from base-hardening)Priority 40 → block-bogon-ranges (from base-hardening)Priority 50 → log-and-drop-default (from base-hardening)Priority 100 → allow-established (from corporate-services)Priority 150 → trusted-networks (from corporate-services)Priority 160 → dns-servers (from corporate-services)Priority 200 → allow-dns-ntp (from corporate-services)Priority 210 → allow-ldap-internal (from corporate-services)Priority 500 → geoip-filter (from intrusion-prevention)Priority 510 → port-scan-detect (from intrusion-prevention)Priority 520 → geoip-blocklist (from intrusion-prevention) ↓Device-local rules (if any)All 13 snippets from three different templates are merged and sorted by priority into a single PREPEND block, followed by any device-local rules. On the device, each rule then goes into its OPNsense rule section, in this order. Only the rules among them are ordered: block-bogon-ranges, trusted-networks, dns-servers and geoip-blocklist are aliases, which position and priority don’t order.
Worked Example: Guest Networks OU
Section titled “Worked Example: Guest Networks OU”The guest-networks OU has two PREPEND templates: base-hardening and guest-isolation. The device receives all 8 snippets sorted by priority as a single PREPEND block:
Priority 10 → drop-invalid-state (from base-hardening)Priority 20 → rate-limit-icmp (from base-hardening)Priority 30 → anti-spoofing (from base-hardening)Priority 40 → block-bogon-ranges (from base-hardening)Priority 50 → log-and-drop-default (from base-hardening)Priority 300 → guest-internet-only (from guest-isolation)Priority 310 → block-internal-nets (from guest-isolation)Priority 320 → guest-rate-limit (from guest-isolation) ↓Device-local rules (if any)Notice how the guest isolation rules (300—320) slot in naturally after the base hardening rules (10—50) thanks to their higher priority numbers. The two templates share no snippets, so there is nothing to deduplicate — the result is simply a merged, priority-sorted list. Only its rules are ordered on the device: block-bogon-ranges is an alias.
Where Rules Land on the Device
Section titled “Where Rules Land on the Device”OPNsense evaluates firewall rules section by section:
- Floating rules — a rule with no interface, with several interfaces, or with its interface selection inverted (
interfacenot). - Interface-group rules — a rule on one interface group, such as
wireguard. Groups are evaluated one after another, in the order of their own sequence numbers. - Single-interface rules — a rule on one interface, such as
lan.
NetDefense orders rules only inside a section, never across sections. In each one, PREPEND rules come before the device’s own rules, and APPEND rules after them, except legacy rules (not yet migrated), which OPNsense always evaluates last in a section:
Floating rules PREPEND → device's own rules → APPEND → device's legacy rulesInterface-group rules PREPEND → device's own rules → APPEND → device's legacy rulesSingle-interface rules PREPEND → device's own rules → APPEND → device's legacy rulesWithin a section, PREPEND rules keep their priority order among themselves, and so do APPEND rules: a PREPEND rule at priority 500 still comes before an APPEND rule at priority 10. Across sections OPNsense’s order comes first, whatever the priority: a floating rule at priority 500 is evaluated before a single-interface rule at priority 10.
This needs agent 1.23.0 or later, and is verified on OPNsense 26.7 — see Agent and OPNsense versions.
What Position Can’t Change
Section titled “What Position Can’t Change”Because OPNsense’s section order comes first:
- A single-interface PREPEND rule comes after the device’s floating and interface-group rules. One of those that matches the same traffic decides first.
- An APPEND rule on several interfaces is a floating rule, so it comes before the device’s interface-group and single-interface rules. An APPEND rule on
lan,opt1is evaluated before the device’s own LAN rules. - Legacy rules come after every managed rule of their section. These are the device’s rules from before OPNsense’s current rule format, which OPNsense doesn’t migrate on its own, so an APPEND rule comes before them. It’s common: a device upgraded from OPNsense 26.1 or earlier keeps its default LAN allow rules as legacy rules, so an APPEND rule on LAN is evaluated before them. Migrating them in OPNsense, under Firewall > Migration assistant (shown while legacy rules exist), lifts this.
- OPNsense’s automatic rules keep their place. Some, such as the anti-lockout rule, come before every section, so no PREPEND rule precedes them. Others come after every section, such as the pass rule OPNsense can add for a port forward: an APPEND rule on WAN that blocks the forwarded traffic, with
quickon, blocks the port forward too.
A sync warns about the first three whenever an enabled rule of the device shares an interface with the managed rule, and about two managed rules sharing an interface that the section order puts the other way round. Disabled rules keep their place but never cause a warning.
Quick Rules
Section titled “Quick Rules”OPNsense rules have a quick setting, on by default. A quick rule decides as soon as it matches: no later rule is evaluated. A rule with quick off doesn’t stop evaluation, and a later rule that matches the same traffic replaces its decision. A PREPEND rule with quick off is therefore only a default that the device’s own rules can override.
The Device’s Own Rules Can Be Renumbered
Section titled “The Device’s Own Rules Can Be Renumbered”Inside a section, OPNsense orders rules by a sequence number. A new rule gets a number after every existing one, and a fresh OPNsense 26.7 has its default LAN rules at 1 and 11, so there’s often no free number below the device’s own rules. NetDefense then raises the sequence numbers of the device’s own rules in that section — that number only, keeping their order — so the PREPEND rules come first. It never lowers one, and never changes a section that holds no PREPEND rule. Each change is listed in the sync result with the old and the new number. On OPNsense 26.7.4 and later, OPNsense stamps each move in the rule’s audit information under the NetDefense agent’s account: its last-updated entry and, for a rule that had no audit information yet, its created entry too.
The first sync after a PREPEND rule is added, or after the device’s agent is upgraded to 1.23.0, can raise the sequence numbers of several of the device’s rules. Each of those changes is saved as a separate configuration revision on the device, and the sync result lists them all. Later syncs leave the rules as they are while their order holds.
Moving one of the device’s rules above a PREPEND rule in OPNsense lasts until the next sync that reaches the device, which moves it back.
A rule that can’t be moved keeps its number, the PREPEND rules of its section go right after it, and the sync fails naming it. That happens when OPNsense refuses to save the rule with its new number, when the rule can’t be read before the move, and when it reads as nothing but OPNsense’s defaults, as a rule does whose only settings are a gateway or schedule that no longer exists. NetDefense doesn’t move such a rule, because a rule its move had re-created would look the same. A rule with other settings that names a missing gateway or schedule is refused by OPNsense when the move saves it.
A move writes only the sequence number, but OPNsense saves a rule it can’t find as a new one with its defaults: a pass rule on every interface. So NetDefense reads each rule before and after moving it. A rule deleted on the device during the sync isn’t moved, and one the move re-created is deleted again, or disabled if it can’t be deleted. When NetDefense can’t rule out such a pass rule, it doesn’t apply the firewall rules in that sync, and the sync fails naming the rule. That only delays it: a re-created rule is already saved in the configuration, and the next firewall apply loads it. The message names the rule by the description it had (its UUID if it had none), but the re-created rule has none: on the device, look for a pass rule on every interface with no description, delete it if you didn’t create it, then sync again.
Placement Results
Section titled “Placement Results”ndcli task describe, or the task’s page in the web app, lists these with the sync’s other results. Warnings don’t fail the task. An error fails it, and the rest of the configuration still applies, except that after RULE_APPLY_WITHHELD the firewall rules aren’t applied in that sync.
| Code | Meaning | Fix |
|---|---|---|
RULE_LOCAL_RENUMBERED | One of the device’s own rules got a higher sequence number, to keep the PREPEND rules first. The result shows the old and the new number. | Nothing to do. |
RULE_LOCAL_VANISHED | Warning: one of the device’s own rules was deleted on the device during the sync, before or right after its move. When the answer to its move was lost, the message says it may have been deleted before the move or after it, and that a move still in flight can re-create it as a pass rule on every interface with no description. | Nothing to do, unless the message mentions a pass rule: then look for one on the device. |
RULE_PREPEND_AFTER_LOCAL | Warning: a PREPEND rule comes after a floating or interface-group rule of the device on one of its interfaces. | Check that the device’s rule should decide first. If not, change or disable it. |
RULE_APPEND_BEFORE_LOCAL | Warning: an APPEND rule comes before a rule of the device on one of its interfaces: one in a later section, or a legacy rule. | Migrate legacy rules in OPNsense, under Firewall > Migration assistant. Otherwise, check that the order is what you want. |
RULE_SECTION_ORDER | Warning: two managed rules on a shared interface are evaluated in the opposite order to their position and priority, because they’re in different sections. | Put both in the same section, or accept the order. |
RULE_SECTION_MISMATCH | Warning: OPNsense ranks a managed rule in a different section from the one the device’s interface groups give it, so the rule is placed where OPNsense ranks it. It repeats on every sync while the two disagree. | Check the rule’s interfaces and the device’s interface groups. |
RULE_LOCAL_RENUMBER_FAILED | Error: one of the device’s own rules wasn’t moved, so the PREPEND rules of its section were placed after it. OPNsense refused its new number, the answer to the move was lost and the rule reads unchanged at its old number (the message gives the error), it couldn’t be read before the move, or it reads as nothing but OPNsense’s defaults (its only settings may be a gateway or schedule that no longer exists). | If OPNsense refused it, fix or delete the rule in OPNsense. If it couldn’t be read, sync again. If it holds only defaults, give it a description, or fix what it names. |
RULE_LOCAL_RENUMBER_UNVERIFIED | Error: one of the device’s own rules changed on the device while the sync moved it, or couldn’t be read back afterwards. When the answer to its move was lost, the message says the rule may have been moved, and that the move may have re-created it. It’s left as it is, unless the move re-created it as a pass rule, which NetDefense deletes again or disables. When such a pass rule can’t be ruled out, the firewall rules aren’t applied in that sync. | Check the rule named on the device. If the message says to delete it, look for a pass rule on every interface with no description: the re-created rule has none. Then sync again. |
RULE_APPLY_WITHHELD | Error: the firewall rules weren’t applied in this sync, because a rule of the device may be a pass rule a renumber re-created. The message names each such rule. | On the device, look for a pass rule on every interface with no description (the message names it by the description the rule had before, its UUID if it had none). Delete it if you didn’t create it: it’s already saved, and the next firewall apply loads it. Then sync again. |
RULE_NO_SEQUENCE_ROOM | Error: no sequence number is left after the device’s own rules for an APPEND rule (OPNsense’s highest is 999999). That rule isn’t written. | Give the device’s own rules in that section lower sequence numbers in OPNsense. |
RULE_PLACEMENT_UNAVAILABLE | Warning: the device’s interfaces or interface groups couldn’t be read. Managed rules kept their sequence numbers, and new ones went after every rule. | Sync again. |
RULE_PLACEMENT_UNVERIFIED | Error: OPNsense put a rule in a different section from the one NetDefense computed, so its place among the device’s rules isn’t verified. | Sync again, and contact support if it persists. |