Network Rules
Network rules let Santa allow, deny, or audit network activity on macOS hosts. A rule has one of two kinds:
- Connection rules match flows by the local process, the remote peer, and the transport (ports, protocols, direction).
- DNS rules match DNS lookups by name, before the name resolves. A DNS rule that denies a name answers the lookup on the host, so the process never gets an address. This is often called DNS sinkholing. See DNS rules.
Either kind applies an action when something matches.
Network rules require Santa's network extension, which is gated behind the network extension tenant feature. The Network rules tab and the CreateNetworkFlowRule API are unavailable until it is enabled.
DNS rules need Santa 2026.9 or later. A host with an older Santa does not enforce them.
Overview
Each rule is scoped to a tag and identified by a name that is unique within that tag. A connection rule describes:
- Who: the local process initiating or receiving the flow
- Where: the remote peer (hostname, domain, or IP/CIDR)
- How: the transport, made of port ranges, IANA protocol numbers, and direction
- What to do: the action to take when a flow matches
Flows that match no rule fall back to the host's effective default action. A DNS rule describes only names and an action.
Actions
| Action | Connection rule | DNS rule |
|---|---|---|
| Allow | Allow matching flows. | Forward the lookup to the resolver. |
| Deny | Deny matching flows and notify the user. | Answer the lookup on the host and notify the user. |
| Silent Deny | Deny matching flows without notifying the user. | Answer the lookup on the host without notifying the user. |
| Audit | Allow matching flows, but log them for auditing. | Forward the lookup and log it. |
Direction
| Direction | Matches |
|---|---|
| Any | Both incoming and outgoing flows (the default). |
| Outgoing | Flows initiated by the host. |
| Incoming | Flows initiated by a remote peer. |
A direction-specific rule matches only that direction. In particular it does not match a flow whose direction is unknown. DNS rules have no direction.
Matchers
A connection rule must specify at least one process or remote matcher. Ports, protocols, and direction alone would match every flow. An intentional match-everything policy belongs in the default action, not in a rule.
Within a single field, multiple values are OR'd (any value matches). Across fields, conditions are AND'd (every populated field must match).
Process matchers
Identify the local process by code signing identity.
- CDHash: the code directory hash of a specific binary.
- Signing ID: the signing identifier, prefixed with the Team ID (
ABCDE12345:com.example.app), orplatform:for platform binaries. - Team ID: the Apple Developer Team ID (
ABCDE12345).
Remote matchers
Identify the remote peer:
- Hostname: an exact hostname (
api.example.com). - Domain: a domain that matches itself and its subdomains (
example.comalso matchesapi.example.com). - Address: an IP address or CIDR prefix (
10.0.0.1,10.0.0.0/8,2001:db8::/32).
Hostnames and domains do not accept wildcards or regular expressions. Use a domain to match all subdomains.
Transport matchers
- Ports: single ports (
443) or inclusive ranges (8000-8080), each between 1 and 65535. Empty matches any port. - Protocols: IANA protocol numbers 0–255 (6 = TCP, 17 = UDP, 1 = ICMP, 58 = ICMPv6). Empty matches any protocol.
Default action
network_flow_default_action is a per-tag network extension setting that decides flows no rule matches. It is the right place for a broad default-allow or default-deny posture. Individual rules then carve out the exceptions.
When a host carries several tags that each set a default action, the highest-priority tag's setting wins (see Tags).
The default action applies to connections only. A DNS lookup that matches no DNS rule always goes to the resolver (see Unmatched lookups).
Precedence
Two independent precedence systems apply, in order. First Workshop decides which rule to send to a host when the same rule name exists across several of the host's tags (tag precedence). Then, on the host, Santa's network extension (santanetd) decides which of the rules that match a given flow wins (on-host evaluation precedence).
Tag precedence
Rule names are unique per tag, but a host usually carries several tags, and the same name may be defined on more than one of them. Santa keys network rules by name (a stable slot), so Workshop resolves each name to a single winner before syncing it to the host.
A host's tags are ordered by the admin-configured tag order, highest priority first (see Tags). For a given name, the rule on the highest-priority tag wins and is the one sent to the host.
On-host evaluation precedence
For a single flow, santanetd collects every rule whose conditions all hold. It then picks the strongest by comparing this tuple field by field. Earlier fields dominate, and a tie moves on to the next field.
- Priority / rank: a rule marked
priorityoutranks every ranked rule. Otherwise the higherrankwins. An unranked rule is rank 0.priorityandrankare mutually exclusive. - Process specificity: of the matched process key, CDHash > Signing ID > Team ID > any-process. A rule is ranked by the key it actually matched through, not its most specific declared key.
- Remote tier: exact IP > CIDR > hostname > domain > any-remote.
- Within-tier specificity: a longer CIDR prefix or deeper domain label depth wins (the more specific match).
- Port narrowness: the narrowest matching port range wins.
- Protocol-specific: a rule that names protocols beats one that does not.
- Direction-specific: a rule that names a direction beats one that does not.
- Action class: deny > silent-deny > allow > audit.
- Rule ID: the final tiebreak. The higher (newer) rule ID wins.
The winning rule's action becomes the flow's verdict. Telemetry records the other matched rules as competing rule IDs, which answers "why didn't my rule win?", but they do not affect enforcement. If no rule matches, the default action decides.
DNS rules
A DNS rule acts on the question a process sends to its resolver, before any connection exists. santanetd checks each question against the host's DNS rules. Deny and Silent Deny answer the question on the host with a negative reply. Allow and Audit forward it to the resolver.
To create one, choose DNS lookups under What's the goal? in the rule form. The form then offers Block lookups, Allow lookups, and Watch without blocking. You can't change the kind of a saved rule. To switch kinds, create a new rule with a different name.
Names
A DNS rule matches question names only:
- Hostname: an exact name (
tracker.example.com). - Domain: the name and every name under it, at label boundaries.
example.commatchesexample.comandads.example.com, but notbadexample.com.
Add at least one name. Matching ignores case and a trailing dot. A rule matches every question type, including A, AAAA, and HTTPS.
DNS rules can't set processes, IP addresses, ports, or protocols, so each one applies to every process on the host. They ignore direction.
Reply
A Deny or Silent Deny rule answers with the reply you pick under Respond with:
| Reply | What the process learns |
|---|---|
| NXDOMAIN (default) | The name does not exist. |
| NODATA | The name exists but has no records of the requested type. |
With Deny, Santa also notifies the user that the lookup was blocked. Allow and Audit rules send no reply of their own.
Unmatched lookups
DNS has no default action. A question that does not match any DNS rule goes to the resolver, and network_flow_default_action does not apply to it. A DNS Allow rule is useful only as an exception to a broader DNS deny.
For example, to deny the domain example.com and allow the hostname api.example.com, add a rule for each. The exact hostname takes priority over the domain, so api.example.com still resolves and every other name under example.com gets the deny reply.
DNS rule precedence
DNS rules and connection rules never compete. A question is checked against DNS rules only, and a flow against connection rules only. Tag precedence works the same for both kinds.
Among DNS rules, santanetd uses the on-host evaluation order. A DNS rule has no process, port, protocol, or direction to compare, so the order comes down to:
- Priority, then rank.
- Exact hostname over domain.
- The deeper domain (
ads.example.comoverexample.com). - Action class: deny > silent-deny > allow > audit.
- Rule ID: the higher (newer) ID wins.
Names hosts need to reach Workshop
A deny rule can't block the names a host uses to reach Workshop. Workshop rejects a Deny or Silent Deny rule, of either kind, that matches any of these:
- Your Workshop host and its
mtls.sibling - The push server host
- Any name under
workshop.cloudornorth-pole.tech
A domain that covers one of these names is rejected too. For example, cloud covers workshop.cloud.
Santa enforces the same protection on the host. It forwards lookups for its sync server and the North Pole Security management domains before it checks any rule, and Santa's own lookups always go through.
What DNS rules don't see
These never reach santanetd as a DNS question:
- Encrypted DNS (DNS over HTTPS or DNS over TLS), such as a browser's secure DNS setting
- Questions asked by a process that bypasses the system resolver
- Names answered from
/etc/hosts - Connections to an IP address, which need no lookup
To keep a destination unreachable in any of these cases, add a connection rule for it too.
Events and telemetry
A lookup that a Deny, Silent Deny, or Audit rule wins appears on the Network events tab. Allowed lookups and lookups that match no rule are not reported.
In the events table, a DNS event's Remote Host is the question name with a badge for the question type, such as DNS A or DNS AAAA. Remote Address is the resolver. Filter by Kind to see only DNS events or only connections.
Events show rule decisions only. To record every lookup, enable DNSActivity in the host's Telemetry key and query the dns_activity table (see SQL examples).
API
A DNS rule uses the same CreateNetworkFlowRule API with these fields:
| Field | Value |
|---|---|
kind | NETWORK_FLOW_RULE_KIND_DNS. A rule with no kind is a connection rule. |
remote_hostnames | Exact names. |
remote_domains | Domains. |
dns_response | NETWORK_FLOW_RULE_DNS_RESPONSE_NXDOMAIN or NETWORK_FLOW_RULE_DNS_RESPONSE_NODATA. Deny and Silent Deny only. Unset means NXDOMAIN. |
The API rejects a DNS rule that sets process_cd_hashes, process_signing_ids, process_team_ids, remote_addresses, ports, or protocols. It accepts direction but ignores it, because Workshop sends every DNS rule to hosts with direction Any.
Best practices
- Start with Audit. Use the Audit action (or a default-allow posture) to see which flows or lookups your rules would match before you enforce a denial.
- Match on signing identity. For connection rules, prefer CDHash, Signing ID, or Team ID over broad remote ranges. Process identity is the strongest signal.
- Be specific. More specific matchers (exact IP, longer CIDR, named ports) win under on-host precedence, so narrow rules reliably override broad ones.
- Use tags deliberately. Put broad defaults on low-priority tags and exceptions on higher-priority tags.
- Pair DNS and connection rules. A DNS deny stops a name from resolving. It does not stop a connection to the address or a lookup over encrypted DNS.