npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nftables-napi

v0.3.0

Published

Native Node.js binding for nftables via libnftnl+libmnl — nftables firewall management

Downloads

638

Readme

nftables-napi

Native Node.js binding for nftables via libnftnl + libmnl. Manages IPv4/IPv6 firewall tables with dynamic IP sets, port blocking, named counters, and timeout support through direct netlink communication — no shell commands, no nft CLI.

Requires Linux kernel ≥ 5.7 with CAP_NET_ADMIN or root.

Install

npm install nftables-napi

Prebuilt binaries are included for linux-x64 and linux-arm64. If a prebuild is not available for your platform, the package will compile from source (requires libnftnl-dev, libmnl-dev, pkg-config, and a C++20 compiler).

Runtime dependencies

The module dynamically links against libnftnl and libmnl. These must be present in the runtime environment. The nft CLI is not required — the module talks to the kernel directly via netlink.

Alpine:

RUN apk add --no-cache libnftnl libmnl

Debian/Ubuntu:

RUN apt-get update && apt-get install -y libnftnl13 libmnl0 && rm -rf /var/lib/apt/lists/*

Usage

const { NftManager } = require("nftables-napi");

const nft = new NftManager({
  tableName: "myfw",
  ingressAddrSets: ["blacklist"],
  egressAddrSets: ["blocklist"],
  egressPortSets: ["blocked_ports"],
});

await nft.createTable();

// ── IP blocking (input/forward) ──

await nft.addAddress({ ip: "1.2.3.4", set: "blacklist", timeout: 1800 });
await nft.addAddress({ ip: "2001:db8::1", set: "blacklist", timeout: 3600 });
await nft.addAddresses({ ips: ["10.0.0.1", "10.0.0.2"], set: "blacklist", timeout: 7200 });

await nft.removeAddress({ ip: "1.2.3.4", set: "blacklist" });
await nft.removeAddresses({ ips: ["10.0.0.1", "10.0.0.2"], set: "blacklist" });

// ── IP blocking (output) ──

await nft.addAddress({ ip: "93.184.216.34", set: "blocklist" });
await nft.removeAddress({ ip: "93.184.216.34", set: "blocklist" });

// ── Port blocking (output, tcp/udp) ──

// Block port 80 for both TCP and UDP
await nft.addPort({ port: 80, set: "blocked_ports", timeout: 3600 });

// Block port 443 for TCP only
await nft.addPort({ port: 443, set: "blocked_ports", protocol: "tcp" });

// Bulk port operations
await nft.addPorts({ ports: [8080, 8443], set: "blocked_ports", protocol: "tcp" });
await nft.removePorts({ ports: [8080, 8443], set: "blocked_ports", protocol: "tcp" });

await nft.removePort({ port: 80, set: "blocked_ports" });

// ── Cleanup ──

await nft.deleteTable();

API

new NftManager(options)

| Option | Type | Required | Description | | --- | --- | --- | --- | | tableName | string | Yes | Base table name. IPv6 table auto-appends '6'. | | ingressAddrSets | string[] | Yes | Input/forward IP set names (≥1). Block by source address on input and forward chains. Rules: log + named counter + drop. IPv6 sets auto-append '6'. | | egressAddrSets | string[] | No | Output IP set names. Block by destination address on output chain. Rules: named counter + drop (no log). IPv6 sets auto-append '6'. | | egressPortSets | string[] | No | Output port set names. Block by destination port (TCP/UDP) on output chain using concatenated inet_proto . inet_service sets. Ports are added to both IPv4 and IPv6 tables. IPv6 sets auto-append '6'. |

Methods

All methods return Promise<void> and throw on error.

Table management

| Method | Description | | --- | --- | | createTable() | Create IPv4/IPv6 tables with all configured sets, chains, named counters, and filter rules. Idempotent — deletes existing tables first. | | deleteTable() | Delete both tables. Idempotent — no error if tables don't exist. |

IP address operations

Work with both ingressAddrSets (input/forward) and egressAddrSets (output).

| Method | Description | | --- | --- | | addAddress({ ip, set, timeout? }) | Add IP to set. Auto-detects IPv4/IPv6. timeout in seconds, omit for permanent. | | removeAddress({ ip, set }) | Remove IP from set. Idempotent. | | addAddresses({ ips, set, timeout? }) | Bulk add. Chunked internally for efficient netlink communication. Empty array is a no-op. | | removeAddresses({ ips, set }) | Bulk remove. Idempotent. Empty array is a no-op. |

Port operations

Work with egressPortSets only. Ports are added to both IPv4 and IPv6 tables.

| Method | Description | | --- | --- | | addPort({ port, set, protocol?, timeout? }) | Add port to set. protocol: 'tcp', 'udp', or omit for both. timeout in seconds. | | removePort({ port, set, protocol? }) | Remove port from set. Idempotent. | | addPorts({ ports, set, protocol?, timeout? }) | Bulk add ports. Empty array is a no-op. | | removePorts({ ports, set, protocol? }) | Bulk remove ports. Idempotent. Empty array is a no-op. |

What createTable() builds

For a config with ingressAddrSets: ["bl"], egressAddrSets: ["out"], egressPortSets: ["ports"]:

table ip myfw {
    counter "processed" { packets 0 bytes 0 }
    counter "bl"        { packets 0 bytes 0 }
    counter "out"       { packets 0 bytes 0 }
    counter "ports"     { packets 0 bytes 0 }

    set bl {
        type ipv4_addr
        flags timeout
        counter
    }

    set out {
        type ipv4_addr
        flags timeout
        counter
    }

    set ports {
        type inet_proto . inet_service
        flags timeout
        counter
    }

    chain input {
        type filter hook input priority -10; policy accept;
        counter name "processed"
        ip saddr @bl log prefix "bl: " counter name "bl" drop
    }

    chain forward {
        type filter hook forward priority -10; policy accept;
        counter name "processed"
        ip saddr @bl log prefix "bl: " counter name "bl" drop
    }

    chain output {
        type filter hook output priority -10; policy accept;
        ip daddr @out counter name "out" drop
        meta l4proto . th dport @ports counter name "ports" drop
    }
}

IPv6 table (myfw6) mirrors the same structure with ipv6_addr sets and corresponding offsets.

Kernel compatibility

Minimum: Linux 5.7

| Feature | Kernel | Used for | | --- | --- | --- | | nftables core | 3.13 | tables, chains, sets, rules | | Set timeouts | 4.1 | element expiration | | Named counters | 4.10 | traffic accounting | | Concatenated sets | 5.6 | port blocking (inet_proto . inet_service) | | Per-element set expressions | 5.7 | per-element counters |

| Distro | Kernel | Compatible | | --- | --- | --- | | Ubuntu 22.04+ | 5.15+ | Yes | | Ubuntu 20.04 (HWE) | 5.15 | Yes | | Ubuntu 20.04 (GA) | 5.4 | No | | Debian 11+ | 5.10+ | Yes | | Debian 10 | 4.19 | No | | RHEL / Rocky 9 | 5.14 | Yes | | RHEL / Rocky 8 | 4.18 | No | | Alpine 3.16+ | 5.15+ | Yes |

Building from source

# Dependencies (Debian/Ubuntu)
sudo apt install pkg-config libnftnl-dev libmnl-dev build-essential

# Dependencies (Alpine)
apk add pkgconfig libnftnl-dev libmnl-dev build-base python3

# Build
npm run build

# Run tests (requires root / CAP_NET_ADMIN)
npm test

# Prebuild for current platform
npx prebuildify --napi --strip

# Prebuild for linux/amd64 + linux/arm64 via Docker
npm run prebuild:all

License

AGPL-3.0-only