Skip to content

firewall

Thomas Mangin edited this page Jun 24, 2026 · 7 revisions

Pre-Alpha. This page describes behavior that may change.

Ze manages nftables packet filter and NAT rules from a single firewall { } YANG section. The abstract data model describes matches (from) and actions (then); the backend lowers them to kernel expressions.

Backend

Backend Platform Mechanism
nft Linux google/nftables netlink library
vpp Linux + VPP GoVPP ACL classify pipeline
firewall {
    backend nft;
}

The ze:backend YANG extension provides commit-time rejection of unsupported features. If a feature is not supported by the configured backend, the commit fails with a descriptive error.

Tables and chains

Ze owns all tables whose kernel name starts with ze_. A table contains one or more chains; a base chain has a type, hook, priority, and default policy.

firewall {
    backend nft;
    table wan {
        family inet;
        chain input {
            type filter;
            hook input;
            priority 0;
            policy drop;
            term allow-ssh {
                from {
                    destination-port 22;
                    protocol tcp;
                }
                then {
                    accept;
                }
            }
            term allow-established {
                from {
                    connection-state established,related;
                }
                then {
                    accept;
                }
            }
        }
    }
}

Table families

inet (dual-stack), ip, ip6, arp, bridge, netdev.

Chain types

filter, nat, route.

Hooks

input, output, forward, prerouting, postrouting, ingress, egress.

Match types

Config key Match Example
source-address IP prefix source-address 10.0.0.0/8;
destination-address IP prefix destination-address 192.168.1.0/24;
source-port Port or range source-port 1024-65535;
destination-port Port, range, or list destination-port 80,443;
protocol L4 protocol protocol tcp;
input-interface Interface name input-interface eth0;
output-interface Interface name output-interface "l2tp*";
icmp-type ICMP type (name or number) icmp-type echo-request;
icmpv6-type ICMPv6 type icmpv6-type nd-neighbor-solicit;
connection-state Conntrack states connection-state established,related;
connection-mark Mark value/mask connection-mark 0x10/0xff;
mark Packet mark value/mask mark 0x10/0xff;
dscp DSCP value dscp ef;
tcp-flags TCP header flags tcp-flags syn;
match-set Named set lookup match-set blocked source-address;

A trailing * on an interface name produces a prefix match ("l2tp*" matches l2tp0, l2tp1, etc.).

Action types

Config key Action Example
accept Accept packet accept;
drop Drop packet drop;
reject Reject with ICMP reject { with icmp; code 3; }
jump / goto Chain transfer jump helper;
return Return from chain return;
snat Source NAT snat { to "10.0.0.1"; }
dnat Destination NAT dnat { to "10.1.1.1:8080"; }
masquerade Masquerade masquerade; or masquerade { port-range "1024-65535"; } or masquerade { random; }
redirect Redirect to port redirect { port 8080; }
notrack Disable conntrack notrack;
flow-offload Hardware offload flow-offload ft0;
mark Set packet mark mark { value 0x10; }
connection-mark Set connmark connection-mark { value 0x20; mask 0xff; }
dscp Set DSCP dscp { value 46; }
tcp-mss Clamp TCP MSS tcp-mss { size 1400; }
counter Count packets/bytes counter my-counter;
log Log packet log { prefix "DROPPED"; }
limit Rate limit limit { rate 10/second; burst 5; }
exclude Skip NAT (Return) exclude;

NAT

SNAT, DNAT, masquerade, and redirect are available in nat chains. exclude emits a Return verdict so matched traffic skips NAT translation. SNAT and DNAT accept address ranges for pool-based NAT: snat { to "10.0.0.1-10.0.0.10"; }.

masquerade accepts an optional port-range "lo-hi" to constrain the source port pool, or the flags random (random { full; } for fully-random port allocation) and persistent. A port range and the flags are mutually exclusive: configuring both is rejected at commit.

VPP backend

When backend vpp is configured and VPP is running, the firewall uses VPP's ACL classify pipeline instead of nftables:

  • NAT44-ED: SNAT, DNAT, and masquerade via VPP's NAT44-ED plugin.
  • ACL classify: SetMark and Limit actions through VPP classify tables.
  • Hardened: patterns discovered in VyOS VPP integration are handled defensively.

The VPP backend supports the same YANG config surface. Features not yet supported by VPP are rejected at commit time via the backend gate.

Named sets

firewall {
    backend nft;
    table wan {
        family inet;
        set blocked {
            type ipv4_addr;
            element 10.0.0.1;
            element 10.0.0.2 { timeout 3600; }
        }
        chain input {
            type filter;
            hook input;
            priority 0;
            policy drop;
            term block-list {
                from {
                    match-set blocked source-address;
                }
                then {
                    drop;
                }
            }
        }
    }
}

