I want to run these two commands in a interactive shell, one after the other (as root and with the "filter" table and the "input" chain loaded):
nft define lala=1.2.3.4
nft add rule ip filter input ip saddr \$lala accept
You can see I escape the "$" to avoid shell expansion. But I get this error message "Unkown identifier 'lala'". If I don't escape the "$", I get this error message instead: "Syntax error, unexepected accept". If I write \$$lala instead, I get this error message instead: "Syntax error, uneepcted accept, expecting string" and this wrong rule is shown: add rule ip filter input ip saddr $ accept.
So, what's the correct syntax to be able to use Nft variables inside a interactive shell. Doing the same inside a Nft script works well (without worrying about escaping).
Thanks a lot
Best Answer
Symbolic variables in use by the
nft
userspace command are resolved into their values only by this command. Thenft
command resolves the variable into its assigned value to assemble the final result. Then thenft
commands uses the netlink API to communicate with the kernel and send it a new rule to add. The kernel never seeslala=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 commandnft ''
). 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 andnft
's prompts which shouldn't be typed.interactive
nft
two commands in a single
nft
invocation.Note the additional
;
needed because in this contextnft
receives one line of parameters, but they should be split into two logical commands. Alsonft
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 samenft
command context.So with a file named
test.nft
having this content:This can then be used:
The variant below executes a script in the "nftables language". Having a
test.nft
file content as:Then:
This would also have worked:
For each previous command, the resulting ruleset is the same (assuming table and chain were created before):
There won't be anymore any trace of
$lala
left: the kernel never received$lala
but only1.2.3.4
and that's what it gives back.