There are too many enums to list them here, see source code for reference.
dsl
- the DSL (reference: see below)types
- contains the NixOS option types for the nftables schemastatement
- a statementcommand
- a commandruleset
- a ruleset (a JSON object containingnftables
)expression
- an expression- there's much much more, see code for details
Currently, you can only create JSON rules. Later you may be able to compile it to plain nftables.
You are expected to read this after reading the comments in the sample in README.md. Additionally, prior experience with nftables is strongly recommended.
Nftables has many "constants", where you can use a string to refer to a
specific value. I call them enums. For example, you can use "syn"
to
refer to the TCP flag syn
.
If you don't want to use strings, you can use my premade enum objects.
For example, notnft.tcpFlags.syn
refers to the syn
tcp flag. But
this is quite bulky and hard to remember. Instead, anywhere you would
use an enum, you can use a function that takes that enum! For example,
instead of doing bit.and payload.tcp.flags notnft.tcpFlags.syn
, you
can do bit.and payload.tcp.flags (f: f.syn)
.
Additionally, if you find this syntax bulky, I've implemented an
advanced feature called "One Enum to Rule Them All" (oneEnum
for
short). If you do with oneEnumToRuleThemAll;
, you can simply use
whatever constants you please, the DSL will automatically detect wrongly
used values. However, be aware that
- Some values (like
add
oricmp
orredirect
) can't be added to One Enum, because they would clash with DSL's own values. However, I got it to work anyway using powers of black magic. The black magic is disabled by default, but enabled if you dowith oneEnumToRuleThemAll;
- Specifically,
oneEnumToRuleThemAll
contains a copy of the DSL with hacks enabled (if you dowith dsl;
afterwith oneEnumToRuleThemAll;
, the hacks will be disabled, but One Enum will not work as well as it could). - I think it's fairly unlikely that those hacks will break anything, but use them at your own risk!
- Specifically,
- You will not get the exact line where you used the wrong value in error messages if you do this.
- The enum may pollute the namespace, as there really are a lot of differently named constants in nftables.
Example:
with dsl.oneEnum; bit.or payload.tcp.flags fin syn rst psh ack urg
create
- make sure something doesnt already exist and create itadd
- add something if it doesnt already existinsert
- for prepending rules to an existing chaindelete
- delete something, error if it doesn't existdestroy
- delete something if it existsflush
- clear somethingreset
- reset something's staterename
- not implemented in the DSL
Here, "objects" means whatever can be created with commands (like tables or chains).
table
- takes mandatoryfamily
and optionalcomment
attrs- You can pass an attrset with the table's contents, each key will
become the associated object's name.
- Alternatively, you can pass the table contents directly or in a
list, but then you'll have to pass
name
to each object manually.
- Alternatively, you can pass the table contents directly or in a
list, but then you'll have to pass
- All other objects either have to be part of a table, or explicitly
passed
family
(table family) andtable
(table name)
- You can pass an attrset with the table's contents, each key will
become the associated object's name.
chain
- takes optionaltype
,hook
,prio
,dev
,policy
,comment
attrs.- You can pass rules to the chain. Each rule is a list of statements.
You can pass either a list of rules (
chain [[a] [b] [c]]
), or you can repeatedly apply rules to the chain (chain [a] [b] [c]
).
- You can pass rules to the chain. Each rule is a list of statements.
You can pass either a list of rules (
set
- takestype
, and optionalpolicy
,flags
,timeout
,gc-interval
,size
attrs.- You can pass a list of expressions to the set to initialize it with some values.
map
- same as above, but also takesmap
attr (in this casetype
is key type, andmap
is value type).- If you want to initialize it with certain values, you have to pass a list of lists of size 2 (1st value is the key, 2nd is the associated value).
flowtable
,counter
,quota
,secmark
,ctHelper
,limit
,ctTimeout
,ctExpectation
,synproxy
- refer to libnftables-json documentation for more info on those.
Each rule contains one or more statements. Unless the rule is a "verdict", the next rule will be executed after the previous one.
The following statements are supported:
accept
- stop evaluation and accept the packetdrop
- stop evaluation and accept the packetcontinue
- go to the next rulereturn
- return from the current rule and continue with the next rule in the previous chainjump <CHAIN_NAME>
- "call" another chain (so it can be returned from to continue evaluating this chain)goto <CHAIN_NAME>
- "call" another chain, but don't push the current position to the call stack (so returning from that chain will return into the parent chain)is
,is.eq
,is.ne
,is.gt
,is.lt
,is.ge
,is.le
- comparison operators (implicit,==
,!=
,>
,<
,>=
,<=
). Each of those takes two expressions and compares them.counter
- use an anonymous counter to count the number of packets/bytes.counter { ... }
- pass some attrs (packets
/bytes
) to the counter. Refer to libnftables-json docs for more info.
mangle <A> <B>
- change packet data/meta info A to Bquota { ... }
- pass some attrs to quota statement (refer to libnftables-json docs)limit { ... }
- pass some attrs to limit statement (refer to libnftables-json docs)fwd { ... }
- pass some attrs to fwd statement - forward a packet to a different destination (refer to libnftables-json docs)notrack
- disable connection tracking for the packet.dup { ... }
- pass some attrs to dup statement - duplicate a packet to a different destination (refer to libnftables-json docs)snat <ip>
/snat <ip> <port>
/snat { ... }
/snat <ip> { ... }
/snat <ip> <port> { ... }
- perform source network address translation, optionally specifying ip/port, optionally specifying the rest of the attrs (refer to libnftables-json docs).- In
inet
tables you have to specify the family. You can do it by callingsnat.ip
/snat.ip6
instead ofsnat
, or alternatively you can specify a family in the attrs.
- In
dnat
- same syntax as above, but destination network address translationmasquerade <port>
/masquerade { ... }
/masquerade <port> { ... }
- perform SNAT to the outgoing interface's IP address.redirect
- same syntax, but DNAT to local host's IP address.reject
/reject { ... }
- reject (with optional attrs, see libnftables-json docs)set.add <set> <elem>
/set.update <set> <elem>
/set.delete <set> <elem>
- add/update/deleteelem
to/fromset
log { ... }
- log with attrs (see libnftables-json docs)log "..."
- log with prefix
ctHelper <expr>
- set a packet's ct helper to<expr>
meter { ... }
- see libnftables-json docsqueue { ... }
- see libnftables-json docsvmap <expr> <data>
- apply a verdict depending on<expr>
.<data>
can either be a list of lists of size 2, each being a key-value pair, or a map with keys being strings and values being verdicts.ctCount <n>
- set conntrack connection count thresholdctCount { ... }
- see nftables-json docs forct count
statement.
ctTimeout <expr>
- set a packet's ct timeout to<expr>
ctExpectation <expr>
- set a packet's ct expectation to<expr>
flow.add <name>
- select the flowtable for flow offloadingtproxy { ... }
- see libnftables-json docssynproxy { ... }
- see libnftables-json docsreset <expr>
- reset a tcp option expressionsecmark <expr>
- set a packet's secmark to<expr>
"@<set_name>"
- set reference/flowtable reference"*"
- wildcard (not sure what this is used for)[ a b c ]
- list expression (not sure what this is used for)concat <a> <b> <c>...
/concat [ <a> <b> <c> ... ]
- concat multiple values (same asa . b . c
in nftables)set [ a b c ... ]
- create an anonymous set (same as{ a, b, c }
in nftables)set [ [ a b ] [ c d ] ... ]
- create an anonymous map (same as{ a : b, c : d }
in nftables)map <expr> <mapping>
- select a value based onexpr
's value. Mapping can either be a list of lists of size 2 (each being a key-value pair), or if the keys are strings it can be an attrset.cidr <prefix> <length>
- create an IP prefix expression (e.g.127.0.0.0/8
iscidr "127.0.0.1" 8
). Alternatively,cidr "<prefix>/<length>"
works too.range a b
- a range from a to b, same as nftables'sa-b
payload.<protocol>.<field>
- access a protocol's field. It is convenient to dowith payload;
to be able to quickly access each field. Example:payload.tcp.flags
accesses TCP flags of a packet.exthdr.<header>
- reference an IPv6 extension headerexthdr.<header>.<field>
- reference an IPv6 extension header fieldtcpOpt.<name>
- reference a TCP optiontcpOpt.<name>.<field>
- reference an TCP option fieldipOpt.<name>
- reference an IP optionipOpt.<name>.<field>
- reference an IP option fieldsctpChunk.<name>
- reference an SCTP chunksctpChunk.<name>.<field>
- reference an SCTP chunk fieldmeta.<key>
- reference a packet's metadata (e.g.meta.iifname
)rt.<family>.<key>
/rt.<key>
- access routing data associated with a packet (key beingclassid
,nexthop
,mtu
,ipsec
)ct.<key>
/ct.<dir>.<key>
/ct.<dir>.<family>.<key>
- conntrack expression (see nftables man for more info)numgen.inc <mod>
/numgen.random <mod>
/numgen.inc { ... }
/numgen.random { ... }
- generate a random number (see libnftables-json docs/nftables man for more info).mod
is modulo.jhash <expr> <mod>
/jhash <expr> { ... }
- hash packet datasymhash <mod>
/symhash { ... }
- hash packetfib <flags> <result>
- query fib based onflags
, fetchingresult
bin.and
,bin.or
,bin.xor
,bin.lsh
,bin.rsh
- binary operations -&
/|
/^
/<<
/>>
. Each takes any amount of arguments (e.g.bin.or a b c d
translates to((a|b)|c)|d
).accept
/drop
/continue
/return
/jump
/goto
- same as statements, but used invmap
statement.elem { ... } <expr>
/elem <expr> { ... }
/elem { val = <expr>, ... }
- enrich<expr>
with optionaltimeout
,expires
andcomment
when adding to a set. For maps, only the key can be anelem
.socket.<key>
> - search for an associated socket and get some associated info. Keys aretransparent
,mark
,wildcard
.osf.<key>
/osf.ttl.<ttl>.<key>
/osf.<ttl>.<key>
- do operating system fingerprinting. Key isname
(OS signature name) orversion
(OS version), TTL isloose
(check fingerprint's TTL) orskip
(don't check it).ipsec.<dir>.<key>
/ipsec.<dir>.<family>.<key>
/ipsec.<dir>.<key> { spnum = ...; }
/ipsec.<dir>.<family>.<key> { spnum = ...; }
- ipsec expression with optional spnum (see nftables man).dccpOpt <type>
- create a reference to a DCCP option (type is numeric)
The DSL does some funky stuff behind the scenes, so you can't serialize
the DSL objects via builtins.toJSON
as-is, and if you want to create
an expression/statement/command via the DSL without enclosing it in
dsl.ruleset
, whether it's for passing it to the NixOS module system or
calling builtins.toJSON
, you have to make sure to get rid of that
"funkiness".
Make sure to call dsl.compile
on any expression/statement that
isn't enclosed in a table
, or on any command (e.g. add table
) that
isn't enclosed in a ruleset
.