NFTables.Expr (NFTables v0.8.2)

View Source

Pure expression builder for nftables rules.

This module provides the core expression builder struct and entry points. All match and action functions are organized into specialized sub-modules.

Usage

Import the main module for the core expr/1 function and protocol shortcuts, then import the specific sub-modules you need:

import NFTables.Expr           # Core: expr/1
import NFTables.Expr.{IP, Port, TCP, Verdict}

# Build rule expressions
rule = tcp() |> dport(22) |> accept()

Module Organization

Expression building functions are organized into specialized modules:

Common Import Patterns

Basic Firewall Rules

import NFTables.Expr
import NFTables.Expr.{IP, Port, TCP, Verdict}

rule = tcp() |> dport(22) |> accept()

With Connection Tracking

import NFTables.Expr
import NFTables.Expr.{IP, Port, TCP, CT, Actions, Verdict}

rule = tcp() |> dport(22) |> ct_state([:new]) |> counter() |> accept()

NAT Rules

import NFTables.Expr
import NFTables.Expr.{IP, Port, TCP, NAT, Verdict}

rule = tcp() |> dport(8080) |> dnat_to("192.168.1.100:80")

Complete Firewall (Import Everything)

use NFTables will import all Expr.* modules into the current modules namespace.

use NFTables
# equivalient to:
#   import NFTables.Expr
#   import NFTables.Expr.{IP, Port, TCP, UDP, Layer2, CT, ICMP, Metadata, Socket, Actions, NAT, Verdict}

rule = tcp() |> dport(8080) |> dnat_to("192.168.1.100:80")

Quick Example

import NFTables.Expr
import NFTables.Expr.{Port, TCP, CT, Actions, Verdict}

# Build rule expressions
ssh_rule = tcp() |> dport(22) |> ct_state([:new]) |> rate_limit(10, :minute) |> accept()
established_rule = ct_state([:established, :related]) |> accept()

# Use with NFTables
NFTables.add(table: "filter", family: :inet)
|> NFTables.add(chain: "INPUT", type: :filter, hook: :input)
|> NFTables.add(rule: ssh_rule)
|> NFTables.add(rule: established_rule)
|> NFTables.submit(pid: pid)

Expression Structure

All sub-modules work with the same %NFTables.Expr{} struct, which contains:

  • expr_list - List of JSON expression maps
  • family - Protocol family (:inet, :inet6, etc.)
  • protocol - Current protocol context (:tcp, :udp, etc.)
  • comment - Optional rule comment

Functions from sub-modules can be chained together via the pipeline operator:

expr()
|> IP.source_ip("10.0.0.0/8")
|> TCP.tcp()
|> Port.dport(22)
|> CT.ct_state([:new])
|> Actions.log("New SSH connection")
|> Verdict.accept()

When fully imported, this becomes:

expr()
|> source_ip("10.0.0.0/8")
|> tcp()
|> dport(22)
|> ct_state([:new])
|> log("New SSH connection")
|> accept()

See Also

Summary

Functions

Add a comment to the rule.

Start building a new rule expression.

Set the protocol context for subsequent port matching.

Convert an expression to a list of JSON expression maps.

Types

t()

@type t() :: %NFTables.Expr{
  comment: String.t() | nil,
  expr_list: [map()],
  family: atom(),
  protocol: atom() | nil
}

Functions

comment(rule, text)

@spec comment(t(), String.t()) :: t()

Add a comment to the rule.

Note: Comments are metadata and don't affect rule matching.

Examples

import NFTables.Expr
import NFTables.Expr.{Port, TCP, Verdict}

tcp() |> dport(22) |> comment("Allow SSH from trusted network") |> accept()

expr(opts \\ [])

@spec expr(keyword()) :: t()

Start building a new rule expression.

Returns an empty Expr struct ready for building rule expressions via piping.

Parameters

  • opts - Options:
    • :family - Protocol family (default: :inet)

Examples

import NFTables.Expr
import NFTables.Expr.{TCP, Port, Verdict}

# Start a new rule with default family
tcp() |> dport(22) |> accept()

# Start with specific family
expr(family: :inet6) |> tcp() |> dport(22) |> accept()

# Multiple rules
ssh = tcp() |> dport(22) |> accept()
http = tcp() |> dport(80) |> accept()

set_protocol(builder, protocol)

@spec set_protocol(t(), atom()) :: t()

Set the protocol context for subsequent port matching.

This is used internally by tcp(), udp(), etc. in the TCP module to track which protocol the rule is matching, allowing sport/dport to work protocol-agnostically.

Most users won't need to call this directly.

to_list(expr)

@spec to_list(t()) :: [map()]

Convert an expression to a list of JSON expression maps.

This is used internally by Builder when extracting expression lists from Expr structs. Most users won't need to call this directly.

Examples

import NFTables.Expr
import NFTables.Expr.{TCP, Port, Verdict}

expression = tcp() |> dport(22) |> accept()
expr_list = to_list(expression)
# Use expr_list with Builder: NFTables.add(builder, rule: expr_list)