net.ipfw
Note
This document describes net.ipfw module usage.
Synopsis
The net.ipfw module manages firewall rules through a common expression
language. Write one rule once, and it translates to anything the host
runs — pf on BSD/macOS, ipfw on FreeBSD, nftables on modern Linux,
iptables on legacy Linux.
Rules are expressed as JSON objects. The module auto-detects the active
firewall backend or accepts an explicit --backend override. A
native escape hatch allows raw backend-specific rules when the common
language is not expressive enough.
Usage
The following options are available:
checkList current rules for the detected backend.
presentEnsure a rule exists. Adds the rule if it is not already present. Idempotent: rules are matched by content, not by position.
absentRemove a rule matching the expression. Searches the current ruleset and removes the first match. Idempotent: returns success if no match exists.
flushRemove all rules for the detected backend. Destructive, irreversible.
dry-runPrint the translated rule without executing it. Works without root privileges and without a live firewall backend.
The following keyword arguments are available:
action(type: string)
allowordeny. Required forpresentandabsent.protocol(type: string)
tcp,udp,icmp, orany. Default:tcp.port(type: string)Single port number, e.g.
80.port-range(type: string)Port range, e.g.
8000-8080. Mutually exclusive withport.source(type: string)Source IP or CIDR. Default:
any.destination(type: string)Destination IP or CIDR. Default:
any.interface(type: string)Network interface, e.g.
eth0,em0.direction(type: string)
inorout. Default:in.stateful(type: bool)Enable connection state tracking. Default:
false.log(type: bool)Log matching packets. Default:
false.backend(type: string)Force a specific backend. One of
pf,ipfw,nftables,iptables. Auto-detected if omitted.comment(type: string)Human-readable rule description. Informational only.
native(type: object)Raw backend rules keyed by backend name. When present, takes precedence over the common expression fields.
Examples
Allow HTTP on port 80 (any OS):
actions:
allow-http:
module: net.ipfw
bind:
- web-servers
state:
$:
opts:
- present
args:
action: allow
port: "80"
stateful: true
Block outbound SMTP:
actions:
block-smtp-out:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- present
args:
action: deny
protocol: tcp
port: "25"
direction: out
Allow SSH from a management subnet with logging:
actions:
allow-ssh-mgmt:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- present
args:
action: allow
port: "22"
source: 10.0.0.0/8
stateful: true
log: true
comment: "SSH from management VLAN"
Block ICMP (ping):
actions:
block-ping:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- present
args:
action: deny
protocol: icmp
Native pf anti-spoofing rules:
actions:
pf-antispoof:
module: net.ipfw
bind:
- freebsd-servers
state:
$:
opts:
- present
args:
native:
pf: |
scrub in all
antispoof quick for egress
Remove a rule:
actions:
remove-http:
module: net.ipfw
bind:
- web-servers
state:
$:
opts:
- absent
args:
action: allow
port: "80"
Inspect current rules:
actions:
audit-firewall:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- check
args: {}
Dry-run to preview a rule without applying it:
actions:
preview-rule:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- present
- dry-run
args:
action: deny
port-range: "8000-8080"
Flush all rules (use with extreme caution):
actions:
reset-firewall:
module: net.ipfw
bind:
- all-servers
state:
$:
opts:
- flush
args: {}
Returning Data
checkReturns the current ruleset:
{ "retcode": 0, "message": "pf rules listed", "data": { "rules": [ "pass in quick proto tcp from any to any port 80", "block in quick proto icmp from any to any" ] } }
presentReturns the added rule:
{ "retcode": 0, "message": "Firewall rule added (pf)", "data": { "rule": "pass in quick proto tcp from any to any port 80", "backend": "pf" } }
absentReturns confirmation of removal:
{ "retcode": 0, "message": "pf rule removed" }
If no matching rule is found:
{ "retcode": 1, "message": "No matching pf rule found" }
flushReturns confirmation:
{ "retcode": 0, "message": "All pf rules flushed" }
dry-runPreviews the translated rule without executing:
{ "retcode": 0, "message": "[dry-run] would add rule (pf): pass in quick proto tcp from any to any port 80" }
Supported Backends
Backend |
Platforms |
|---|---|
pf |
FreeBSD, OpenBSD, NetBSD, macOS |
ipfw |
FreeBSD |
nftables |
Linux (nftables, successor to iptables) |
iptables |
Legacy Linux |
The module probes backends in the order listed above. The first one
that responds successfully is selected. Override with the --backend
argument.
Note
present and absent require root privileges on all platforms.
dry-run works without root and without a live firewall backend.