NFTables.Port (NFTables.Port v0.4.2)
View SourceGenServer managing the nftables port process with JSON communication.
This module provides the low-level interface to nftables via a native Zig port executable. All communication uses JSON format through the official libnftables library, providing a simple, performant, and safe interface to the kernel firewall.
Architecture
flowchart TD
GenServer[NFTables.Port<br/>GenServer]
Port[Erlang Port<br/>Zig executable]
Lib[libnftables<br/>C library]
Kernel[Linux Kernel<br/>nftables]
GenServer --> Port
Port --> Lib
Lib --> KernelCommunication Flow
Request: Elixir JSON → [4-byte length][JSON bytes] → Zig → libnftables → kernel
Response: kernel → libnftables → Zig → [4-byte length][JSON bytes] → Elixir JSON
Protocol
The port uses 4-byte big-endian length-prefixed packets for framing:
[4 bytes: packet length][N bytes: JSON string]This framing is handled automatically by Erlang's {:packet, 4} option.
Port Binary Location
The native port executable is located using the following resolution order:
- PORT_NFTABLES_PATH environment variable (if set and file exists)
- /usr/local/sbin/port_nftables (system-wide installation)
- /usr/sbin/port_nftables (system-wide installation)
- priv/port_nftables (development or application-bundled)
For production deployments, set the PORT_NFTABLES_PATH environment variable
to specify a custom location, or install to /usr/local/sbin/port_nftables.
Capabilities
The port executable requires CAP_NET_ADMIN capability to communicate with
the kernel firewall. Set it with:
sudo setcap cap_net_admin=ep /path/to/port_nftablesUsage Example
# Start the port process
{:ok, pid} = NFTables.Port.start_link()
# Send a request to list tables
request = ~s({"nftables": [{"list": {"tables": {}}}]})
{:ok, response} = NFTables.Port.commit(pid, request)
# Parse the response
{:ok, data} = JSON.decode(response)Direct Usage vs High-Level APIs
This module is typically used indirectly through NFTables high-level APIs (Table, Chain, Rule, Set, etc.) which handle JSON construction and parsing. Direct usage is appropriate for:
- Custom nftables operations not covered by high-level APIs
- Performance-critical code paths
- Advanced nftables features
- Testing and debugging
Summary
Functions
Returns a specification to start this module under a supervisor.
Commit a request to nftables and wait for response.
Start the nftables port GenServer.
Stop the port GenServer.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
Commit a request to nftables and wait for response.
Sends a JSON-formatted nftables request to the port process, which forwards it to the native port executable that communicates with libnftables. The function blocks until a response is received or the timeout expires.
Parameters
pid- The port GenServer PIDrequest- JSON string containing nftables commandstimeout- Timeout in milliseconds (default: 5000)
Returns
{:ok, json_string}- Success, returns JSON string response from nftables{:error, reason}- Error occurred during request processing
Examples
# List all tables
request = ~s({"nftables": [{"list": {"tables": {}}}]})
{:ok, response} = NFTables.Port.commit(pid, request)
# Add a table
request = ~s({"nftables": [{"add": {"table": {"family": "inet", "name": "filter"}}}]})
{:ok, response} = NFTables.Port.commit(pid, request)
# With custom timeout
{:ok, response} = NFTables.Port.commit(pid, request, 10_000)
Start the nftables port GenServer.
Spawns the native Zig port executable and establishes JSON communication. The port process will remain running until explicitly stopped or until it crashes (in which case this GenServer will also terminate).
Options
:check_capabilities- Check for CAP_NET_ADMIN capability on startup (default: true):name- Register the GenServer with a name (optional)
Returns
{:ok, pid}- Successfully started port GenServer{:error, reason}- Failed to start
Examples
# Start with default options
{:ok, pid} = NFTables.Port.start_link()
# Start with named registration
{:ok, pid} = NFTables.Port.start_link(name: MyApp.NFTablesPort)
# Skip capability check (not recommended for production)
{:ok, pid} = NFTables.Port.start_link(check_capabilities: false)
Stop the port GenServer.
Gracefully shuts down the port process and closes the connection to the native port executable. Any pending requests will fail.
Parameters
pid- The port GenServer PID
Returns
:ok
Examples
{:ok, pid} = NFTables.Port.start_link()
# ... use the port ...
:ok = NFTables.Port.stop(pid)