knftables

package module
v0.0.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 16 Imported by: 31

README

knftables: a golang nftables library

This is a library for using nftables from Go.

It is not intended to support arbitrary use cases, but instead specifically focuses on supporting Kubernetes components which are using nftables in the way that nftables is supposed to be used (as opposed to using nftables in a naively-translated-from-iptables way, or using nftables to do totally valid things that aren't the sorts of things Kubernetes components are likely to need to do; see the "iptables porting" doc for more thoughts on porting old iptables-based components to nftables.)

knftables is still under development and is not yet API stable. (See the section on "Possible future changes" below.)

The library is implemented as a wrapper around the nft CLI, because the CLI API is the only well-documented interface to nftables. Although it would be possible to use netlink directly (and some other golang-based nftables libraries do this), that would result in an API that is quite different from all documented examples of nftables usage (e.g. the man pages and the nftables wiki) because there is no easy way to convert the "standard" representation of nftables rules into the netlink form.

(Actually, it's not quite true that there's no other usable API: the nft CLI is just a thin wrapper around libnftables, and it would be possible for knftables to use cgo to invoke that library instead of using an external binary. However, this would be harder to build and ship, so I'm not bothering with that for now. But this could be done in the future without needing to change knftables's API.)

knftables requires nft version 1.0.1 or later, because earlier versions would download and process the entire ruleset regardless of what you were doing, which, besides being pointlessly inefficient, means that in some cases, other people using new features in their tables could prevent you from modifying your table. (In particular, a change in how some rules are generated starting in nft 1.0.3 triggers a crash in nft 0.9.9 and earlier, even if you aren't looking at the table containing that rule.)

In general, if you are creating a container image containing nft, it is better to include an older version of nft than a newer one, because newer versions may create rules, sets, etc., that older ones can't understand (and in some cases, newer versions of nft may even cause older versions to crash). If your container uses an older version of nft than the host uses, then it's guaranteed to not cause problems if the admin runs nft list ruleset or the like. (As of v0.0.20, knftables should never look at any tables other than the one(s) it is managing, so having an older version of nft in your container than is on the host should not cause any problems for knftables.)

Usage

Create an Interface object to manage operations on a single nftables table:

nft, err := knftables.New(knftables.IPv4Family, "my-table")
if err != nil {
        return fmt.Errorf("no nftables support: %v", err)
}

knftables.New also takes a comma-separated list of options after the family and table name; see the documentation for that function for more information.

(If you want to operate on multiple tables or multiple nftables families, you have two options: you can either create separate Interface objects for each table, or you can create a single Interface and pass "" for the family and table. In that case, you will need to explicitly fill in the Family and Table fields of every Chain, Rule, etc, object you create.)

You can use the various List* methods on the Interface to check if objects exist. ListAll returns a map of the names of top-level objects in the table, sorted by object type, while List returns just the names of objects of a single type. ListElements, ListRules, and ListCounters returned parsed objects of the given types. Note that ListRules returns partial Rule objects; it does not fill in the Rule field.

allChains, err := nft.List(ctx, "chains")
if err != nil {
        return fmt.Errorf("could not list chains: %v", err)
}
for chain := range sets.New(allChains...).Difference(expectedChains) {
        tx.Delete(&knftables.Chain{Name: chain})
}

// ...

elements, err := nft.ListElements(ctx, "map", "mymap")
if err != nil {
        return fmt.Errorf("could not list map elements: %v", err)
}

...

To make changes, create a Transaction, add the appropriate operations to the transaction, and then call nft.Run on it:

tx := nft.NewTransaction()

tx.Add(&knftables.Chain{
        Name:    "mychain",
        Comment: knftables.PtrTo("this is my chain"),
})
tx.Flush(&knftables.Chain{
        Name: "mychain",
})

var destIP net.IP
var destPort uint16
...
tx.Add(&knftables.Rule{
        Chain: "mychain",
        Rule: knftables.Concat(
                "ip daddr", destIP,
                "ip protocol", "tcp",
                "th port", destPort,
                "jump", destChain,
        )
})

err := nft.Run(context, tx)

If any operation in the transaction would fail, then Run() will return an error and the entire transaction will be ignored. You can use the knftables.IsNotFound() and knftables.IsAlreadyExists() methods to check for those well-known error types. In a large transaction, there is no supported way to determine exactly which operation failed.

(You can also pass a transaction to nft.Check(), which uses nft --check, but otherwise behaves the same as nft.Run().)

knftables.Transaction operations

knftables.Transaction operations correspond to the top-level commands in the nft binary. Currently-supported operations are:

  • tx.Add(): creates an object if it does not already exist, as with nft add
  • tx.Create(): creates an object, which must not already exist, as with nft create
  • tx.Flush(): flushes the contents of a table/chain/set/map, as with nft flush
  • tx.Reset(): resets a counter, as with nft reset
  • tx.Delete(): deletes an object, which must exist, as with nft delete
  • tx.Destroy(): deletes an object if it exists, as with nft destroy

For Rule objects the semantics and operations are slightly different:

  • tx.Add(): appends a rule to a chain or adds it after an existing rule, as with nft add rule
  • tx.Insert(): prepends a rule to a chain or inserts it before another rule, as with nft insert rule
  • tx.Replace(): replaces a rule, as with nft replace rule
  • tx.Delete()/tx.Destroy(): deletes the rule with the given Handle, as with nft delete rule/nft destroy rule
Destroy operations

Actually doing nft destroy requires a fairly new kernel (6.3 or later) and nft binary (1.0.8 or later). Trying to run a transaction containing a Destroy operation on an older host will result in an error.

There are two construct-time options to help out with this. First, you can specify RequireDestroy, if you want knftables construction to fail on older hosts:

nft, err := knftables.New(knftables.IPv4Family, "my-table", knftables.RequireDestroy)
if err != nil {
        ...

Alternatively, you can construct the Interface with the EmulateDestroy option:

nft, err := knftables.New(knftables.IPv4Family, "my-table", knftables.EmulateDestroy)

in which case knftables will attempt to emulate nft destroy if it is not available by doing a combination of an add and a delete (where the add will succeed whether the object previously existed or not, and then the delete will succeed because the object definitely exists at that point). To ensure that this emulation will work, if EmulateDestroy is in effect then tx.Destroy() will require that you pass it an object that is suitable for passing to both tx.Add() and tx.Delete() (even if the system you are currently on supports nft destroy). In particular, this means that when EmulateDestroy is in effect:

  • You can only Destroy() objects by Name or Key, not by Handle.

  • You can't Destroy() a Rule (since Rules can only be deleted by Handle).

  • If you include optional fields in the object (e.g. base chain properties), they need to be correct (since an Add() would fail if you passed different values). However, note that you can just leave the optional fields unset.

  • When Destroy()ing a Set or Map you must include the correct Type (since an Add() would fail if you did not specify it or specified it incorrectly).

  • When Destroy()ing a Map Element you must include the correct Value (since an Add() would fail if you did not specify it or specified it incorrectly).

Objects

The Transaction methods take arguments of type knftables.Object. The currently-supported objects are:

  • Table
  • Flowtable
  • Chain
  • Rule
  • Set
  • Map
  • Element
  • Counter

Optional fields in objects can be filled in with the help of the PtrTo() function, which just returns a pointer to its argument.

Concat() can be used to concatenate a series of strings, []string arrays, and other arguments (including numbers, net.IPs / net.IPNets, and anything else that can be formatted usefully via fmt.Sprintf("%s")) together into a single string. This is often useful when constructing Rules.

knftables.Fake

There is a fake (in-memory) implementation of knftables.Interface for use in unit tests. Use knftables.NewFake() instead of knftables.New() to create it, and then it should work mostly the same. See fake.go for more details of the public APIs for examining the current state of the fake nftables database.

Missing APIs

Various top-level object types are not yet supported.

Most IPTables libraries have an API for "add this rule only if it doesn't already exist", but that does not seem as useful in nftables (or at least "in nftables as used by Kubernetes-ish components that aren't just blindly copying over old iptables APIs"), because chains tend to have static rules and dynamic sets/maps, rather than having dynamic rules. If you aren't sure if a chain has the correct rules, you can just Flush it and recreate all of the rules.

ListRules returns Rule objects without the Rule field filled in, because it uses the JSON API to list the rules, but there is no easy way to convert the JSON rule representation back into plaintext form. This means that it is only useful when either (a) you know the order of the rules in the chain, but want to know their handles, or (b) you can recognize the rules you are looking for by their comments, rather than the rule bodies.

Possible future changes

nft output parsing

nft's output is documented and standardized, so it ought to be possible for us to extract better error messages in the event of a transaction failure.

Additionally, if we used the --echo (-e) and --handle (-a) flags, we could learn the handles associated with newly-created objects in a transaction, and return these to the caller somehow. (E.g., by setting the Handle field in the object that had been passed to tx.Add when the transaction is run.)

(For now, ListRules fills in the handles of the rules it returns, so it's possible to find out a rule's handle after the fact that way. For other supported object types, either handles don't exist (Element) or you don't really need to know their handles because it's possible to delete by name instead (Table, Chain, Set, Map).)

List APIs

The fact that List works completely differently from ListRules and ListElements is a historical artifact.

I would like to have a single function

List[T Object](ctx context.Context, template T) ([]T, error)

So you could say

elements, err := nft.List(ctx, &knftables.Element{Set: "myset"})

to list the elements of "myset". But this doesn't actually compile ("syntax error: method must have no type parameters") because allowing that would apparently introduce extremely complicated edge cases in Go generics.

Set/map type representation

There is currently an annoying asymmetry in the representation of concatenated types between Set/Map and Element, where the former uses a string containing nft syntax, and the latter uses an array:

tx.Add(&knftables.Set{
        Name: "firewall",
        Type: "ipv4_addr . inet_proto . inet_service",
})
tx.Add(&knftables.Element{
        Set: "firewall",
        Key: []string{"10.1.2.3", "tcp", "80"},
})

This will probably be fixed at some point, which may result in a change to how the type vs typeof distinction is handled as well.

Optimization and rule representation

We will need to optimize the performance of large transactions. One change that is likely is to avoid pre-concatenating rule elements in cases like:

tx.Add(&knftables.Rule{
        Chain: "mychain",
        Rule: knftables.Concat(
                "ip daddr", destIP,
                "ip protocol", "tcp",
                "th port", destPort,
                "jump", destChain,
        )
})

This will presumably require a change to knftables.Rule and/or knftables.Concat() but I'm not sure exactly what it will be.

Community, discussion, contribution, and support

knftables is maintained by Kubernetes SIG Network.

See CONTRIBUTING.md for more information about contributing. Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.

Documentation

Index

Constants

View Source
const (
	// Maximum length of a table, chain, set, etc, name
	NameLengthMax = 256

	// Maximum length of a comment
	CommentLengthMax = 128
)

Variables

This section is empty.

Functions

func Concat

func Concat(args ...interface{}) string

Concat is a helper (primarily) for constructing Rule objects. It takes a series of arguments and concatenates them together into a single string with spaces between the arguments. Strings are output as-is, string arrays are output element by element, numbers are output as with `fmt.Sprintf("%d")`, and all other types are output as with `fmt.Sprintf("%s")`. To help with set/map lookup syntax, an argument of "@" will not be followed by a space, so you can do, eg, `Concat("ip saddr", "@", setName)`.

func IsAlreadyExists

func IsAlreadyExists(err error) bool

IsAlreadyExists tests if err corresponds to an nftables "already exists" error (e.g. when doing a "create" rather than an "add").

func IsNotFound

func IsNotFound(err error) bool

IsNotFound tests if err corresponds to an nftables "not found" error of any sort. (e.g., in response to a "delete rule" command, this might indicate that the rule doesn't exist, or the chain doesn't exist, or the table doesn't exist.)

func ParsePriority

func ParsePriority(family Family, priority string) (int, error)

ParsePriority tries to convert the string form of a chain priority into a number

func PtrTo

func PtrTo[T any](val T) *T

PtrTo can be used to fill in optional field values in objects

Types

type BaseChainHook

type BaseChainHook string

BaseChainHook represents the "hook" that a base chain is attached to. See https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_hooks and https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

const (
	// PreroutingHook is the "prerouting" stage of packet processing, which is the
	// first stage (after "ingress") for inbound ("input path" and "forward path")
	// packets.
	PreroutingHook BaseChainHook = "prerouting"

	// InputHook is the "input" stage of packet processing, which happens after
	// "prerouting" for inbound packets being delivered to an interface on this host,
	// in this network namespace.
	InputHook BaseChainHook = "input"

	// ForwardHook is the "forward" stage of packet processing, which happens after
	// "prerouting" for inbound packets destined for a non-local IP (i.e. on another
	// host or in another network namespace)
	ForwardHook BaseChainHook = "forward"

	// OutputHook is the "output" stage of packet processing, which is the first stage
	// for outbound packets, regardless of their final destination.
	OutputHook BaseChainHook = "output"

	// PostroutingHook is the "postrouting" stage of packet processing, which is the
	// final stage (before "egress") for outbound ("forward path" and "output path")
	// packets.
	PostroutingHook BaseChainHook = "postrouting"

	// IngressHook is the "ingress" stage of packet processing, in the "netdev" family
	// or (with kernel >= 5.10 and nft >= 0.9.7) the "inet" family.
	IngressHook BaseChainHook = "ingress"

	// EgressHook is the "egress" stage of packet processing, in the "netdev" family
	// (with kernel >= 5.16 and nft >= 1.0.1).
	EgressHook BaseChainHook = "egress"
)

type BaseChainPolicy added in v0.0.19

type BaseChainPolicy string

BaseChainPolicy sets what happens to packets not explicitly accepted or refused by a base chain.

const (
	// AcceptPolicy, which is the default, accepts any unmatched packets (though,
	// as with any other nftables chain, a later chain can drop or reject it).
	AcceptPolicy BaseChainPolicy = "accept"

	// DropPolicy drops any unmatched packets.
	DropPolicy BaseChainPolicy = "drop"
)

type BaseChainPriority

type BaseChainPriority string

BaseChainPriority represents the "priority" of a base chain. Lower values run earlier. See https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_priority and https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks#Priority_within_hook

In addition to the const values, you can also use a signed integer value, or an arithmetic expression consisting of a const value followed by "+" or "-" and an integer.

const (
	// RawPriority is the earliest named priority. In particular, it can be used for
	// rules that need to run before conntrack. It is equivalent to the value -300 and
	// can be used in the ip, ip6, and inet families.
	RawPriority BaseChainPriority = "raw"

	// ManglePriority is the standard priority for packet-rewriting operations. It is
	// equivalent to the value -150 and can be used in the ip, ip6, and inet families.
	ManglePriority BaseChainPriority = "mangle"

	// DNATPriority is the standard priority for DNAT operations. In the ip, ip6, and
	// inet families, it is equivalent to the value -100. In the bridge family it is
	// equivalent to the value -300. In both cases it can only be used from the
	// prerouting hook.
	DNATPriority BaseChainPriority = "dstnat"

	// FilterPriority is the standard priority for filtering operations. In the ip,
	// ip6, inet, arp, and netdev families, it is equivalent to the value 0. In the
	// bridge family it is equivalent to the value -200.
	FilterPriority BaseChainPriority = "filter"

	// OutPriority is FIXME. It is equivalent to the value 300 and can only be used in
	// the bridge family.
	OutPriority BaseChainPriority = "out"

	// SecurityPriority is the standard priority for security operations ("where
	// secmark can be set for example"). It is equivalent to the value 50 and can be
	// used in the ip, ip6, and inet families.
	SecurityPriority BaseChainPriority = "security"

	// SNATPriority is the standard priority for SNAT operations. In the ip, ip6, and
	// inet families, it is equivalent to the value 100. In the bridge family it is
	// equivalent to the value 300. In both cases it can only be used from the
	// postrouting hook.
	SNATPriority BaseChainPriority = "srcnat"
)

type BaseChainType

type BaseChainType string

BaseChainType represents the "type" of a "base chain" (ie, a chain that is attached to a hook). See https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types

const (
	// FilterType is the chain type for basic packet filtering.
	FilterType BaseChainType = "filter"

	// NATType is the chain type for doing DNAT, SNAT, and masquerading.
	// NAT operations are only available from certain hooks.
	NATType BaseChainType = "nat"

	// RouteType is the chain type for rules that change the routing of packets.
	// Chains of this type can only be added to the "output" hook.
	RouteType BaseChainType = "route"
)

type Chain

type Chain struct {
	// Family is the nftables family of the chain's table. You do not normally need to
	// fill this in because it will be filled in for you automatically from the
	// Interface.
	Family Family

	// Table is the name of the chain's table. You do not normally need to fill this
	// in because it will be filled in for you automatically from the Interface.
	Table string

	// Name is the name of the chain.
	Name string

	// Type is the chain type; this must be set for a base chain and unset for a
	// regular chain.
	Type *BaseChainType
	// Hook is the hook that the chain is connected to; this must be set for a base
	// chain and unset for a regular chain.
	Hook *BaseChainHook
	// Priority is the chain priority; this must be set for a base chain and unset for
	// a regular chain. You can call ParsePriority() to convert this to a number.
	Priority *BaseChainPriority

	// Policy is the policy for packets not explicitly accepted or refused by a base
	// chain.
	Policy *BaseChainPolicy

	// Device is the network interface that the chain is attached to; this must be set
	// for a base chain connected to the "ingress" or "egress" hooks, and unset for
	// all other chains.
	Device *string

	// Comment is an optional comment for the object.  (Requires kernel >= 5.10 and
	// nft >= 0.9.7; otherwise this field will be silently ignored. Requires
	// nft >= 1.0.8 to include comments in List() results.)
	Comment *string

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil
	Handle *int
}

Chain represents an nftables chain; either a "base chain" (if Type, Hook, and Priority are specified), or a "regular chain" (if they are not).

type Counter added in v0.0.19

type Counter struct {
	// Family is the nftables family of the counter's table. You do not normally
	// need to fill this in because it will be filled in for you automatically from
	// the Interface.
	Family Family

	// Table is the name of the counter's table. You do not normally need to fill
	// this in because it will be filled in for you automatically from the Interface.
	Table string

	// Name is the name of the named counter
	Name string

	// Comment is an optional comment for the counter
	Comment *string

	// Packets represents numbers of packets tracked by the counter.
	// This will be filled in by ListCounters() but can be nil when creating new counter.
	Packets *uint64

	// Bytes represents numbers of bytes tracked by the counter.
	// This will be filled in by ListCounters() but can be nil when creating new counter.
	Bytes *uint64

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil
	Handle *int
}

Counter represents named counter

type Element

type Element struct {
	// Family is the nftables family of the element's table. You do not normally need
	// to fill this in because it will be filled in for you automatically from the
	// Interface.
	Family Family

	// Table is the name of the element's table. You do not normally need to fill this
	// in because it will be filled in for you automatically from the Interface.
	Table string

	// Set is the name of the set that contains this element (or the empty string if
	// this is a map element.)
	Set string

	// Map is the name of the map that contains this element (or the empty string if
	// this is a set element.)
	Map string

	// Key is the element key. (The list contains a single element for "simple" keys,
	// or multiple elements for concatenations.)
	Key []string

	// Value is the map element value. As with Key, this may be a single value or
	// multiple. For set elements, this must be nil.
	Value []string

	// Comment is an optional comment for the element
	Comment *string
}

Element represents a set or map element

type Fake

type Fake struct {

	// mutex is used to protect Table/Tables and LastTransaction.
	// When Table/Tables and LastTransaction are accessed directly, the caller must
	// acquire Fake.RLock and release when finished.
	sync.RWMutex

	// Table contains the Interface's table (assuming the Fake has a default table).
	// This will be `nil` until you `tx.Add()` the table.
	// Make sure to acquire Fake.RLock before accessing Table in a concurrent environment.
	Table *FakeTable

	// Tables contains all tables known to Fake. This will be empty until you
	// `tx.Add()` a table.
	// Make sure to acquire Fake.RLock before accessing Tables in a concurrent environment.
	Tables map[Family]map[string]*FakeTable

	// LastTransaction is the last transaction passed to Run(). It will remain set until the
	// next time Run() is called. (It is not affected by Check().)
	// Make sure to acquire Fake.RLock before accessing LastTransaction in a
	// concurrent environment.
	LastTransaction *Transaction
	// contains filtered or unexported fields
}

Fake is a fake implementation of Interface

func NewFake

func NewFake(family Family, table string) *Fake

NewFake creates a new fake Interface, for unit tests

func (*Fake) Check

func (fake *Fake) Check(_ context.Context, tx *Transaction) error

Check is part of Interface

func (*Fake) Dump

func (fake *Fake) Dump() string

Dump dumps the current contents of fake, in a way that looks like an nft transaction.

func (*Fake) List

func (fake *Fake) List(_ context.Context, objectType string) ([]string, error)

List is part of Interface.

func (*Fake) ListAll added in v0.0.20

func (fake *Fake) ListAll(_ context.Context) (map[string][]string, error)

ListAll is part of Interface.

func (*Fake) ListCounters added in v0.0.19

func (fake *Fake) ListCounters(_ context.Context) ([]*Counter, error)

ListCounters is part of Interface

func (*Fake) ListElements

func (fake *Fake) ListElements(_ context.Context, objectType, name string) ([]*Element, error)

ListElements is part of Interface

func (*Fake) ListRules

func (fake *Fake) ListRules(_ context.Context, chain string) ([]*Rule, error)

ListRules is part of Interface

func (*Fake) NewTransaction

func (fake *Fake) NewTransaction() *Transaction

NewTransaction is part of Interface

func (*Fake) ParseDump added in v0.0.15

func (fake *Fake) ParseDump(data string) (err error)

ParseDump can parse a dump for a given nft instance. It expects fake's table name and family in all rules. The best way to verify that everything important was properly parsed is to compare given data with nft.Dump() output.

func (*Fake) Run

func (fake *Fake) Run(_ context.Context, tx *Transaction) error

Run is part of Interface

type FakeChain

type FakeChain struct {
	Chain

	// Rules contains the chain's rules, in order
	Rules []*Rule
}

FakeChain wraps Chain for the Fake implementation

type FakeCounter added in v0.0.19

type FakeCounter struct {
	Counter
}

FakeCounter wraps Counter for the Fake implementation

type FakeFlowtable added in v0.0.18

type FakeFlowtable struct {
	Flowtable
}

FakeFlowtable wraps Flowtable for the Fake implementation

type FakeMap

type FakeMap struct {
	Map

	// Elements contains the map's elements. You can also use the FakeMap's
	// FindElement() method to see if a particular element is present.
	Elements []*Element
}

FakeMap wraps Set for the Fake implementation

func (*FakeMap) FindElement

func (m *FakeMap) FindElement(key ...string) *Element

FindElement finds an element of the map with the given key. If there is no matching element, it returns nil.

type FakeSet

type FakeSet struct {
	Set

	// Elements contains the set's elements. You can also use the FakeSet's
	// FindElement() method to see if a particular element is present.
	Elements []*Element
}

FakeSet wraps Set for the Fake implementation

func (*FakeSet) FindElement

func (s *FakeSet) FindElement(key ...string) *Element

FindElement finds an element of the set with the given key. If there is no matching element, it returns nil.

type FakeTable

type FakeTable struct {
	Table

	// Flowtables contains the table's flowtables, keyed by name
	Flowtables map[string]*FakeFlowtable

	// Chains contains the table's chains, keyed by name
	Chains map[string]*FakeChain

	// Sets contains the table's sets, keyed by name
	Sets map[string]*FakeSet

	// Maps contains the table's maps, keyed by name
	Maps map[string]*FakeMap

	// Counters contains the table's counters, keyed by name
	Counters map[string]*FakeCounter
}

FakeTable wraps Table for the Fake implementation

type Family

type Family string

Family is an nftables family

const (
	// IPv4Family represents the "ip" nftables family, for IPv4 rules.
	IPv4Family Family = "ip"

	// IPv6Family represents the "ip6" nftables family, for IPv6 rules.
	IPv6Family Family = "ip6"

	// InetFamily represents the "inet" nftables family, for mixed IPv4 and IPv6 rules.
	InetFamily Family = "inet"

	// ARPFamily represents the "arp" nftables family, for ARP rules.
	ARPFamily Family = "arp"

	// BridgeFamily represents the "bridge" nftables family, for rules operating
	// on packets traversing a bridge.
	BridgeFamily Family = "bridge"

	// NetDevFamily represents the "netdev" nftables family, for rules operating on
	// the device ingress/egress path.
	NetDevFamily Family = "netdev"
)

type Flowtable added in v0.0.18

type Flowtable struct {
	// Family is the nftables family of the flowtable's table. You do not normally
	// need to fill this in because it will be filled in for you automatically from
	// the Interface.
	Family Family

	// Table is the name of the flowtable's table. You do not normally need to fill
	// this in because it will be filled in for you automatically from the Interface.
	Table string

	// Name is the name of the flowtable.
	Name string

	// The Priority can be a signed integer or FlowtableIngressPriority which stands for 0.
	// Addition and subtraction can be used to set relative priority, e.g. filter + 5 equals to 5.
	Priority *FlowtableIngressPriority

	// The Devices are specified as iifname(s) of the input interface(s) of the traffic
	// that should be offloaded.
	Devices []string

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil
	Handle *int
}

Flowtable represents an nftables flowtable. https://wiki.nftables.org/wiki-nftables/index.php/Flowtables

type FlowtableIngressPriority added in v0.0.18

type FlowtableIngressPriority string
const (
	// FilterIngressPriority is the priority for the filter value in the Ingress hook
	// that stands for 0.
	FilterIngressPriority FlowtableIngressPriority = "filter"
)

type Interface

type Interface interface {
	// NewTransaction returns a new (empty) Transaction
	NewTransaction() *Transaction

	// Run runs a Transaction and returns the result. The IsNotFound and
	// IsAlreadyExists methods can be used to test the result.
	Run(ctx context.Context, tx *Transaction) error

	// Check does a dry-run of a Transaction (as with `nft --check`) and returns the
	// result. The IsNotFound and IsAlreadyExists methods can be used to test the
	// result.
	Check(ctx context.Context, tx *Transaction) error

	// ListAll returns a map containing the names of all objects in the table,
	// grouped by object type. If there are no objects, this will return an empty list
	// and no error.
	ListAll(ctx context.Context) (map[string][]string, error)

	// List returns a list of the names of the objects of objectType ("chain", "set",
	// "map", "counter", or "flowtable" in the table. If there are no such objects,
	// this will return an empty list and no error.
	List(ctx context.Context, objectType string) ([]string, error)

	// ListRules returns a list of the rules in a chain, in order. If no chain name is
	// specified, then all rules within the table will be returned. Note that at the
	// present time, the Rule objects will have their `Comment` and `Handle` fields
	// filled in, but *not* the actual `Rule` field. So this can only be used to find
	// the handles of rules if they have unique comments to recognize them by, or if
	// you know the order of the rules within the chain. If the chain exists but
	// contains no rules, this will return an empty list and no error.
	ListRules(ctx context.Context, chain string) ([]*Rule, error)

	// ListElements returns a list of the elements in a set or map. (objectType should
	// be "set" or "map".) If the set/map exists but contains no elements, this will
	// return an empty list and no error.
	ListElements(ctx context.Context, objectType, name string) ([]*Element, error)

	// ListCounters returns a list of the counters in the table.
	ListCounters(ctx context.Context) ([]*Counter, error)
}

Interface is an interface for running nftables commands against a given family and table.

func New

func New(family Family, table string, options ...Option) (Interface, error)

New creates a new nftables.Interface. If nftables is not available/usable on the current host, it will return an error.

Normally, family and table will specify the family and table to use for all operations on the returned Interface. However, if you leave them empty (`""`), then the Interface will have no associated family/table and (a) you must explicitly fill in those fields in any objects you use in a Transaction, (b) you can't use any of the List* methods.

In addition to the family and table, you can specify additional comma-separated options to New(). The currently-supported options are:

  • NoObjectCommentEmulation: disables the default knftables.Interface behavior of ignoring comments on Table, Chain, Set, and Map objects if the underlying CLI or kernel does not support them.

  • RequireDestroy: require the system to support `nft destroy`; the New() call will fail with an error on older systems.

  • EmulateDestroy: adjust the API of `tx.Destroy()` to make it possible to emulate via `nft add` and `nft delete` on systems that do not have `nft destroy`; see the docs for `tx.Destroy()` for more details.

  • UseNetlink: use the experimental netlink version of the List* methods rather than using `nft list`.

type Map

type Map struct {
	// Family is the nftables family of the map's table. You do not normally need to
	// fill this in because it will be filled in for you automatically from the
	// Interface.
	Family Family

	// Table is the name of the map's table. You do not normally need to fill this
	// in because it will be filled in for you automatically from the Interface.
	Table string

	// Name is the name of the map.
	Name string

	// Type is the type of the map key and value (eg "ipv4_addr : verdict"). Either
	// Type or TypeOf, but not both, must be non-empty.
	Type string

	// TypeOf is the type of the set key as an nftables expression (eg "ip saddr : verdict").
	// Either Type or TypeOf, but not both, must be non-empty. (Requires at least nft 0.9.4,
	// and newer than that for some types.)
	TypeOf string

	// Flags are the map flags
	Flags []SetFlag

	// Timeout is the time that an element will stay in the set before being removed.
	// (Optional; mandatory for sets that will be added to from the packet path)
	Timeout *time.Duration

	// GCInterval is the interval at which timed-out elements will be removed from the
	// set. (Optional; FIXME DEFAULT)
	GCInterval *time.Duration

	// Size if the maximum numer of elements in the set.
	// (Optional; mandatory for sets that will be added to from the packet path)
	Size *uint64

	// Policy is the FIXME
	Policy *SetPolicy

	// Comment is an optional comment for the object.  (Requires kernel >= 5.10 and
	// nft >= 0.9.7; otherwise this field will be silently ignored.)
	Comment *string

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil
	Handle *int
}

Map represents the definition of an nftables map (but not its elements)

type Object

type Object interface {
	// contains filtered or unexported methods
}

Object is the interface for an nftables object. All of the concrete object types implement this interface.

type Option added in v0.0.19

type Option string

Option is an optional nftables feature that an Interface might or might not support

const (
	// NoObjectCommentEmulation turns off the default knftables.Interface behavior of
	// ignoring comments on Table, Chain, Set, and Map objects if the underlying CLI
	// or kernel does not support them. (The only real reason to specify this is if
	// you want to avoid doing any "nft check" calls at construction time.)
	NoObjectCommentEmulation Option = "NoObjectCommentEmulation"

	// RequireDestroy tells knftables.New to fail if the `nft destroy` command is not
	// available.
	RequireDestroy Option = "RequireDestroy"

	// EmulateDestroy tells the Interface to emulate the `nft destroy` command if it
	// is not available. If you pass this option, then that will restrict the ways
	// that you can use the `tx.Destroy()` method to be compatible with destroy
	// emulation; see the docs for that method for more details.
	EmulateDestroy Option = "EmulateDestroy"

	// UseNetlink turns on the experimental netlink support for List* commands.
	UseNetlink Option = "UseNetlink"
)

type Rule

type Rule struct {
	// Family is the nftables family of the rule's table. You do not normally need to
	// fill this in because it will be filled in for you automatically from the
	// Interface.
	Family Family

	// Table is the name of the rule's table. You do not normally need to fill this
	// in because it will be filled in for you automatically from the Interface.
	Table string

	// Chain is the name of the chain that contains this rule
	Chain string

	// Rule is the rule in standard nftables syntax. (Should be empty on Delete, but
	// is ignored if not.) Note that this does not include any rule comment, which is
	// separate from the rule itself.
	Rule string

	// Comment is an optional comment for the rule.
	Comment *string

	// Index is the number of a rule (counting from 0) to Add this Rule after or
	// Insert it before. Cannot be specified along with Handle. If neither Index
	// nor Handle is specified then Add appends the rule the end of the chain and
	// Insert prepends it to the beginning.
	Index *int

	// Handle is a rule handle. In Add or Insert, if set, this is the handle of
	// existing rule to put the new rule after/before. In Delete or Replace, this
	// indicates the existing rule to delete/replace, and is mandatory. In the result
	// of a List, this will indicate the rule's handle that can then be used in a
	// later operation.
	Handle *int
}

Rule represents a rule in a chain

type Set

type Set struct {
	// Family is the nftables family of the set's table. You do not normally need to
	// fill this in because it will be filled in for you automatically from the
	// Interface.
	Family Family

	// Table is the name of the set's table. You do not normally need to fill this
	// in because it will be filled in for you automatically from the Interface.
	Table string

	// Name is the name of the set.
	Name string

	// Type is the type of the set key (eg "ipv4_addr"). Either Type or TypeOf, but
	// not both, must be non-empty.
	Type string

	// TypeOf is the type of the set key as an nftables expression (eg "ip saddr").
	// Either Type or TypeOf, but not both, must be non-empty. (Requires at least nft
	// 0.9.4, and newer than that for some types.)
	TypeOf string

	// Flags are the set flags
	Flags []SetFlag

	// Timeout is the time that an element will stay in the set before being removed.
	// (Optional; mandatory for sets that will be added to from the packet path)
	Timeout *time.Duration

	// GCInterval is the interval at which timed-out elements will be removed from the
	// set. (Optional; FIXME DEFAULT)
	GCInterval *time.Duration

	// Size if the maximum numer of elements in the set.
	// (Optional; mandatory for sets that will be added to from the packet path)
	Size *uint64

	// Policy is the FIXME
	Policy *SetPolicy

	// AutoMerge indicates that adjacent/overlapping set elements should be merged
	// together (only for interval sets)
	AutoMerge *bool

	// Comment is an optional comment for the object.  (Requires kernel >= 5.10 and
	// nft >= 0.9.7; otherwise this field will be silently ignored.)
	Comment *string

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil
	Handle *int
}

Set represents the definition of an nftables set (but not its elements)

type SetFlag

type SetFlag string

SetFlag represents a set or map flag

const (
	// ConstantFlag is a flag indicating that the set/map is constant. FIXME UNDOCUMENTED
	ConstantFlag SetFlag = "constant"

	// DynamicFlag is a flag indicating that the set contains stateful objects
	// (counters, quotas, or limits) that will be dynamically updated.
	DynamicFlag SetFlag = "dynamic"

	// IntervalFlag is a flag indicating that the set contains either CIDR elements or
	// IP ranges.
	IntervalFlag SetFlag = "interval"

	// TimeoutFlag is a flag indicating that the set/map has a timeout after which
	// dynamically added elements will be removed. (It is set automatically if the
	// set/map has a Timeout.)
	TimeoutFlag SetFlag = "timeout"
)

type SetPolicy

type SetPolicy string

SetPolicy represents a set or map storage policy

const (
	// PolicyPerformance FIXME
	PerformancePolicy SetPolicy = "performance"

	// PolicyMemory FIXME
	MemoryPolicy SetPolicy = "memory"
)

type Table

type Table struct {
	// Family is the nftables family of the table. You do not normally need to fill
	// this in because it will be filled in for you automatically from the Interface.
	Family Family

	// Name is the name of the table. You do not normally need to fill this in
	// because it will be filled in for you automatically from the Interface.
	Name string

	// Comment is an optional comment for the table. (Requires kernel >= 5.10 and
	// nft >= 0.9.7; otherwise this field will be silently ignored. Requires
	// nft >= 1.0.8 to include comments in List() results.)
	Comment *string

	// Flags are the table flags
	Flags []TableFlag

	// Handle is an identifier that can be used to uniquely identify an object when
	// deleting it. When adding a new object, this must be nil.
	Handle *int
}

Table represents an nftables table.

type TableFlag added in v0.0.19

type TableFlag string

TableFlag represents a table flag

const (
	// DormantFlag indicates that a table is not currently evaluated. (Its base chains
	// are unregistered.)
	DormantFlag TableFlag = "dormant"
)

type Transaction

type Transaction struct {
	// contains filtered or unexported fields
}

Transaction represents an nftables transaction

func (*Transaction) Add

func (tx *Transaction) Add(obj Object)

Add adds an "nft add" operation to tx, ensuring that obj exists by creating it if it did not already exist. (If obj is a Rule, it will be appended to the end of its chain, or else added after the Rule indicated by this rule's Index or Handle.) The Add() call always succeeds, but if obj is invalid, or inconsistent with the existing nftables state, then an error will be returned when the transaction is Run.

func (*Transaction) Create

func (tx *Transaction) Create(obj Object)

Create adds an "nft create" operation to tx, creating obj, which must not already exist. (If obj is a Rule, it will be appended to the end of its chain, or else added after the Rule indicated by this rule's Index or Handle.) The Create() call always succeeds, but if obj is invalid, already exists, or is inconsistent with the existing nftables state, then an error will be returned when the transaction is Run.

func (*Transaction) Delete

func (tx *Transaction) Delete(obj Object)

Delete adds an "nft delete" operation to tx, deleting obj, which must exist. The Delete() call always succeeds, but if obj does not exist or cannot be deleted based on the information provided (eg, Handle is required but not set) then an error will be returned when the transaction is Run.

func (*Transaction) Destroy added in v0.0.19

func (tx *Transaction) Destroy(obj Object)

Destroy adds an "nft destroy" operation to tx, ensuring that obj does not exist, by deleting it if it does exist. The Destroy() call always succeeds, but if obj cannot be deleted based on the information provided (eg, Handle is required but not set) then an error will be returned when the transaction is Run.

Support for the actual "nft destroy" command requires kernel 6.3+ and nft 1.0.7+. You can create the Interface with the `RequireDestroy` option if you want construction to fail on older hosts. Alternatively, you can create the interface with the `EmulateDestroy` option, in which case knftables will emulate Destroy by doing an Add+Delete. In that case, obj must be valid for both an Add and a Delete. (Even if the system you are on supports destroy, you may only call Destroy() in a backward-compatible way if you are using `EmulateDestroy`.) In particular, this means:

  • You can only Destroy() objects by Name or Key, not by Handle.
  • You can't Destroy() a Rule (since they can only be deleted by Handle).
  • You do not need to include optional values in obj (e.g. base chain properties) but if you do include them, they need to be correct.
  • When Destroy()ing a Set or Map you must include the correct Type.
  • When Destroy()ing a Map Element you must include the correct Value.

func (*Transaction) Flush

func (tx *Transaction) Flush(obj Object)

Flush adds an "nft flush" operation to tx, clearing the contents of obj. The Flush() call always succeeds, but if obj does not exist (or does not support flushing) then an error will be returned when the transaction is Run.

func (*Transaction) Insert

func (tx *Transaction) Insert(obj Object)

Insert adds an "nft insert" operation to tx, inserting obj (which must be a Rule) at the start of its chain, or before the other Rule indicated by this rule's Index or Handle. The Insert() call always succeeds, but if obj is invalid or is inconsistent with the existing nftables state, then an error will be returned when the transaction is Run.

func (*Transaction) NumOperations added in v0.0.17

func (tx *Transaction) NumOperations() int

NumOperations returns the number of operations queued in the transaction.

func (*Transaction) Replace

func (tx *Transaction) Replace(obj Object)

Replace adds an "nft replace" operation to tx, replacing an existing rule with obj (which must be a Rule). The Replace() call always succeeds, but if obj is invalid, does not contain the Handle of an existing rule, or is inconsistent with the existing nftables state, then an error will be returned when the transaction is Run.

func (*Transaction) Reset added in v0.0.19

func (tx *Transaction) Reset(obj Object)

Reset adds a "nft reset" operation to tx, resetting obj (which must be a Counter). The Reset() call always succeeds, but if obj does not exist then an error will be returned when the transaction is Run.

func (*Transaction) String

func (tx *Transaction) String() string

String returns the transaction as a string containing the nft commands; if there is a pending error, it will be output as a comment at the end of the transaction.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL