Symbolic variables in use by the nft
userspace command are resolved into their values only by this command. The nft
command resolves the variable into its assigned value to assemble the final result. Then the nft
commands uses the netlink API to communicate with the kernel and send it a new rule to add. The kernel never sees lala=1.2.3.4
nor has any concept of symbolic variable.
So if you split your nft
command in two invocations what happens is:
The first nft
command defines a symbolic variable for its own later use. But does nothing else. It doesn't even have to communicate with the kernel since no ruleset change is asked. (Actually it does communicate, but to send "nothing", like with the command nft ''
). At the end of the command the definition of the symbol is lost, without having been used.
A second invocation of the nft
command needs to resolve the $lala
symbol, but cannot find a definition: nft
stops with an error.
So this must be all done in one nft
invocation so the second statement still knows about the symbolic variable. There are multiple ways to do this. I left in examples below shell and nft
's prompts which shouldn't be typed.
interactive nft
-i, --interactive
Read input from an interactive readline CLI. You can use quit
to exit, or use the EOF marker, normally this is CTRL-D.
# nft -i
nft> define lala=1.2.3.4
nft> add rule ip filter input ip saddr $lala accept
nft> quit
two commands in a single nft
invocation.
# nft 'define lala=1.2.3.4; add rule ip filter input ip saddr $lala accept'
Note the additional ;
needed because in this context nft
receives one line of parameters, but they should be split into two logical commands. Also nft
having its own parser, it doesn't care if commands are received as a single command parameter or multiple separate parameters. Here everything was enclosed in a pair of ''
to avoid shell issues with both ;
and $
characters.
Then nft
has an option to read from a file. When reading from a file, all the input is part of the same nft
command context.
-f, --file filename
Read input from filename. If filename is -, read from stdin.
nft scripts must start #!/usr/sbin/nft -f
So with a file named test.nft
having this content:
define lala=1.2.3.4
add rule ip filter input ip saddr $lala accept
This can then be used:
# nft -f test.nft
The variant below executes a script in the "nftables language". Having a test.nft
file content as:
#!/usr/sbin/nft -f
define lala=1.2.3.4
add rule ip filter input ip saddr $lala accept
Then:
# chmod a+rx test.nft
# ./test.nft
This would also have worked:
# nft -f - <<'EOF'
> define lala=1.2.3.4
> add rule ip filter input ip saddr $lala accept
> EOF
For each previous command, the resulting ruleset is the same (assuming table and chain were created before):
# nft list chain ip filter input
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
ip saddr 1.2.3.4 accept
}
}
There won't be anymore any trace of $lala
left: the kernel never received $lala
but only 1.2.3.4
and that's what it gives back.