Set elements support optional per-element timeouts for dynamic blocklists.

Global options

The global-options container provides sysctl convenience mappings for common firewall-related kernel tunables, so you do not need to duplicate them in the sysctl { } block.

firewall {
    global-options {
        all-ping enable;
        broadcast-ping disable;
        ip-src-route disable;
        ipv6-src-route disable;
        log-martians enable;
        receive-redirects disable;
        send-redirects disable;
        syn-cookies enable;
    }
}

These map to their corresponding net.ipv4.* / net.ipv6.* sysctls and are applied through the sysctl plugin for three-layer precedence.

IRR prefix-list filtering

The firewall-irr plugin matches traffic by ASN or AS-SET using prefix lists resolved from Internet Routing Registry (IRR) data. It expands a reference into the set of registered prefixes, caches the result, and populates nftables interval sets that firewall terms match against.

Expansion is dual-stack: each ASN or AS-SET resolves to both an IPv4 and an IPv6 prefix list, lowered into separate irr_v4_<name> and irr_v6_<name> interval sets.

The plugin reuses the same shared IRR prefix store (the resolve IRR client plus the on-disk cache) as the bgp-filter-irr plugin, so a prefix list fetched for BGP filtering is also available to the firewall and vice versa.

Operator workflow

  1. Fetch prefix data: update firewall irr asn 13335
  2. Inspect cached data: show firewall irr
  3. Commit config referencing the ASN or AS-SET in a term's from block.
  4. Refresh all cached entries: update firewall irr all

Match leaves

These leaves are used inside a term from block:

Leaf Type Match
source-asn uint32 Source address against the ASN's IRR prefixes
source-as-set string Source address against the AS-SET's IRR prefixes
destination-asn uint32 Destination address against the ASN's IRR prefixes
destination-as-set string Destination address against the AS-SET's IRR prefixes
firewall {
    irr {
        server whois.radb.net;
        peeringdb-url "https://www.peeringdb.com";
        refresh-interval 0;   // 0 = manual only; 60 to 86400 = auto-refresh seconds
    }
    table wan {
        family inet;
        chain forward {
            type filter;
            hook forward;
            priority 0;
            policy drop;
            term from-cloudflare {
                from {
                    source-asn 13335;
                }
                then {
                    accept;
                }
            }
        }
    }
}

Config commit is rejected if a referenced ASN or AS-SET has no cached prefix data. The error names the missing entry and the exact update firewall irr ... command to run.

Auto-refresh (when refresh-interval > 0) is fail-closed: a failed IRR query keeps the last-good cache and logs an error rather than emptying the set.

Per-interface source validation

Bind an AS-SET to a customer-facing interface to enforce ingress source validation (BCP 38). Packets arriving on that interface whose source address is not in the AS-SET's IRR-resolved prefixes are dropped.

firewall {
    irr {
        interface eth1 {
            source-as-set AS-CUSTOMER-A;
        }
        interface eth2 {
            source-as-set AS-CUSTOMER-B;
        }
    }
}

The plugin generates a ze_irr_iface table with a prerouting base chain. For each bound interface it emits accept terms matching input-interface plus source address in the set (IPv4 and IPv6), followed by a drop term for that interface. Unconfigured interfaces pass through unfiltered (chain policy accept). The same fail-closed commit check applies: a bound AS-SET with no cached prefix data rejects the commit. Removing an interface binding removes its filter on the next apply.

FlowSpec-to-firewall bridge

The flowspec-firewall plugin converts BGP FlowSpec rules into nftables firewall entries. When a peer announces FlowSpec routes, the plugin translates the FlowSpec match/action into an nftables rule in a dedicated ze_flowspec table.

plugin {
    internal flowspec-fw { use flowspec-firewall }
}

bgp {
    peer upstream {
        process flowspec-fw { receive [ update ]; }
    }
}

CLI

Command Description
show firewall Display all firewall tables and rules.
show firewall counters Per-term packet and byte counters.
clear firewall counters Reset match counters.
show firewall irr IRR filter status for all cached entries.
show firewall irr prefix <asn-or-as-set> List cached prefixes for an ASN or AS-SET.
update firewall irr asn <asn> Fetch or refresh the IRR prefix-list for an ASN.
update firewall irr as-set <as-set> Fetch or refresh the IRR prefix-list for an AS-SET.
update firewall irr all Refresh all cached IRR entries.

See also

Adapted from main/docs/guide/firewall.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally