Skip to content

Snippets

A snippet is the smallest unit of configuration in NetDefense. Each snippet contains a piece of JSON configuration that maps to a specific feature on the firewall device — a rule, an alias, a DNS override, and so on.

Snippets are reusable building blocks: you create them once at the organization level, then compose them into templates. The same snippet can appear in multiple templates, which means a single change to a snippet automatically propagates to every template (and therefore every device) that uses it.

Snippet Types

NetDefense supports an increasing number of snippet types. The list of supported types defines what kind of configuration can be managed through NetDefense.

Firewall Configuration:

TypePurpose
RULEFirewall filter rules — defines traffic matching criteria and actions (accept, drop, reject, log). This is the most common snippet type.
ALIASNamed address or network groups — defines reusable sets of IP addresses, networks, or ports that can be referenced by rules. For example, a trusted-networks alias listing all internal subnets.

Account Configuration:

TypePurpose
USERUser account definitions — defines user accounts on the device for authentication-based policies.
GROUPUser group definitions — organizes users into groups for easier privileges targeting.

DNS Configuration (Unbound):

TypePurpose
UNBOUND_HOST_OVERRIDEDNS host override — maps a hostname to a specific IP address, effectively creating a local DNS record (e.g., intranet.corp to 10.0.1.50).
UNBOUND_DOMAIN_FORWARDDNS domain forwarding — forwards all DNS queries for a specific domain to a designated nameserver (e.g., forward internal.corp queries to 10.0.0.53).
UNBOUND_HOST_ALIASDNS host alias — creates an alternative hostname (CNAME-like) that points to an existing host override.
UNBOUND_ACLDNS access control list — controls which networks are allowed to query the Unbound DNS resolver.

Priority

Each snippet has a priority value between 1 and 60,000 (default: 1,000). Priority controls the order in which snippets appear in the final device configuration — lower numbers are placed first. This matters for firewall rules because OPNsense evaluates them top-to-bottom and stops at the first match.

For example, suppose you have a rule that blocks traffic from known bad sources (priority 100) and another that allows general LAN traffic (priority 500). Because the block rule has a lower priority number, it appears higher in the list and is evaluated first — so malicious traffic is dropped before the allow rule ever gets a chance to match it. If the priorities were reversed, the allow rule would match first and let the traffic through.

Priority only affects ordering for snippet types where order matters (rules). For types like aliases and users, the priority value is stored but has no effect on behavior.

List Snippets

Terminal window
ndcli snippet list
╭──────────────────────┬──────────┬───────┬──────────────────╮
│ Name │ Priority │ Type │ Updated │
├──────────────────────┼──────────┼───────┼──────────────────┤
│ drop-invalid-state │ 10 │ RULE │ 2026-02-20 19:18 │
│ rate-limit-icmp │ 20 │ RULE │ 2026-02-20 19:18 │
│ anti-spoofing │ 30 │ RULE │ 2026-02-20 19:18 │
│ block-bogon-ranges │ 1000 │ ALIAS │ 2026-02-20 19:18 │
│ log-and-drop-default │ 50 │ RULE │ 2026-02-20 19:18 │
│ allow-established │ 100 │ RULE │ 2026-02-20 19:18 │
│ trusted-networks │ 1000 │ ALIAS │ 2026-02-20 19:18 │
│ dns-servers │ 1000 │ ALIAS │ 2026-02-20 19:18 │
│ allow-dns-ntp │ 200 │ RULE │ 2026-02-20 19:18 │
│ allow-ldap-internal │ 210 │ RULE │ 2026-02-20 19:18 │
│ guest-internet-only │ 300 │ RULE │ 2026-02-20 19:18 │
│ block-internal-nets │ 310 │ RULE │ 2026-02-20 19:18 │
│ guest-rate-limit │ 320 │ RULE │ 2026-02-20 19:18 │
│ geoip-filter │ 500 │ RULE │ 2026-02-20 19:18 │
│ port-scan-detect │ 510 │ RULE │ 2026-02-20 19:18 │
│ geoip-blocklist │ 1000 │ ALIAS │ 2026-02-20 19:18 │
│ log-accepted-traffic │ 900 │ RULE │ 2026-02-20 19:18 │
│ log-dropped-traffic │ 910 │ RULE │ 2026-02-20 19:18 │
╰──────────────────────┴──────────┴───────┴──────────────────╯

Describe a Snippet

Terminal window
ndcli snippet describe allow-dns-ntp
╭───────────────┬──────────┬──────┬──────────────────╮
│ Name │ Priority │ Type │ Updated │
├───────────────┼──────────┼──────┼──────────────────┤
│ allow-dns-ntp │ 200 │ RULE │ 2026-02-20 19:18 │
╰───────────────┴──────────┴──────┴──────────────────╯
Content:
{
"%action": "Pass",
"%direction": "In",
"%ipprotocol": "IPv4",
"%statetype": "keep state",
"action": "pass",
"description": "Allow DNS & NTP",
"destination_net": "any",
"destination_not": "0",
"destination_port": "DNS_NTP",
(...)
"uuid": "221f3268-f2a5-49f5-bf6b-f8a6e5d23014"
}

Content Format

Snippet content is JSON that the NDAgent translates into OPNsense API calls. Each snippet type maps to a different section of the device configuration. Below are examples for the two most common types.

RULE snippet — defines a firewall filter rule with action, direction, protocol, and source/destination matching:

{
"uuid": "221f3268-0001-4abc-9000-000000000001",
"enabled": true,
"action": "pass",
"interface": "lan",
"direction": "in",
"ipprotocol": "inet",
"protocol": "TCP/UDP",
"source_net": "trusted-networks",
"destination_net": "dns-servers",
"destination_port": "53",
"description": "Allow DNS queries to internal resolvers"
}

ALIAS snippet — defines a named group of addresses, networks, or ports that rules can reference:

{
"uuid": "221f3268-0002-4abc-9000-000000000001",
"enabled": true,
"name": "trusted-networks",
"type": "network",
"content": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
"description": "RFC1918 private address ranges"
}

Notable fields:

  • source_net / destination_net — Can reference an alias by name (e.g., "trusted-networks") or use literal values ("any", "192.168.1.0/24"). When applying the configuration, the NDAgent resolves alias names against each device’s local database, making snippets portable across devices.
  • content (aliases) — Accepts an array of values or a single newline-separated string.

How NDAgent Identifies Managed Configuration

A device running OPNsense can have both locally-created configuration (rules added by hand, aliases created in the web UI) and configuration managed by NetDefense. The NDAgent needs a reliable way to tell them apart. During a sync, it only creates, updates, or deletes objects it recognizes as its own — everything else is left untouched.

Because the OPNsense API does not provide a single uniform mechanism for tagging managed objects, NDAgent uses different identification strategies depending on what each part of the API allows:

Object TypeIdentification MethodMarker
Aliases, Rules, DNS recordsUUID prefixUUID starts with 221f3268-
Users, GroupsDescription tagDescription contains [nd-template:...]
WireGuard tunnelsName prefixName starts with nd-vpn__

Portable Snippets and the PULL Workflow

Snippet content is designed to be portable — the same JSON can be applied to any device in the organization. The NDAgent handles the translation: it resolves alias references, maps interface names, and re-references UUIDs against each device’s local database.

The OPNsense API JSON format can be nuanced and is not always exhaustively documented. Building snippet content from scratch requires knowledge of the exact field names, value formats, and constraints that the API expects. Rather than guessing at the correct structure, a more reliable approach is to use the PULL workflow:

  1. Configure the desired rule or alias manually through the OPNsense web interface on any device.

  2. Use ndcli sync pull to retrieve that configuration in portable JSON format.

  3. Use the returned JSON as the content for a new snippet.