Netify Flow Actions Processor Plugin
The Flow Actions Plugin bridges the gap between Layer 7 application intelligence and Layer 3 network enforcement. By translating deep packet inspection into actionable policies, the plugin provides a unified mechanism for firewalling, QoS prioritization, and intelligent routing across the following targets:
- IP sets
- nftables sets
- Connection Tracking (CT) Labels
- Connection Tracking (CT) Marks
- PF tables (BSD)
Leveraging the Netify Flow Expressions engine, you can deploy sophisticated security and optimization policies:
- Application-based optimizations
- Security policy enforcement
- Protection against exfiltration
License
The Netify Flow Actions plugin is a proprietary plugin requiring a license. Please contact us for details.
Installation
Netify plugins are distributed through the same packaging workflow as the Netify Agent, allowing for a consistent installation experience using standard package manager syntax. While pre-compiled binaries are readily available for x86_64 architectures via our public mirrors, support for ARM, MIPS, and other specialized architectures is available upon request. Please contact us for details.
Step 1 - Select your installation target:
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
sudo curl https://download.netify.ai/5/debian/netify-archive-keyring.gpg -o /usr/share/keyrings/netify-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netify-archive-keyring.gpg] http://download.netify.ai/5/debian/12/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
sudo curl https://download.netify.ai/5/debian/netify-archive-keyring.gpg -o /usr/share/keyrings/netify-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netify-archive-keyring.gpg] http://download.netify.ai/5/debian/11/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
sudo curl https://download.netify.ai/5/debian/netify-archive-keyring.gpg -o /usr/share/keyrings/netify-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netify-archive-keyring.gpg] http://download.netify.ai/5/debian/10/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
sudo curl https://download.netify.ai/5/ubuntu/netify-archive-keyring.gpg -o /usr/share/keyrings/netify-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netify-archive-keyring.gpg] http://download.netify.ai/5/ubuntu/noble/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
sudo curl https://download.netify.ai/5/ubuntu/netify-archive-keyring.gpg -o /usr/share/keyrings/netify-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/netify-archive-keyring.gpg] http://download.netify.ai/5/ubuntu/jammy/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo apt-get update
sudo apt-get -y install curl gnupg2
curl -fsSL https://download.netify.ai/5/ubuntu/apt-gpg-key-netify.asc | sudo apt-key add -
echo 'deb http://download.netify.ai/5/ubuntu/focal/ /' | sudo tee /etc/apt/sources.list.d/netify.list
Step 3 - Install Netify Flow Actions:
sudo apt update
sudo apt install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
wget https://download.netify.ai/5/openwrt/key-build.pub -O /etc/opkg/keys/b18c240cb821dad2
echo 'src/gz netify https://download.netify.ai/5/openwrt/24.10/x86' >> /etc/opkg/customfeeds.conf
Step 3 - Install Netify Flow Actions:
opkg update
opkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
wget https://download.netify.ai/5/openwrt/key-build.pub -O /etc/opkg/keys/b18c240cb821dad2
echo 'src/gz netify https://download.netify.ai/5/openwrt/23.05/x86' >> /etc/opkg/customfeeds.conf
Step 3 - Install Netify Flow Actions:
opkg update
opkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
wget https://download.netify.ai/5/openwrt/key-build.pub -O /etc/opkg/keys/b18c240cb821dad2
echo 'src/gz netify https://download.netify.ai/5/openwrt/22.03/x86' >> /etc/opkg/customfeeds.conf
Step 3 - Install Netify Flow Actions:
opkg update
opkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
wget https://download.netify.ai/5/openwrt/key-build.pub -O /etc/opkg/keys/b18c240cb821dad2
echo 'src/gz netify https://download.netify.ai/5/openwrt/21.02/x86' >> /etc/opkg/customfeeds.conf
Step 3 - Install Netify Flow Actions:
opkg update
opkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
wget http://download.netify.ai/5/openwrt/key-build.pub -O /etc/opkg/keys/b18c240cb821dad2
echo 'src/gz netify http://download.netify.ai/5/openwrt/19.07/x86' >> /etc/opkg/customfeeds.conf
Step 3 - Install Netify Flow Actions:
opkg update
opkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import https://download.netify.ai/5/opensuse/15.6/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/opensuse/netify.repo -o /etc/zypp/repos.d/repo-netify.repo
Step 3 - Install Netify Flow Actions:
sudo zypper update
sudo zypper install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import https://download.netify.ai/5/opensuse/15.5/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/opensuse/netify.repo -o /etc/zypp/repos.d/repo-netify.repo
Step 3 - Install Netify Flow Actions:
sudo zypper update
sudo zypper install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import https://download.netify.ai/5/almalinux/9/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/almalinux/9/netify.repo -o /etc/yum.repos.d/netify.repo
Step 3 - Install Netify Flow Actions:
sudo yum update
sudo yum install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import https://download.netify.ai/5/almalinux/8/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/almalinux/8/netify.repo -o /etc/yum.repos.d/netify.repo
Step 3 - Install Netify Flow Actions:
sudo yum update
sudo yum install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import http://download.netify.ai/5/rockylinux/9/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/rockylinux/9/netify.repo -o /etc/yum.repos.d/netify.repo
Step 3 - Install Netify Flow Actions:
sudo yum update
sudo yum install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
sudo rpm --import http://download.netify.ai/5/rockylinux/8/stable/RPM-GPG-KEY-netify
sudo curl https://download.netify.ai/5/rockylinux/8/netify.repo -o /etc/yum.repos.d/netify.repo
Step 3 - Install Netify Flow Actions:
sudo yum update
sudo yum install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
mkdir -p /usr/local/etc/pkg/fingerprints/Netify/trusted
curl https://download.netify.ai/5/opnsense/fingerprint -o /usr/local/etc/pkg/fingerprints/Netify/trusted/fingerprint
cat << EOF > /usr/local/etc/pkg/repos/Netify.conf
Netify: {
fingerprints: "/usr/local/etc/pkg/fingerprints/Netify",
url: "https://download.netify.ai/5/opnsense/25.7",
signature_type: "fingerprints",
mirror_type: "http",
priority: 11,
enabled: yes
}
EOF
Step 3 - Install Netify Flow Actions:
pkg update
pkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
mkdir -p /usr/local/etc/pkg/fingerprints/Netify/trusted
curl https://download.netify.ai/5/opnsense/fingerprint -o /usr/local/etc/pkg/fingerprints/Netify/trusted/fingerprint
cat << EOF > /usr/local/etc/pkg/repos/Netify.conf
Netify: {
fingerprints: "/usr/local/etc/pkg/fingerprints/Netify",
url: "https://download.netify.ai/5/opnsense/24.7",
signature_type: "fingerprints",
mirror_type: "http",
priority: 11,
enabled: yes
}
EOF
Step 3 - Install Netify Flow Actions:
pkg update
pkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
mkdir -p /usr/local/etc/pkg/fingerprints/Netify/trusted
curl https://download.netify.ai/5/freebsd/fingerprint -o /usr/local/etc/pkg/fingerprints/Netify/trusted/fingerprint
cat << EOF > /usr/local/etc/pkg/repos/Netify.conf
Netify: {
fingerprints: "/usr/local/etc/pkg/fingerprints/Netify",
url: "https://download.netify.ai/5/freebsd/15.0",
signature_type: "fingerprints",
mirror_type: "http",
priority: 11,
enabled: yes
}
EOF
Step 3 - Install Netify Flow Actions:
pkg update
pkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
mkdir -p /usr/local/etc/pkg/fingerprints/Netify/trusted
curl https://download.netify.ai/5/freebsd/fingerprint -o /usr/local/etc/pkg/fingerprints/Netify/trusted/fingerprint
cat << EOF > /usr/local/etc/pkg/repos/Netify.conf
Netify: {
fingerprints: "/usr/local/etc/pkg/fingerprints/Netify",
url: "https://download.netify.ai/5/freebsd/14.0",
signature_type: "fingerprints",
mirror_type: "http",
priority: 11,
enabled: yes
}
EOF
Step 3 - Install Netify Flow Actions:
pkg update
pkg install netify-proc-flow-actions
Step 2 - Add Netify's package signing key and repository:
mkdir -p /usr/local/etc/pkg/fingerprints/Netify/trusted
curl https://download.netify.ai/5/freebsd/fingerprint -o /usr/local/etc/pkg/fingerprints/Netify/trusted/fingerprint
cat << EOF > /usr/local/etc/pkg/repos/Netify.conf
Netify: {
fingerprints: "/usr/local/etc/pkg/fingerprints/Netify",
url: "https://download.netify.ai/5/freebsd/14.0",
signature_type: "fingerprints",
mirror_type: "http",
priority: 11,
enabled: yes
}
EOF
Step 3 - Install Netify Flow Actions:
pkg update
pkg install netify-proc-flow-actions
Setup
To use the Netify Flow Actions plugin, ensure your license.json includes the netify-proc-flow-actions entitlement.
All plugins are disabled by default, and the Netify Flow Actions plugin is no different. Use netifyd's --enable-plugin and --disable-plugin flags to enable or disable the plugin.
netifyd --enable-plugin proc-nfa # Enables loader
netifyd --disable-plugin proc-nfa # Disables loader
For orchestration tools or manual setup, you can also directly update configuration file in the plugins.d subdirectory and set enable to yes.
See the advanced configuration section for details on instantiating multiple instances of the plugin.
$ cat 10-netify-proc-flow-actions.conf
[proc-nfa]
enable = yes
plugin_library = /usr/lib64/libnetify-proc-flow-actions.so.0.0.0
conf_filename = ${path_state_persistent}/netify-proc-flow-actions.json
Intro: Understanding Actions and Targets
The Flow Actions plugin uses a two-part model to turn network intelligence into real outcomes. By separating decision-making from execution, network policies remain organized, reusable, and easier to scale as your environment grows.
Actions: The Decision Layer (The Brain)
Actions contain the logic. They monitor traffic and determine when something should happen. An Action does not directly modify packets or connections; instead, it evaluates flows against configured rules and triggers a Target when the criteria are met. Key components of an Action include:
- Criteria
- Defines the "who" and "what", e.g., Is this a Zoom call on the Guest WiFi?
- Exemptions
- Specifies which entities should be ignored by the rule, e.g., never block the internal DNS server.
- Priority
- Determines the order in which rules are evaluated when multiple actions could apply.
Targets: The Execution Layer (The Muscle)
Targets perform the actual work. When an Action determines that a rule has been met, it invokes a Target to carry out the task. Targets are platform-aware and reusable, allowing multiple Actions to trigger the same execution mechanism.
- Reusable
- You can create one blacklist target and have ten different Actions feed into it.
- Decoupled
- Targets do not evaluate policy - they simply perform their assigned task (like updating a firewall list or writing a log).
The following action target types are supported:
| Name | Platforms | Description |
|---|---|---|
| log | All | Writes periodic, structured JSON files for forensic analysis. |
| ipset | Linux | Updates kernel-level IP sets for real-time firewalling, QoS/QoE, and routing. |
| nftset | Linux | Updates kernel-level nftable sets for real-time firewalling, QoS/QoE, and routing. |
| ctlabel | Linux | Applies persistent labels to connections for stateful tracking. |
| ctmark | Linux | Applies 32-bit integer marks to the connection state, ideal for QoS hand-offs. |
| pftable | FreeBSD | Manages native pf tables to automate security on BSD systems. |
| sink | All | Streams live telemetry and flow events to external apps, sockets, or message queues. |
Note: only a subset of these may be available, depending on licensing options and/or platform capabilities.
Examples
Technical concepts are often best understood through implementation. We recommend exploring the following examples to see the Flow Actions plugin in a real-world operational context.
| Description | State Engine | Packet Filter | Action |
|---|---|---|---|
| Block insecure connections | nft Sets | nftables | Block |
| Mark BitTorrent and category traffic | IP Sets | iptables | Kernel mark |
| Throttling/QoS with Traffic Control | IP Sets | iptables | QoS with tc |
| Set DSCP bits for Zoom traffic | Connection Tracking Label | nftables | QoS with DSCP |
Global Configuration
Properties
version
integer
Tells the plugin which JSON schema is supported.
reprocess_flows
boolean
If set to true the agent will re-evaluate all active flows on a reload. This property was added in Flow Actions 1.1.10.
timezone
string
The timezone used in the Time of Day feature. If this property is not provided, times will be relative to the system clock. A timezone string must be represented as a valid zoneinfo file (e.g. files in /usr/share/zoneinfo/). Install zoneinfo packages as required for your operating system.
exemptions
array
Global exemptions are usually employed to filter out certain hosts by address, however they can also be configured with an expression for more advanced exemption filtering.
Global Configuration Example
{
"version": 1,
"reprocess_flows": true,
"timezone": "America/Toronto",
"actions": {
...
},
"targets": {
...
},
"target_defaults": {
...
},
"exemptions": [
"192.168.1.1",
"protocol == 'dns';"
]
}
Optimizations
The reprocess_flows property is a configuration option that, if set to true , will force the agent to re-evaluate all active flows that the DPI agent is tracking against every single action criteria when the agent is reloaded or sent a SIGHUP signal. System integrators may want to enable this feature to improve the user experience. For example, adding a block rule to an already established application will be blocked immediately - not just new unique flows associated with that application. It is also a useful function during testing.
The downside in enabling this feature is that CPU usage could jump temporarily when reloading the agent, especially in cases of high traffic (e.g., more than 1000 active flows). If you are not dynamically adding rules through a UX, we recommend this setting remains in its default state of false .
Action Configuration
Actions set the criteria that will be evaluated against each flow detection. The evaluation happens after the DPI processing of the flow has been completed, and subsequently again if the flow's metadata has been updated. If the action's criteria match, the specified action targets are called.
Each action must reference at least one target. There is no limit to the number of targets an action can reference.
Properties
enabled
boolean
State of the action.
criteria
string
The criteria property is mandatory and requires a flow expression.
targets
array
An array of one or more target names to call when a flow matches the action criteria.
exemptions
array
Exemptions are optional and can be thought of as the inverse of criteria. Usually they are employed to filter out certain hosts by address, however they can also be configured with an expression for more advanced exemption filtering.
interface
string
Filter flows by interface or interface role. Specify an interface name, such as: eth0, or the interface's role, which can be either lan or wan. If an asterisk (*) is used, the flow actions will be performed across all listening interfaces.
halt_on_match
boolean
If set to true, matching on this action will cause the plugin to stop evaluating any further actions listed after this instance.
time_of_day
object
Time of day object. See next section for details.
Flow Action Example
...
"actions": {
"social": {
"enabled": true,
"criteria": "category == 'social-media';",
"targets": [
"ipset.high"
],
"exemptions": [
"app == 'netify.reddit';"
],
"interface": "*",
"halt_on_match": false
}
},
...
Time of Day
Available in Flow Actions version 1.1.27, the Time of Day feature introduces the ability to apply targets (or policies) only during specific time windows. This allows for precise control over when certain actions or rules should be enforced, enabling time-based filtering, monitoring, or enforcement logic.
Each target can now include one or more time-of-day rules that define when it is eligible to match. If the current system time falls outside the defined windows, the target will not be considered during flow evaluation. This is particularly useful for:
- Restricting bandwidth during peak hours
- Enabling policies only during working hours
- Blocking specific apps or sites during homework or bedtime hours
Setting the timezone in the global configuration may be required.
Time of Day Example: Workday Hours
"time_of_day": [
{
"day": [
"mon",
"tue",
"wed",
"thu",
"fri"
],
"time_start": "9:00",
"time_end": "17:00",
"policy": "inclusive"
}
]
Properties
time_of_day.day
array
An array of days of the week to match on. If this property is missing or null, matching will apply on every day of the week by default.
time_of_day.time_start
string
Represents when the start time of a policy begins. This value can be represented as hh:mm:ss or simply hh:mm
time_of_day.time_end
string
Represents when the end time of a policy begins. This value can be represented as hh:mm:ss or simply hh:mm
time_of_day.policy
string
Determines whether the time-of-day component matches the expression when the time is inside the time window (inclusive) or outside the time window (exclusive)
{
...
"timezone": "America/Toronto",
...
"actions": {
"example": {
"enabled": true,
"criteria": [ ... ],
"targets": [ ... ],
"priority": 100,
"halt_on_match": true
"time_of_day": [
{
"day": [
"mon",
"tue",
"wed",
"thu",
"fri"
],
"time_start": "9:00",
"time_end": "17:00",
"policy": "inclusive"
},
{
"time_start": "0:00",
"time_end": "12:00",
"policy": "exclusive"
}
],
}
},
...
}
IP Set Target Configuration
IP Sets are high-speed Linux kernel tables that are used to store lists of network addresses. More information about IP Sets can be found on the project website, or from the ipset man page.
Properties
target_type
string
Target type - always ipset for IP set targets.
target_enabled
boolean
State of the target rule.
set_name
string
The set name of your choosing.
type
string
The IP set type. IP set types are comprised of a storage method and a datatype. Valid storage methods are: bitmap, hash, and list . The currently supported list of types are: ip, ip,port, ip,port,ip, and mac.
skb_mark
string
Firewall mark as a hexadecimal string. When any of the skb_* options are set, and an appropriate firewall rule is present (a SET netfilter target with the --map- set argument), packets that match this IP set will have their corresponding socket buffer options set.
skb_mask
string
Corresponding mask to a specified skb_mark, as a hexadecimal string. If skb_mark is set, without a mask, the default value is: 0xffffffff
skb_prio
string
Traffic control tc class. The option has the format: MAJOR:MINOR.
skb_queue
integer
Hardware queue ID, integer integer.
set_family
string
The IP family of the set.
ttl
integer
The plugin will attempt to remove the matching element after not seeing matching traffic after this TTL. Elements can be set to expire after a specified number of seconds by configuring the ttl property. Generally it is recommended to always set a ttl, to a fairly high value, such as 900 (15 minutes), to ensure the list of elements doesn't grow too large. Set the ttl to 0 to disable timed expiration.
managed
boolean
When the managed mode is enabled, the plugin will attempt to create the set/table if it doesn't exist. If you change the plugin's configuration, and existing sets/tables are present, you must manually destroy them in order for any new settings to take effect.
max_elements
integer
The maximum number of elements that can be stored in the set.
flush_on_create
boolean
When the managed mode is enabled and flush_on_create is enabled, the target will be flushed (cleared), on start-up if it exists.
flush_on_destroy
boolean
When enabled, flush_on_destroy will flush (clear) all elements on shutdown. This option does not depend on managed mode being enabled.
IP Set Target Example
{
"version": 1,
...
"targets": {
"ipset.example": {
"target_type": "ipset",
"target_enabled": true,
"set_name": "nfa.example"
}
},
"target_defaults": {
"ipset": {
"type": "hash:ip,port,ip",
"ttl": 120,
"set_family": "*",
"managed": true,
"flush_on_create": false,
"flush_on_destroy": false
}
}
}
nft Set Target Configuration
Properties
target_type
string
Target type - always nftset for nft set targets.
target_enabled
boolean
State of the target rule.
set_name
string
The set name of your choosing.
table_name
string
The table name that the NFT set is a member of.
table_family
string
The family of the table.
set_family
string
The IP family of the set.
ttl
integer
The plugin will attempt to remove the matching element after not seeing matching traffic after this TTL. Elements can be set to expire after a specified number of seconds by configuring the ttl property. Generally it is recommended to always set a ttl, to a fairly high value, such as 900 (15 minutes), to ensure the list of elements doesn't grow too large. Set the ttl to 0 to disable timed expiration.
type
array
The set type is defined as an array of flow metadata fields. Rules that reference the NFT set must do so using the same field order that is defined here.
managed
boolean
When the managed mode is enabled, the plugin will attempt to create the set/table if it doesn't exist. If you change the plugin's configuration, and existing sets/tables are present, you must manually destroy them in order for any new settings to take effect.
max_elements
integer
The maximum number of elements that can be stored in the set.
flush_on_create
boolean
When the managed mode is enabled and flush_on_create is enabled, the target will be flushed (cleared), on start-up if it exists.
flush_on_destroy
boolean
When enabled, flush_on_destroy will flush (clear) all elements on shutdown. This option does not depend on managed mode being enabled.
nft Set Target Example
{
"version": 1,
...
"targets": {
"nftset.example": {
"target_type": "nftset",
"target_enabled": false,
"set_name": "nfa.example",
}
},
"target_defaults": {
"nftset": {
"table_name": "netify",
"table_family": "inet",
"set_family": "ipv4",
"size": 65535,
"ttl": 300,
"type": [
"local_addr",
"ip_proto",
"other_port",
"other_addr"
],
"managed": true,
"flush_on_destroy": true,
"flush_on_create": true
}
}
}
Connection Tracking (CT) Labels Target
The Netfilter conntrack API exposes an interface for applying user-defined labels (bitfields) to individual network flows. These flow labels can be inspected using the conntrack utility from the conntrack-tools package (for example, conntrack -L -o labels ). The Zoom traffic priority example demonstrates how conntrack labels can be implemented and used effectively.
While labels are highly efficient, it is important to note that conntrack labels are limited to a maximum of 128 bits. Each label is a bit in a 128-bit field. This bitmask approach is ideal for defining binary states across a connection, such as:
- Blocking Policies
- Flagging a flow for dropping based on security rules.
- QoS Buckets
- Categorizing traffic into specific priority queues (e.g., VoIP vs. Bulk).
- Routing Flags
- Identifying flows that require specific gateway routing.
If your use case requires a larger address space or more complex metadata—such as storing unique IDs or 32-bit integers—the Connection Tracking Marking (connmark) integration might be a better option. While labels are simple on/off bitfields, connmark allows you to store a full 32-bit value directly on the connection entry, providing more flexibility for high-cardinality data.
Auto Labels
The CT labels target can parse prefixed names from connlabels.conf and, when the auto_label feature is enabled, automatically apply them to matching flows. Label names follow a specific syntax: the prefix indicates the type—a for application or p for protocol—followed by a hyphen and the name. Any forward slashes in the application or protocol name must be replaced with hyphens. For example, WhatsApp/Call is translated to p-whatsapp-call.
Example connlabel.conf with Auto Labels
1 a-spotify
2 a-google
10 p-whatsapp-call
11 p-http-s
Target Global Properties
Global properties define tuning parameters that map directly to the underlying operating system environment.
max_bits
integer
Maximum bits used on the target operating system.
connlabel_conf
string
Path connlabel.conf on the target operating system.
CT Labels Target Globals
"target_globals": {
"ctlabel": {
"max_bits": 127,
"connlabel_conf": "/etc/xtables/connlabel.conf"
}
}
Properties
target_type
string
Target type - always ctlabel for connection tracking label targets.
target_enabled
boolean
State of the target rule.
labels
array
The labels array contains one or more label bits or label names. All labels will be applied to all flows that reach the target.
auto_label
boolean
State of the auto-label system - see above.
log_errors
boolean
By default, errors are not logged to reduce processing overhead. When the Agent is in debug mode and log_errors is enabled, error messages will be displayed for flows that could not be labeled.
CT Labels Target Example
{
"version": 1,
"actions": {...}
"targets": {
"ctlabel.example": {
"target_type": "ctlabel",
"target_enabled": true,
"labels": [
"netify-games"
]
}
},
"target_defaults": {
"ctlabel": {
"auto_label": false,
"log_errors": false
}
},
"target_globals": {
"ctlabel": {
"max_bits": 127,
"connlabel_conf": "/etc/xtables/connlabel.conf"
}
}
}
Connection Tracking (CT) Marks Target
The Netfilter Conntrack API provides an interface module for applying user-defined marks (bits) on a per-flow basis. Flow marks can be examined using the conntrack command from the conntrack-tools package. For example: conntrack -L
Properties
target_type
string
Target type - always ctmark for connection tracking mark targets.
target_enabled
boolean
State of the target rule.
mark
string
This is the value that will be set in the conntrack mark field. It is a 32-bit hexadecimal value.
mask
string
This is a bitmask that determines which bits of the CT mark should be affected. A mask of 0xffffffff (all bits set) means the entire mark is replaced. A mask like 0x000000ff would only affect the lower 8 bits.
shift
integer
This tells the system to bit-shift the mark value before applying it, which is useful when packing multiple pieces of metadata into the CT mark. A shift of 0 means the value is written as-is. A shift of 8 would mean the value is written into the second byte.
shift
integer
This tells the system to bit-shift the mark value before applying it, which is useful when packing multiple pieces of metadata into the CT mark. A shift of 0 means the value is written as-is. A shift of 8 would mean the value is written into the second byte.
CT Marks Target Example
{
"version": 1,
...
"targets": {
"ctmark.example": {
"target_type": "ctmark",
"target_enabled": true,
"mark": "0x00000001"
}
},
"target_defaults": {
"ctmark": {
"mask": "0xffffffff",
"shift": 0
}
}
}
PF Tables Target
Netify integrates natively with PF (Packet Filter) tables on FreeBSD-based platforms such as OPNsense and pfSense, enabling real-time enforcement of application intelligence directly at the firewall layer. This integration bridges deep packet inspection (DPI) and stateful packet filtering, allowing Netify to translate high-level application and traffic classifications into low-level firewall controls with minimal overhead.
Target Global Properties
Global properties define tuning parameters that map directly to the underlying operating system environment.
pftable
string
Path to the PF (Packet Filter) firewall control device. This device must exist and be accessible for PF management operations.
PF Labels Target Globals
"target_globals": {
"pftable": {
"device": "/dev/pf"
}
}
Properties
target_type
string
Target type - always pftable for PF tables targets.
target_enabled
boolean
State of the target rule.
table_name
string
Identifier of a PF table used to store and match a set of IP addresses or networks.
address_type
string
Identifier of either the local or other IP.
ttl
integer
The plugin will attempt to remove the matching element after not seeing matching traffic after this TTL. Elements can be set to expire after a specified number of seconds by configuring the ttl property. Generally it is recommended to always set a ttl, to a fairly high value, such as 900 (15 minutes), to ensure the list of elements doesn't grow too large. Set the ttl to 0 to disable timed expiration.
managed
boolean
When the managed mode is enabled, the plugin will attempt to create the set/table if it doesn't exist. If you change the plugin's configuration, and existing sets/tables are present, you must manually destroy them in order for any new settings to take effect.
PF Tables Target Example
{
"version": 1,
...
"targets": {
"pftable.example": {
"target_type": "pftable",
"target_enabled": true,
"table_name": "nfa.example"
}
},
"target_defaults": {
"pftable": {
"anchor_name": "*",
"address_type": "other",
"ttl": 60,
"managed": true
}
},
"target_globals": {
"pftable": {
"device": "/dev/pf"
}
}
}
Log Target
The Log target is useful for development and testing. If you need to provide telemetry when a flow action event occurs, use the Sink Plugin to configure a log, socket, message queue, etc.
Properties
target_type
string
Target type - always log for log targets.
target_enabled
boolean
State of the target rule.
prefix
string
The log filename prefix.
path
string
The full path of the desired log directory.
suffix
string
The log filename suffix and/or extension.
interval
integer
The interval of time, in seconds, between log writes. A new file is created for each interval only if new flow data is collected (empty log files will not be created).
Log Target Example
{
"version": 1,
...
"targets": {
"log.example": {
"target_type": "log",
"target_enabled": true,
"prefix": "netify-flow-action-example"
}
},
"target_defaults": {
"log": {
"path": "/tmp",
"suffix": ".json",
"interval": 300
}
}
}
Sink Target and Telemetry
When a flow action event occurs, the Sink target provides a way to send the telemetry to a log, socket, message queue, etc. When an action event occurs, the flow_action is attached to the flow record - you can find format of this record on the Flow Action Telemetry page. This sink configuration is highly flexible, but it can also be easy to misconfigure if the relationships between components are not clear. A guide is provided further below.
Properties
target_type
string
Target type - always sink for sink targets.
target_enabled
boolean
State of the target rule.
sink
string
The name of the sink target.
channel
string
The name of the sink channel.
compressor
string
The compression policy.
flow_events
flags
Flow event flags for matching.
header
boolean
Flag to indicate if length header is included in JSON output.
Sink Target Example
{
"version": 1,
...
"targets": {
"sink.example": {
"target_type": "sink",
"target_enabled": true
}
},
"target_defaults": {
"sink": {
"sink": "sink-socket",
"channel": "flow-actions",
"format": "json",
"compressor": "none",
"flow_events": "new | updated | expired",
"header": true
}
}
}
Sink and Channel Configuration
The sink property determines which sink (output) receives the telemetry data. This property must match the section name defined by the corresponding plugin loader. In our example, the sink is set to sink-log , which must exactly match the loader section name sink-log as shown below:
$ cat /etc/netifyd/plugins.d/10-netify-sink-log.conf
[sink-log]
enable = yes
plugin_library = /usr/lib64/libnetify-sink-log.so.0.0.0
conf_filename = ${path_state_persistent}/netify-sink-log.json
Here we can see that the section name [sink-log] matches the sink value used in the configuration. The presence of this configuration file indicates that the plugin has been installed, and the enable = yes setting confirms that it is currently enabled. The loader configuration also specifies the runtime configuration file through the conf_filename property.
This mapping is critical: if the names do not match, the processor will not be able to deliver data to the sink.
The other property in our Flow Actions target configuration is the channel . Sink output channels provide a way to separate different types of telemetry into different output targets. For example, you can send:
- flow actions data to /tmp/netify-flow-actions-x
- interface statistics to /tmp/netify-interface-stats-x
- intelligence detections to /tmp/netify-intelligence-x
This channel must be configured in the target sink configuration as shown: flow-actions . Refer to the relevant Sink Plugin configuration for channel configuration details.
Sink Log Config: /etc/netifyd/netify-sink-log.json
{
"overwrite": false,
"log_path": "/tmp",
"channels": {
"flow-actions": {
"overwrite": true,
"log_path": "/tmp",
"log_name": "netify-flow-actions-"
}
}
}
UCI Configuration
UCI on OpenWrt support was introduced in Netify Flow Actions plugin 1.1.16 and is only available on Netify 5.2 and above. The plugin will pull configuration from both the standard JSON configuration file and your UCI configuration in /etc/config/netify-proc-flow-actions i. We recommend either one or the other.
A sample UCI compliant configuration file is shown below.
config target 'log_games'
option target_type 'log'
option target_enabled '0'
option prefix 'netify-games'
option interval '60'
config target 'log_external'
option target_type 'log'
option target_enabled '0'
option prefix 'netify-external'
option interval '60'
config target 'sink_games'
option target_type 'sink'
option target_enabled '0'
option sink 'sink-socket'
option channel 'default'
option flow_events 'new | updated | expired'
option format 'json'
option compressor 'none'
option header '1'
config target 'ipset_games'
option target_type 'ipset'
option target_enabled '0'
option set_name 'nfa.games'
option set_family 'ipv4'
option type 'hash:ip,port,ip'
option ttl '60'
option flush_on_destroy '1'
config target 'ipset_games'
option target_type 'ipset'
option target_enabled '0'
option set_name 'nfa.games'
option set_family 'ipv4'
option type 'hash:ip,port,ip'
option ttl '60'
option flush_on_destroy '1'
config target 'ctlabel_auto'
option target_type 'ctlabel'
option target_enabled '0'
option auto_label '1'
config target 'ctlabel_games'
option target_type 'ctlabel'
option target_enabled '0'
option auto_label '0'
list label 'netify-games'
config target 'nftset_games'
option target_type 'nftset'
option target_enabled '0'
option set_name 'nfa.games'
option set_family 'ipv4'
list type 'local_addr'
list type 'ip_proto'
list type 'other_port'
list type 'other_addr'
option ttl '60'
option flush_on_create '1'
config target_default 'log'
option path '/tmp'
option prefix 'netify-flow-actions'
option suffix '.json'
option interval '300'
config target_default 'ipset'
option set_family '*'
option ttl '600'
config target_default 'nftset'
option table_name 'netify'
option table_family 'inet'
option size '65535'
option ttl '300'
option managed '1'
option flush_on_destroy '1'
config target_default 'sink'
option flow_events 'new'
option format 'json'
option compressor 'none'
config action 'games'
option enabled '0'
option priority '100'
option interface '*'
list criteria "category == 'games';"
list criteria '${path_state_persistent}/nfa-games.d'
list target 'log_games'
list target 'ipset_games'
list target 'ctlabel_games'
list target 'nftset_games'
list exemption 'playstation'
list halt_on_match '1'
config action 'external'
option enabled '0'
option priority '200'
option interface '*'
list criteria '${path_state_persistent}/nfa-external.conf'
list target 'log_external'
config action 'auto_label'
option enabled '0'
option interface 'lan'
option criteria '*'
list target 'ctlabel_auto'
config exemption 'playstation'
list exemption "app == 'netify.playstation';"
config exemption 'global'
list exemption '192.168.1.1'
list exemption "protocol == 'dns';"
list exemption "app == 'netify.google';"