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

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:

Terminal - Netify
×
curl -fsSL https://download.netify.ai/5/debian/apt-gpg-key-netify.asc | sudo apt-key add -
echo 'deb http://download.netify.ai/5/debian/12/ /' | sudo tee /etc/apt/sources.list.d/netify.list > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
curl -fsSL https://download.netify.ai/5/debian/apt-gpg-key-netify.asc | sudo apt-key add -
echo 'deb http://download.netify.ai/5/debian/11/ /' | sudo tee /etc/apt/sources.list.d/netify.list > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
curl -fsSL https://download.netify.ai/5/debian/apt-gpg-key-netify.asc | sudo apt-key add -
echo 'deb http://download.netify.ai/5/debian/10/ /' | sudo tee /etc/apt/sources.list.d/netify.list > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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/noble/ /' | sudo tee /etc/apt/sources.list.d/netify.list > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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/jammy/ /' | sudo tee /etc/apt/sources.list.d/netify.list > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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 > /dev/null

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
opkg update
opkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
opkg update
opkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
opkg update
opkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
opkg update
opkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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/19.07/x86' >> /etc/opkg/customfeeds.conf

Step 3 - Install Netify Flow Actions:

Terminal - Netify
×
opkg update
opkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
sudo zypper update
sudo zypper install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
sudo apt update
sudo apt install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
sudo yum update
sudo yum install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
sudo yum update
sudo yum install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
pkg update
pkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
pkg update
pkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
pkg update
pkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
pkg update
pkg install netify-proc-flow-actions

Step 2 - Add Netify's package signing key and repository:

Terminal - Netify
×
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:

Terminal - Netify
×
pkg update
pkg install netify-proc-flow-actions

Setup

All plugins are disabled by default, and the Netify Flow Actions plugin is no different. Use the --enable-plugin and --disable-plugin parameters to enable/disable the plugin:

Terminal - Netify
×
netifyd --enable-plugin proc-nfa
netifyd --disable-plugin proc-nfa

Alternatively, you can edit /etc/netifyd/plugins.d/10-netify-proc-flow-actions.conf and set enable to yes.

Terminal - Netify
×
[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
log All
ipset Linux
nftset Linux
ctlabel Linux
ctmark Linux
pftable FreeBSD
sink All

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
Block insecure connections nft Sets
Mark BitTorrent and category traffic IP Sets
Throttling/QoS with Traffic Control IP Sets
Set DSCP bits for Zoom traffic Connection Tracking Label

Global Configuration

Properties

version

integer

Tells the plugin which JSON schema is supported.

reprocess_flows

integer

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.

Default
true

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

string

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.

Default
*

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.

Default
false

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.

Options
mon, tue, wed, thu, fri, sat, sun

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)

Options
inclusive, 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.

Default
hash:ip

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.

Default
*
Options
ipv4, ipv6, *

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.

Default
60

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.

Default
false

max_elements

integer

The maximum number of elements that can be stored in the set.

Default
65536

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.

Default
false

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.

Default
false

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.

Default
nfa

table_family

string

The family of the table.

Default
inet

set_family

string

The IP family of the set.

Default
*
Options
ipv4, ipv6, *

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.

Default
60

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. The supported fields are:

  • local_mac
  • other_mac
  • local_addr
  • other_addr
  • local_port
  • other_port
  • mark
  • interface

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.

Default
false

max_elements

integer

The maximum number of elements that can be stored in the set.

Default
65536

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.

Default
false

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.

Default
false

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 provides an interface module for applying user-defined labels (bits) on a per-flow basis. Flow labels can be examined using the conntrack command from the conntrack-tools package. For example: conntrack -L -o labels

Target Global Properties

max_bits

integer

Maximum bits used on the target operating system.

connlabel_conf

string

Path for the connlabel.conf file.

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

array

The target can parse prefixed label names from connlabels.conf which, when enabled, will automatically apply them to matching flows.The syntax for the label names is:- The prefix can be either a for application, or p for protocol. A hyphen delimits the from the name. The application and protocol names must have all forward-slashes replaced by hyphens. An example translation: Google/Meet/Duo -> a-google-meet-duo

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,
  ...
  "targets": {
    "ctlabel.example": {
      "target_type": "ctlabel",
      "target_enabled": true,
      "labels": [
        "netify-games"
      ]
    }
  },
  "target_defauts": {
    "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 ctlabel for connection tracking label 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. In this case, the mark being applied is 0x2.

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 0x00000002 is written as-is. A shift of 8 would mean the value is written into the second byte (i.e., becomes 0x00000200 before being OR’d with existing mark, if mask allows).

CT Marks Target Example

{
  "version": 1,
  ...
  "targets": {
    "ctmark.example": {
      "target_type": "ctmark",
      "target_enabled": true,
      "mark": "0x00000001"
    }
  },
  "target_defauts": {
    "ctmark": {
      "mask": "0xffffffff",
      "shift": 0
    }
  },
  "target_globals": {
    "ctlabel": {
      "max_bits": 127,
      "connlabel_conf": "/etc/xtables/connlabel.conf"
    }
  }
}

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

pftable

string

Path to the PF (Packet Filter) firewall control device. This device must exist and be accessible for PF management operations.

Default
/dev/pf

CT 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.

Default
other

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.

Default
60

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.

Default
false

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.

Default
/tmp

suffix

string

The log filename suffix and/or extension.

Default
.json

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).

Default
60

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.

format

string

The data format.

Options
json, msgpack

compressor

string

The compression policy.

Options
none, gz

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:

Terminal - Netify
×
$ 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';"