From 121433c2a856f6baa1274ff70583716a3c5d2b16 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Tue, 25 Nov 2025 09:59:22 +0100 Subject: [PATCH 01/12] nfqueue support --- packages/netifyd/Makefile | 2 + .../etc/netifyd/interfaces.d/10-nfqueue.conf | 16 ++++ .../99-netify-enable-nfqueue.uci-default | 11 +++ .../share/nftables.d/table-pre/10-netifyd.nft | 18 ++++- packages/ns-api/Makefile | 1 - .../files/post-commit/configure-netifyd.py | 76 ------------------- 6 files changed, 46 insertions(+), 78 deletions(-) create mode 100644 packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf create mode 100644 packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default delete mode 100644 packages/ns-api/files/post-commit/configure-netifyd.py diff --git a/packages/netifyd/Makefile b/packages/netifyd/Makefile index 18f8bed0b..6782da9a5 100644 --- a/packages/netifyd/Makefile +++ b/packages/netifyd/Makefile @@ -157,6 +157,7 @@ define Package/netifyd/install $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_DIR) $(1)/etc/netifyd $(INSTALL_DIR) $(1)/etc/netifyd/categories.d + $(INSTALL_DIR) $(1)/etc/netifyd/interfaces.d $(INSTALL_DIR) $(1)/etc/netifyd/plugins.d $(INSTALL_DIR) $(1)/etc/netifyd/profiles.d $(INSTALL_DIR) $(1)/etc/uci-defaults @@ -172,6 +173,7 @@ define Package/netifyd/install $(INSTALL_DATA) ./files/etc/config/netifyd $(1)/etc/config/netifyd $(INSTALL_BIN) ./files/etc/init.d/netifyd $(1)/etc/init.d/netifyd $(INSTALL_DATA) ./files/etc/netifyd.conf $(1)/etc/netifyd.conf + $(INSTALL_DATA) ./files/etc/netifyd/interfaces.d/10-nfqueue.conf $(1)/etc/netifyd/interfaces.d/10-nfqueue.conf $(INSTALL_DATA) ./files/etc/netifyd/netify-apps.conf $(1)/etc/netifyd/netify-apps.conf $(INSTALL_DATA) ./files/etc/netifyd/netify-categories.json $(1)/etc/netifyd/netify-categories.json $(INSTALL_DATA) ./files/etc/netifyd/profiles.d/00-default.conf $(1)/etc/netifyd/profiles.d/00-default.conf diff --git a/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf b/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf new file mode 100644 index 000000000..747969dfb --- /dev/null +++ b/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf @@ -0,0 +1,16 @@ +# Netify Agent Example Capture Interface Configuration +# Copyright (C) 2024-2025 eGloo Incorporated +# +############################################################################## + +# Example Netfilter QUEUE capture source +############################################################################## + +[capture-interface-LAN] +capture_type = nfqueue +role = lan +queue_id = 10 +queue_instances = 20 +conntrack_counters = true + +# vim: set ft=dosini : diff --git a/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default b/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default new file mode 100644 index 000000000..7a983425c --- /dev/null +++ b/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default @@ -0,0 +1,11 @@ +#!/bin/sh + +# +# Copyright (C) 2025 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-2.0-only +# + +# Removing the interfaces from netifyd configuration, ignore exit codes +uci -q del netifyd.@netifyd[0].external_if +uci -q del netifyd.@netifyd[0].internal_if +exit 0 diff --git a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft index d2283646e..9971b2ac9 100644 --- a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft +++ b/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft @@ -7,4 +7,20 @@ set nfa.blocks.v4 { chain netify_block_chain { type filter hook forward priority -10; policy accept; ip saddr . ip protocol . th dport . ip daddr @nfa.blocks.v4 counter drop -} \ No newline at end of file +} + +chain netifyd_queue_input { + type filter hook input priority filter + 1; policy accept; + iifname != $wan_devices queue num 10-29 bypass +} + +chain netifyd_queue_output { + type filter hook output priority filter + 1; policy accept; + oifname != $wan_devices queue num 10-29 bypass +} + +chain netifyd_queue_forward { + type filter hook forward priority filter + 1; policy accept; + iifname != $wan_devices queue num 10-29 bypass + oifname != $wan_devices queue num 10-29 bypass +} diff --git a/packages/ns-api/Makefile b/packages/ns-api/Makefile index 472887c19..409ad5cb7 100644 --- a/packages/ns-api/Makefile +++ b/packages/ns-api/Makefile @@ -177,7 +177,6 @@ define Package/ns-api/install $(INSTALL_BIN) ./files/post-commit/restart-netdata.py $(1)/usr/libexec/ns-api/post-commit/ $(INSTALL_BIN) ./files/pre-commit/fix-redirect-reflections.py $(1)/usr/libexec/ns-api/pre-commit $(INSTALL_BIN) ./files/pre-commit/update-objects.py $(1)/usr/libexec/ns-api/pre-commit - $(INSTALL_BIN) ./files/post-commit/configure-netifyd.py $(1)/usr/libexec/ns-api/post-commit $(INSTALL_BIN) ./files/post-commit/reload-ipsets.py $(1)/usr/libexec/ns-api/post-commit $(INSTALL_BIN) ./files/post-commit/restart-cron.py $(1)/usr/libexec/ns-api/post-commit $(INSTALL_BIN) ./files/post-commit/restart-wireguard.py $(1)/usr/libexec/ns-api/post-commit diff --git a/packages/ns-api/files/post-commit/configure-netifyd.py b/packages/ns-api/files/post-commit/configure-netifyd.py deleted file mode 100644 index 2129f8709..000000000 --- a/packages/ns-api/files/post-commit/configure-netifyd.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/python - -# -# Copyright (C) 2024 Nethesis S.r.l. -# SPDX-License-Identifier: GPL-2.0-only -# - -# This script configures netifyd: -# - add new interfaces to internal_if and external_if options -# - disable rules for interfaces that are not in the internal_if and external_if options -# - reload netifyd service - -import subprocess -from fnmatch import fnmatch -from euci import EUci -from nethsec import utils, firewall - -commit = False -# The changes variable is already within the scope from the caller -if 'network' in changes: - uci = EUci() - config = uci.get_all("netifyd") - cname = list(config.keys())[0] - if config[cname].get('autoconfig', '1') == "1": - uci.set("netifyd", cname, "autoconfig", "0") - commit = True - - # Fetch excluded interfaces (one-liner) - excluded_interfaces = set(uci.get_all("netifyd").get(cname, {}).get("ns_exclude", [])) - - # Collect interfaces - internal_if = set() - external_if = set() - zones = firewall.list_zones(uci) - for z in zones: - zone = zones[z] - devices = utils.get_all_devices_by_zone(uci, zone['name'], exclude_aliases=True) - # Filter interfaces based on exclusion patterns - filtered_devices = set() - if not devices: - continue - for iface in devices: - skip = False - for pattern in excluded_interfaces: - if fnmatch(iface, pattern): # Use fnmatch here - skip = True - break - if skip: - continue - filtered_devices.add(iface.split('.')[0]) # Strip VLAN part for base interface - filtered_devices = sorted(filtered_devices) # Return sorted list - - # Assign devices to internal or external interfaces - if zone['name'] == "wan": - external_if.update(filtered_devices) - else: - internal_if.update(filtered_devices) - - if tuple(internal_if) != uci.get("netifyd", cname, "internal_if", default=()): - uci.set("netifyd", cname, "internal_if", list(internal_if)) - commit = True - - if tuple(external_if) != uci.get("netifyd", cname, "external_if", default=()): - uci.set("netifyd", cname, "external_if", list(external_if)) - commit = True - - rules = utils.get_all_by_type(uci, 'dpi', 'rule') - for r in rules: - rule = rules[r] - if rule['device'] not in internal_if and rule['device'] not in external_if: - uci.delete("dpi", r) - commit = True -if commit: - uci.commit("netifyd") - uci.commit("dpi") - subprocess.run(["/etc/init.d/netifyd", "restart"]) From beef1d4cf294c05edec553d0089e9aff591fa550 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Mon, 1 Dec 2025 15:25:51 +0100 Subject: [PATCH 02/12] fix: using only lan traffic for queueing --- .../share/nftables.d/table-post/10-netifyd.nft | 14 ++++++++++++++ .../share/nftables.d/table-pre/10-netifyd.nft | 16 ---------------- 2 files changed, 14 insertions(+), 16 deletions(-) create mode 100644 packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft diff --git a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft new file mode 100644 index 000000000..bd7184afc --- /dev/null +++ b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft @@ -0,0 +1,14 @@ +chain netifyd_queue_input { + type filter hook input priority filter + 5; policy accept; + iifname != $wan_devices queue flags bypass to 10-29 +} + +chain netifyd_queue_forward { + type filter hook forward priority filter + 5; policy accept; + iifname != $wan_devices queue flags bypass to 10-29 +} + +chain netifyd_queue_output { + type filter hook output priority filter + 5; policy accept; + oifname != $wan_devices queue flags bypass to 10-29 +} diff --git a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft index 9971b2ac9..ad3e2d1d6 100644 --- a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft +++ b/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft @@ -8,19 +8,3 @@ chain netify_block_chain { type filter hook forward priority -10; policy accept; ip saddr . ip protocol . th dport . ip daddr @nfa.blocks.v4 counter drop } - -chain netifyd_queue_input { - type filter hook input priority filter + 1; policy accept; - iifname != $wan_devices queue num 10-29 bypass -} - -chain netifyd_queue_output { - type filter hook output priority filter + 1; policy accept; - oifname != $wan_devices queue num 10-29 bypass -} - -chain netifyd_queue_forward { - type filter hook forward priority filter + 1; policy accept; - iifname != $wan_devices queue num 10-29 bypass - oifname != $wan_devices queue num 10-29 bypass -} From 76f08da8cb1a1eecde361c9dc8508cf971bcf09b Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Wed, 17 Dec 2025 13:48:07 +0100 Subject: [PATCH 03/12] removing internal traffic --- .../files/usr/share/nftables.d/table-post/10-netifyd.nft | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft index bd7184afc..3ad500cb2 100644 --- a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft +++ b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft @@ -1,5 +1,7 @@ chain netifyd_queue_input { type filter hook input priority filter + 5; policy accept; + ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept + ip6 saddr ::1 ip6 daddr ::1 accept iifname != $wan_devices queue flags bypass to 10-29 } @@ -10,5 +12,7 @@ chain netifyd_queue_forward { chain netifyd_queue_output { type filter hook output priority filter + 5; policy accept; + ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept + ip6 saddr ::1 ip6 daddr ::1 accept oifname != $wan_devices queue flags bypass to 10-29 } From 164c1688181a8c9cc322136cd5e04fbc8c8e477a Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Fri, 19 Dec 2025 15:50:02 +0100 Subject: [PATCH 04/12] adjusted queues --- .../etc/netifyd/interfaces.d/10-nfqueue.conf | 9 ++++++++- .../nftables.d/table-post/10-netifyd.nft | 20 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf b/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf index 747969dfb..0544df9cf 100644 --- a/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf +++ b/packages/netifyd/files/etc/netifyd/interfaces.d/10-nfqueue.conf @@ -10,7 +10,14 @@ capture_type = nfqueue role = lan queue_id = 10 -queue_instances = 20 +queue_instances = 10 +conntrack_counters = true + +[capture-interface-WAN] +capture_type = nfqueue +role = wan +queue_id = 20 +queue_instances = 10 conntrack_counters = true # vim: set ft=dosini : diff --git a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft index 3ad500cb2..2e7206a48 100644 --- a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft +++ b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft @@ -2,17 +2,29 @@ chain netifyd_queue_input { type filter hook input priority filter + 5; policy accept; ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept ip6 saddr ::1 ip6 daddr ::1 accept - iifname != $wan_devices queue flags bypass to 10-29 + + # Traffic FROM LAN interfaces -> Queue 10-19 + iifname != $wan_devices queue flags bypass to 10-19 + # Traffic FROM WAN interfaces -> Queue 20-29 + iifname $wan_devices queue flags bypass to 20-29 } chain netifyd_queue_forward { type filter hook forward priority filter + 5; policy accept; - iifname != $wan_devices queue flags bypass to 10-29 + + # Traffic entering from LAN (Upload/LAN-to-LAN) -> Queue 10-19 + iifname != $wan_devices queue flags bypass to 10-19 + # Traffic entering from WAN (Download/Port Forwarding) -> Queue 20-29 + iifname $wan_devices queue flags bypass to 20-29 } chain netifyd_queue_output { type filter hook output priority filter + 5; policy accept; ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept ip6 saddr ::1 ip6 daddr ::1 accept - oifname != $wan_devices queue flags bypass to 10-29 -} + + # Traffic going TO LAN interfaces -> Queue 10-19 + oifname != $wan_devices queue flags bypass to 10-19 + # Traffic going TO WAN interfaces -> Queue 20-29 + oifname $wan_devices queue flags bypass to 20-29 +} \ No newline at end of file From c6b7ff9c146ec198a77bec1abcf6c554f2f58e83 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Thu, 29 Jan 2026 16:45:31 +0100 Subject: [PATCH 05/12] updated table location --- packages/netifyd/Makefile | 4 +-- .../99-netify-enable-nfqueue.uci-default | 9 ++++-- .../nftables.d/table-post/10-netifyd.nft | 30 ------------------- .../share/nftables.d/table-pre/10-netifyd.nft | 10 ------- 4 files changed, 8 insertions(+), 45 deletions(-) delete mode 100644 packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft delete mode 100644 packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft diff --git a/packages/netifyd/Makefile b/packages/netifyd/Makefile index 6782da9a5..b5fe3ffda 100644 --- a/packages/netifyd/Makefile +++ b/packages/netifyd/Makefile @@ -167,7 +167,7 @@ define Package/netifyd/install $(INSTALL_DIR) $(1)/usr/share $(INSTALL_DIR) $(1)/usr/share/netifyd $(INSTALL_DIR) $(1)/usr/share/netifyd/plugins.d - $(INSTALL_DIR) $(1)/usr/share/nftables.d/table-pre + $(INSTALL_DIR) $(1)/usr/share/nftables.d/ruleset-pre # netifyd $(INSTALL_DATA) ./files/etc/config/netifyd $(1)/etc/config/netifyd @@ -187,7 +187,7 @@ define Package/netifyd/install $(INSTALL_DATA) ./files/usr/share/netifyd/netify-sink-http-auto.json $(1)/usr/share/netifyd/netify-sink-http-auto.json $(INSTALL_DATA) ./files/usr/share/netifyd/plugins.d/99-netify-proc-core-auto.conf $(1)/usr/share/netifyd/plugins.d/99-netify-proc-core-auto.conf $(INSTALL_DATA) ./files/usr/share/netifyd/plugins.d/99-netify-sink-http-auto.conf $(1)/usr/share/netifyd/plugins.d/99-netify-sink-http-auto.conf - $(INSTALL_DATA) ./files/usr/share/nftables.d/table-pre/10-netifyd.nft $(1)/usr/share/nftables.d/table-pre/10-netifyd.nft + $(INSTALL_DATA) ./files/usr/share/nftables.d/ruleset-pre/netifyd.nft $(1)/usr/share/nftables.d/ruleset-pre/netifyd.nft $(LN) /usr/lib/libnetifyd.so.4.0.0 $(1)/usr/lib/libnetifyd.so $(LN) /usr/lib/libnetifyd.so.4.0.0 $(1)/usr/lib/libnetifyd.so.4 # netify-plm diff --git a/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default b/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default index 7a983425c..d426866af 100644 --- a/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default +++ b/packages/netifyd/files/etc/uci-defaults/99-netify-enable-nfqueue.uci-default @@ -6,6 +6,9 @@ # # Removing the interfaces from netifyd configuration, ignore exit codes -uci -q del netifyd.@netifyd[0].external_if -uci -q del netifyd.@netifyd[0].internal_if -exit 0 +if ! uci -q get netifyd.@netifyd[0].external_if; then + uci -q del netifyd.@netifyd[0].external_if +fi +if ! uci -q get netifyd.@netifyd[0].internal_if; then + uci -q del netifyd.@netifyd[0].internal_if +fi diff --git a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft deleted file mode 100644 index 2e7206a48..000000000 --- a/packages/netifyd/files/usr/share/nftables.d/table-post/10-netifyd.nft +++ /dev/null @@ -1,30 +0,0 @@ -chain netifyd_queue_input { - type filter hook input priority filter + 5; policy accept; - ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept - ip6 saddr ::1 ip6 daddr ::1 accept - - # Traffic FROM LAN interfaces -> Queue 10-19 - iifname != $wan_devices queue flags bypass to 10-19 - # Traffic FROM WAN interfaces -> Queue 20-29 - iifname $wan_devices queue flags bypass to 20-29 -} - -chain netifyd_queue_forward { - type filter hook forward priority filter + 5; policy accept; - - # Traffic entering from LAN (Upload/LAN-to-LAN) -> Queue 10-19 - iifname != $wan_devices queue flags bypass to 10-19 - # Traffic entering from WAN (Download/Port Forwarding) -> Queue 20-29 - iifname $wan_devices queue flags bypass to 20-29 -} - -chain netifyd_queue_output { - type filter hook output priority filter + 5; policy accept; - ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept - ip6 saddr ::1 ip6 daddr ::1 accept - - # Traffic going TO LAN interfaces -> Queue 10-19 - oifname != $wan_devices queue flags bypass to 10-19 - # Traffic going TO WAN interfaces -> Queue 20-29 - oifname $wan_devices queue flags bypass to 20-29 -} \ No newline at end of file diff --git a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft deleted file mode 100644 index ad3e2d1d6..000000000 --- a/packages/netifyd/files/usr/share/nftables.d/table-pre/10-netifyd.nft +++ /dev/null @@ -1,10 +0,0 @@ -set nfa.blocks.v4 { - type ipv4_addr . inet_proto . inet_service . ipv4_addr - size 65536 - timeout 15m -} - -chain netify_block_chain { - type filter hook forward priority -10; policy accept; - ip saddr . ip protocol . th dport . ip daddr @nfa.blocks.v4 counter drop -} From c9ee38b16406496aa30b765b9d88105e74deb263 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Thu, 29 Jan 2026 16:45:48 +0100 Subject: [PATCH 06/12] fix: adapted to new nfqueue --- packages/ns-dpi/Makefile | 2 +- packages/ns-dpi/files/dpi-config | 32 ++++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/ns-dpi/Makefile b/packages/ns-dpi/Makefile index 8ef988b45..772addc83 100644 --- a/packages/ns-dpi/Makefile +++ b/packages/ns-dpi/Makefile @@ -63,7 +63,7 @@ define Package/ns-dpi/install $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_DIR) $(1)/usr/share/ns-plug/hooks/unregister $(INSTALL_DIR) $(1)/etc/xtables - $(INSTALL_CONF) ./files/connlabel.conf $(1)/etc/xtables/connlabel.conf + $(INSTALL_CONF) ./files/connlabel.conf $(1)/etc/connlabel.conf $(INSTALL_BIN) ./files/dpi.init $(1)/etc/init.d/dpi $(INSTALL_BIN) ./files/dpi-license-update.init $(1)/etc/init.d/dpi-license-update $(INSTALL_BIN) ./files/dpi $(1)/usr/sbin/ diff --git a/packages/ns-dpi/files/dpi-config b/packages/ns-dpi/files/dpi-config index 32520b698..b4d742333 100755 --- a/packages/ns-dpi/files/dpi-config +++ b/packages/ns-dpi/files/dpi-config @@ -30,22 +30,17 @@ def get_interface_ips(interface): cfg_file = "/etc/netifyd/netify-proc-flow-actions.json" config = { "reprocess_flows": True, + "target_globals": { + "ctlabel": { + "connlabel_conf": "/etc/connlabel.conf" + }, + }, "targets": { "block": { - "target_type": "nftset", + "target_type": "ctlabel", "target_enabled": True, - "table_name": "fw4", - "table_family": "inet", - "size": 65535, - "ttl": 900, - "set_name": "nfa.blocks", - "set_family": "ipv4", - "flush_on_destroy": True, - "type": [ - "local_addr", - "ip_proto", - "other_port", - "other_addr" + "labels": [ + "netify-block" ] } }, @@ -84,6 +79,8 @@ for section in u.get_all('dpi'): if rule['action'] not in valid_actions or not rule['enabled']: continue + device = rule.get('device', '*') + if 'criteria' in rule: # criteria has precedence over sources, protocol, category and application criteria = rule['criteria'].replace('"',"'") @@ -107,14 +104,14 @@ for section in u.get_all('dpi'): sources_s = ' or '.join(sources) applications_s = ' or '.join(applications) + criteria = f'(iface_nfq_src == \'{device}\' or iface_nfq_dst == \'{device}\') && ' if len(sources) < 1: - criteria = f'({applications_s}) ;' + criteria += f'({applications_s}) ;' elif len(applications) < 1: - criteria = f'({sources_s}) ;' + criteria += f'({sources_s}) ;' else: - criteria = f'({sources_s}) && ({applications_s}) ;' + criteria += f'({sources_s}) && ({applications_s}) ;' - device = rule.get('device', '*') vlan_id = None base_if = None for item in utils.get_all_by_type(u, 'network', 'device').values(): @@ -129,7 +126,6 @@ for section in u.get_all('dpi'): config["actions"][f"rule{rcount}"] = { "enabled": rule['enabled'] == '1', - "interface": device, "criteria": criteria, "targets": [rule['action']], "exemptions": rule.get('exemption', []) From 96f937941c419dc5492cf038b079c616f4c274aa Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Thu, 29 Jan 2026 17:33:29 +0100 Subject: [PATCH 07/12] completed nfq --- packages/netifyd/Makefile | 4 +- .../share/nftables.d/table-pre/netifyd.nft | 5 ++ packages/ns-dpi/files/dpi | 2 +- packages/ns-dpi/files/dpi-nft | 59 +++++++++++-------- packages/ns-dpi/files/dpi.init | 1 - 5 files changed, 42 insertions(+), 29 deletions(-) create mode 100644 packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft diff --git a/packages/netifyd/Makefile b/packages/netifyd/Makefile index b5fe3ffda..7b8d6523f 100644 --- a/packages/netifyd/Makefile +++ b/packages/netifyd/Makefile @@ -167,7 +167,7 @@ define Package/netifyd/install $(INSTALL_DIR) $(1)/usr/share $(INSTALL_DIR) $(1)/usr/share/netifyd $(INSTALL_DIR) $(1)/usr/share/netifyd/plugins.d - $(INSTALL_DIR) $(1)/usr/share/nftables.d/ruleset-pre + $(INSTALL_DIR) $(1)/usr/share/nftables.d/table-pre # netifyd $(INSTALL_DATA) ./files/etc/config/netifyd $(1)/etc/config/netifyd @@ -187,7 +187,7 @@ define Package/netifyd/install $(INSTALL_DATA) ./files/usr/share/netifyd/netify-sink-http-auto.json $(1)/usr/share/netifyd/netify-sink-http-auto.json $(INSTALL_DATA) ./files/usr/share/netifyd/plugins.d/99-netify-proc-core-auto.conf $(1)/usr/share/netifyd/plugins.d/99-netify-proc-core-auto.conf $(INSTALL_DATA) ./files/usr/share/netifyd/plugins.d/99-netify-sink-http-auto.conf $(1)/usr/share/netifyd/plugins.d/99-netify-sink-http-auto.conf - $(INSTALL_DATA) ./files/usr/share/nftables.d/ruleset-pre/netifyd.nft $(1)/usr/share/nftables.d/ruleset-pre/netifyd.nft + $(INSTALL_DATA) ./files/usr/share/nftables.d/table-pre/netifyd.nft $(1)/usr/share/nftables.d/table-pre/netifyd.nft $(LN) /usr/lib/libnetifyd.so.4.0.0 $(1)/usr/lib/libnetifyd.so $(LN) /usr/lib/libnetifyd.so.4.0.0 $(1)/usr/lib/libnetifyd.so.4 # netify-plm diff --git a/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft new file mode 100644 index 000000000..e45c01166 --- /dev/null +++ b/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft @@ -0,0 +1,5 @@ +chain nfq { + type filter hook forward priority filter + 10; policy accept; + ct packets > 32 counter return + counter queue num 10-19 bypass +} \ No newline at end of file diff --git a/packages/ns-dpi/files/dpi b/packages/ns-dpi/files/dpi index a17994109..267e6d6fe 100755 --- a/packages/ns-dpi/files/dpi +++ b/packages/ns-dpi/files/dpi @@ -8,6 +8,6 @@ # Generate netify flow actions config file /usr/sbin/dpi-config # Apply nftables rules -/usr/sbin/dpi-nft | nft -f - +/usr/sbin/dpi-nft # reload netifyd daemon /etc/init.d/netifyd reload diff --git a/packages/ns-dpi/files/dpi-nft b/packages/ns-dpi/files/dpi-nft index 48c7231c0..463cd7c86 100755 --- a/packages/ns-dpi/files/dpi-nft +++ b/packages/ns-dpi/files/dpi-nft @@ -1,33 +1,42 @@ -#!/bin/sh +#!/usr/bin/env python # -# Copyright (C) 2025 Nethesis S.r.l. +# Copyright (C) 2026 Nethesis S.r.l. # SPDX-License-Identifier: GPL-2.0-only # -# -# DPI: generate NFT script -# +import subprocess + +from euci import EUci +from jinja2 import Environment, BaseLoader + +CHAIN=""" +chain dpi_blocks { + # filter is + 11 to be before the nfq hook at + 10 + type filter hook forward priority filter + 11; policy accept; + + # init is to allow kernel to set labels + ct label set netify-init + ct label netify-block counter {% if log_enabled %}log prefix "DPI block: " limit rate {{ log_limit }} {% endif %}drop +} +""" -log_opt="" -if [ $(uci -q get dpi.config.log_blocked) = "1" ]; then - log_opt='log prefix "DPI block: "' - limit=$(uci -q get firewall.ns_defaults.rule_log_limit) - # validate limit syntax to avoid error on nft rules - if echo "$limit" | grep -qE '^[0-9]+/s$'; then - limit="${limit}econd" - else - limit="1/second" - fi -fi -if nft list chain inet fw4 block_chain >/dev/null 2>&1; then - echo flush chain inet fw4 block_chain -fi +def generate_dpi(): + e_uci = EUci() + template = Environment(loader=BaseLoader()).from_string(CHAIN) + render = template.render( + log_enabled=e_uci.get('dpi', 'config', 'log_blocked', dtype=bool, default=False), + log_limit=e_uci.get('firewall', 'ns_defaults', 'rule_log_limit', dtype=str, default='1/s') + ) + # save to nftables directory table-pre, only if the file is changed + with open('/usr/share/nftables.d/table-pre/dpi_blocks.nft', 'r') as f: + current = f.read() + if current != render: + with open('/usr/share/nftables.d/table-pre/dpi_blocks.nft', 'w') as f: + f.write(render) + # reload nftables + subprocess.run(['fw4', 'reload'], check=True) -echo add set inet fw4 nfa.blocks.v4 '{ type ipv4_addr . inet_proto . inet_service . ipv4_addr; size 65536; timeout 15m; }' -echo add chain inet fw4 block_chain '{ type filter hook forward priority -10; }' -if [ -n "$log_opt" ]; then - echo add rule inet fw4 block_chain ip saddr . ip protocol . th dport . ip daddr @nfa.blocks.v4 limit rate $limit burst 5 packets $log_opt -fi -echo add rule inet fw4 block_chain ip saddr . ip protocol . th dport . ip daddr @nfa.blocks.v4 counter drop +if __name__ == "__main__": + generate_dpi() diff --git a/packages/ns-dpi/files/dpi.init b/packages/ns-dpi/files/dpi.init index 3186f1bba..663dae8d9 100755 --- a/packages/ns-dpi/files/dpi.init +++ b/packages/ns-dpi/files/dpi.init @@ -25,7 +25,6 @@ start_service() { reload_service() { - stop start } From bc2f1398a04a23bceca32b3095a50ea3f14b2a4f Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Fri, 30 Jan 2026 11:29:21 +0100 Subject: [PATCH 08/12] added traffic for-from firewall --- .../share/nftables.d/table-pre/netifyd.nft | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft b/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft index e45c01166..572f72e28 100644 --- a/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft +++ b/packages/netifyd/files/usr/share/nftables.d/table-pre/netifyd.nft @@ -1,5 +1,33 @@ -chain nfq { +chain nfq_input { + type filter hook input priority filter + 10; policy accept; + ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept + ip6 saddr ::1 ip6 daddr ::1 accept + + ct packets > 32 counter accept + # Traffic FROM LAN interfaces -> Queue 10-19 + iifname != $wan_devices queue flags bypass to 10-19 + # Traffic FROM WAN interfaces -> Queue 20-29 + iifname $wan_devices queue flags bypass to 20-29 +} + +chain nfq_forward { type filter hook forward priority filter + 10; policy accept; - ct packets > 32 counter return - counter queue num 10-19 bypass -} \ No newline at end of file + + ct packets > 32 counter accept + # Traffic entering from LAN (Upload/LAN-to-LAN) -> Queue 10-19 + iifname != $wan_devices queue flags bypass to 10-19 + # Traffic entering from WAN (Download/Port Forwarding) -> Queue 20-29 + iifname $wan_devices queue flags bypass to 20-29 +} + +chain nfq_output { + type filter hook output priority filter + 10; policy accept; + ip saddr 127.0.0.1 ip daddr 127.0.0.1 accept + ip6 saddr ::1 ip6 daddr ::1 accept + + ct packets > 32 counter accept + # Traffic going TO LAN interfaces -> Queue 10-19 + oifname != $wan_devices queue flags bypass to 10-19 + # Traffic going TO WAN interfaces -> Queue 20-29 + oifname $wan_devices queue flags bypass to 20-29 +} From f480cb10702f9e618453236e72f27b7cb26c5b67 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Fri, 30 Jan 2026 11:31:38 +0100 Subject: [PATCH 09/12] moved blocking to pre-routing --- packages/ns-dpi/files/dpi-nft | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/ns-dpi/files/dpi-nft b/packages/ns-dpi/files/dpi-nft index 463cd7c86..618c0fa70 100755 --- a/packages/ns-dpi/files/dpi-nft +++ b/packages/ns-dpi/files/dpi-nft @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0-only # +import os import subprocess from euci import EUci @@ -12,13 +13,13 @@ from jinja2 import Environment, BaseLoader CHAIN=""" chain dpi_blocks { - # filter is + 11 to be before the nfq hook at + 10 - type filter hook forward priority filter + 11; policy accept; + type filter hook prerouting priority filter + 10; policy accept; # init is to allow kernel to set labels ct label set netify-init ct label netify-block counter {% if log_enabled %}log prefix "DPI block: " limit rate {{ log_limit }} {% endif %}drop } + """ @@ -27,13 +28,16 @@ def generate_dpi(): template = Environment(loader=BaseLoader()).from_string(CHAIN) render = template.render( log_enabled=e_uci.get('dpi', 'config', 'log_blocked', dtype=bool, default=False), - log_limit=e_uci.get('firewall', 'ns_defaults', 'rule_log_limit', dtype=str, default='1/s') + log_limit=e_uci.get('firewall', 'ns_defaults', 'rule_log_limit', dtype=str, default='1/second') ) # save to nftables directory table-pre, only if the file is changed - with open('/usr/share/nftables.d/table-pre/dpi_blocks.nft', 'r') as f: - current = f.read() + file_path = '/usr/share/nftables.d/table-pre/dpi_blocks.nft' + current = None + if os.path.exists(file_path): + with open(file_path, 'r') as f: + current = f.read() if current != render: - with open('/usr/share/nftables.d/table-pre/dpi_blocks.nft', 'w') as f: + with open(file_path, 'w') as f: f.write(render) # reload nftables subprocess.run(['fw4', 'reload'], check=True) From 88073cd03532e6951f258935123d17ece8ce89a8 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Fri, 30 Jan 2026 11:37:25 +0100 Subject: [PATCH 10/12] removed dpi output --- packages/ns-dpi/files/dpi-nft | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ns-dpi/files/dpi-nft b/packages/ns-dpi/files/dpi-nft index 618c0fa70..2ec876ae4 100755 --- a/packages/ns-dpi/files/dpi-nft +++ b/packages/ns-dpi/files/dpi-nft @@ -40,7 +40,7 @@ def generate_dpi(): with open(file_path, 'w') as f: f.write(render) # reload nftables - subprocess.run(['fw4', 'reload'], check=True) + subprocess.run(['fw4', 'reload'], check=True, capture_output=True) if __name__ == "__main__": generate_dpi() From 6a06c6fe4e18329dfa6776c8d67c2b5813d453f7 Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Fri, 30 Jan 2026 11:50:47 +0100 Subject: [PATCH 11/12] fixed connlabels --- packages/ns-dpi/files/connlabel.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ns-dpi/files/connlabel.conf b/packages/ns-dpi/files/connlabel.conf index d9daafc36..03b23f4e9 100644 --- a/packages/ns-dpi/files/connlabel.conf +++ b/packages/ns-dpi/files/connlabel.conf @@ -1,5 +1,5 @@ -0 dummy -1 block +0 netify-init +1 netify-block 2 bulk 3 best_effort 4 video From b5a71dd227c9244c62081232497ddbdaa013d94a Mon Sep 17 00:00:00 2001 From: Tommaso Bailetti Date: Wed, 4 Feb 2026 16:23:35 +0100 Subject: [PATCH 12/12] Triggering clean build