All posts Feature

RULE and ALIAS Snippets Now Set Every OPNsense Field, and Place Rules Where You Said

FEATURE 8 MIN READ NETDEFENSE TEAM

A RULE snippet that said "log": "1" used to sync without logging. NetDefense sent twelve settings of the rule to OPNsense (its identity and enabled flag among them) and dropped the rest without a word. A PREPEND rule had a quieter version of the same problem: it was meant to come before the firewall’s own rules, but on OPNsense 26.7 it landed after them, behind the default “allow LAN to any” rules, so a PREPEND block rule could sit there never deciding anything.

Both are fixed. A RULE snippet can set any field of OPNsense’s rule model, an ALIAS snippet any field of an alias, and PREPEND and APPEND now work inside each OPNsense 26.7 rule section. The release is live: agent 1.23.0, ndcli 1.38.0, the web app and the control plane.

If your snippet files live in git and CI applies them with ndcli or the API, read on. The same file can now behave differently on a firewall, and a few files that were accepted before are refused.

TL;DR

  • Any field of a rule or alias can be set, under its OPNsense API name. A field the snippet leaves out is set to OPNsense’s default at every sync.
  • PREPEND rules come ahead of the device’s own rules in their section, unless OPNsense refuses to re-save one of those rules. To make room, the device’s own rules can get higher sequence numbers: same order, every move reported.
  • At save, values in RULE, ALIAS and UNBOUND snippets must be strings, and every rule needs an action. Snippets already stored aren’t re-checked.
  • At sync, a misspelled field fails that rule or alias, and a device on an agent older than 1.23.0 is refused outright when it would apply the snippet only in part.
  • The first sync that reaches a firewall after it upgrades to 1.23.0 re-places rules even if no template changed.

What you can set now

Use the field’s name from OPNsense’s API: log, quick, statetype or gateway on a rule, proto, updatefreq or interface on an alias. Which fields exist depends on the OPNsense release each firewall runs. Pulling a rule or alias you built by hand in the OPNsense interface remains the quickest way to see the names and values.

allow-dns.json json
{   "enabled": true,   "action": "pass",   "interface": "lan",   "protocol": "TCP/UDP",   "destination_net": "dns_servers",   "destination_port": "53",   "log": "1",   "description": "Allow DNS queries to internal resolvers" }

The field contract, the value forms and the full list of result codes are in Snippets; this post covers what changes for you.

Where PREPEND and APPEND rules land

OPNsense 26.7 evaluates rules section by section: floating rules, then interface-group rules, then single-interface rules. NetDefense now orders inside each section: PREPEND rules first, then the device’s own rules, then APPEND rules. Among themselves, PREPEND rules keep their priority order, and so do APPEND rules.

A fresh OPNsense 26.7 has its default LAN allow rules at sequence 1 and 11, so there is often no free number ahead of them. To make room, NetDefense may raise the sequence number of the device’s own rules in that section. It keeps their order, changes nothing else about them, and reports every move in the sync result as a renumbered item with the old and the new number. It never lowers a number and never touches a section that has no PREPEND rule. See Policy Chain for the section order, what position can’t change, and the placement result codes.

A PREPEND block rule can start blocking

If you had a PREPEND rule that blocked traffic the default allow rules already passed, it never decided anything. Now it comes first, so it blocks. That’s the intent of PREPEND, but check such rules before the first sync on 1.23.0.

What changes on your firewalls with the same file

Nothing in these files has to change for the firewalls to change, once the agent is on 1.23.0.

  • Fields that used to be dropped now apply. log, quick, gateway, statetype and the rest. Take quick seriously: it changes evaluation order, and a quick rule decides as soon as it matches.
  • Content is declarative. A managed rule or alias is exactly its snippet. A field the snippet doesn’t set goes to OPNsense’s default at every sync. If someone turned on logging by hand in the OPNsense interface, or changed an alias’s refresh interval or categories, the next sync resets it. To keep a setting, put it in the snippet.
  • sequence in the content is ignored. Placement comes from the template’s position and the snippet’s priority.
  • The first sync that reaches a firewall after the upgrade re-places rules even if no template changed. A sync of an unchanged configuration is skipped unless you use --force. PREPEND rules an older agent put after the device’s own rules move ahead of them, with the renumbering above, and hand-made settings on managed rules and aliases reset.

Firewalls installed from the NetDefense repository upgrade the agent along with their OPNsense updates, so there may be no separate moment to prepare. The upgrade note says what to pull and copy into snippets before that update.

What is now refused at save

These checks run when you upload or update a snippet, so a pipeline learns about them immediately. Snippets already stored aren’t re-checked and keep working.

  • In RULE, ALIAS and UNBOUND_* snippets, values must be JSON strings. Write "443", not 443, and "1" and "0", not true and false. Exceptions: enabled may be a string or a boolean, a few other switch fields may also be booleans, an alias’s content and an UNBOUND_ACL’s networks may be lists, and keys that appear only in pulled output take any value. The refusal names the field and the form to write.
  • Every RULE needs a non-empty action. OPNsense’s default action is pass, so a rule without one would let traffic through. The refusal reads: content must include a non-empty 'action': OPNsense's default action is pass, so a rule without one would let traffic through.
  • GROUP members must be a list, "" or null. A comma-separated string used to be ignored, and entries that aren’t strings are refused too.

What now fails at sync

Before, an unknown key was ignored. Now it fails.

  • Unknown or misspelled keys fail that rule or alias. A "lgo": "1" gives RULE_FIELD_UNKNOWN (ALIAS_FIELD_UNKNOWN for an alias), with a “did you mean” hint and the firewall’s OPNsense version. The rest of the sync still applies, and the task ends FAILED. OPNsense adds fields within a release line, so a field can be valid on one 26.7 point release and unknown on an earlier one.
  • A list value of only blanks or commas is refused.
  • An old agent is refused for its whole sync. A device on an agent older than 1.23.0 gets SNIPPET_AGENT_TOO_OLD when its snippet content is something that agent would apply only in part, for example a non-default value in a field it drops. No task is created for that device and nothing reaches it until the agent is upgraded or the snippet edited. A field left at OPNsense’s default doesn’t count.
ndcli sync apply text
Errors:   • fw-branch-01: [SNIPPET_AGENT_TOO_OLD] This device's NetDefense agent (1.22.1) applies these snippets only in part; upgrade the agent to 1.23.0 or later, or edit what is listed: allow-https (RULE: fields it ignores: log, source_not; ...)

Upgrade before you add the new fields

Add log, quick or gateway to a snippet only after the firewalls it reaches run 1.23.0. Until then, the firewalls still on an older agent are refused for their whole sync instead of getting a rule that silently lacks the field. See Agent and OPNsense versions.

For automation: ndcli 1.38.0

Exit codes are unchanged. What changes is what the output says, and what you filter on.

  • Warnings show ⚠ in every result family. Some warnings, such as a failed package-catalog refresh, used to show ✗.
  • New items. A renumbered item shows as ~ with its before and after sequence, and an unchanged rule or alias shows as =. -f json carries the new codes and actions.
  • --org and --ou match exact names. They always did on the server; the help text used to say regex. --device and --template are unanchored regular expressions, so --device fw-01 also syncs fw-010. Anchor a single device as ^fw-01$.
  • Pulled content changed. ndcli snippet pull now returns the identifying fields plus every field that differs from OPNsense’s default, as strings, so a diff against a file you stored earlier will show changes.
ndcli bash
$ ndcli sync apply --device '^fw-branch-01$'

The flags are in the sync reference and the content contract is in the snippet reference.

Checklist for snippet files in a repository

  • Quote every value, apart from enabled and list-valued content or networks.
  • Set action on every rule.
  • Drop sequence, and any key OPNsense’s model doesn’t have.
  • Include every non-default setting you rely on. A sync resets the rest.
  • Check PREPEND block rules, and rules with quick, against the order they will now have.
  • Upgrade agents to 1.23.0 before adding fields that older agents drop.
  • Review snippets you pulled with an older agent before upgrading: they hold every field of their source, including ones the old agent ignored, and 1.23.0 applies them all.
  • Anchor single-device filters in sync commands as ^name$.
  • Expect renumbered items in the first sync result after an upgrade. They are the device’s own rules getting higher sequence numbers, in the same order.

Related reading

Feature Firmware Tracks: Stage OPNsense Updates from Fast to Stable
Feature Certificate Sync for OPNsense: Renew Once, Every Firewall Follows
Security Superuser Clearance for Snippets That Grant Firewall Admin Rights

Enjoyed this post? Explore more in the documentation.