I am trying to programmatically create user chains and delete them in iptables
. I was wondering what is the best way to check if a user chain exist and if it does not create it.

- 19,179
- 10
- 84
- 156

- 779
- 3
- 12
- 31
3 Answers
Use iptables(8)
to list the chain, redirecting stdout/stderr to /dev/null
, and check the exit code. If the chain exists, iptables
will exit true.
This shell function is from my iptables front-end script:
chain_exists()
{
[ $# -lt 1 -o $# -gt 2 ] && {
echo "Usage: chain_exists <chain_name> [table]" >&2
return 1
}
local chain_name="$1" ; shift
[ $# -eq 1 ] && local table="--table $1"
iptables $table -n --list "$chain_name" >/dev/null 2>&1
}
Note that I use the -n
option so that iptables does not try to resolve IP addresses to hostnames. Without this, you'll find this function would be slow.
You can then use this function to conditionally create a chain:
chain_exists foo || create_chain foo ...
where create_chain
is another function to create the chain. You could call iptables
directly, but the above naming makes it quite obvious what is going on.

- 40,988
- 13
- 62
- 70
-
Should be `iptables(8)` and `iptables -t $table ...`? – mkj Dec 14 '16 at 17:19
-
1@mkj: iptables(8) - I have fixed this, thanks. `-t $table` - look at the line above and you'll see `$table` already contains `--table`. I did it this way so that `$table` is either empty or "--table
", since the table is optional and you don't want -t/--table if there is no table argument.
– camh Dec 15 '16 at 03:39 -
Using `>/dev/null 2>&1` will lead to hide the error `Could not fetch rule set...` in case a user does not have permission to run `iptables` and is likely to happen if `sudo` is omitted. Adding `sudo` is not a silver bullet because `sudo` may not be available and `>/dev/null 2>&1` will hide the error about its unavailability as well. If intention to use `>/dev/null 2>&1` was to hide `iptables` error when a chain does not exist then you can use `iptables-save` and parse its output without the `>/dev/null 2>&1` like in [this solution](https://stackoverflow.com/a/76799114/1174405) – Jimmix Jul 30 '23 at 20:32
For the default table filter
and IPv4
Solution:
user_chain='MY_CHAIN'
sudo iptables-save -t filter | awk -F ":| " "/^:${user_chain:?} /"' {rc = 1;}; END { exit !rc }' && printf "Skip create: ${user_chain:?}\n" || \
{ sudo iptables -t filter -N "${user_chain:?}" && printf "Created: ${user_chain:?}\n" ;}
Outputs when run for the first time:
Created: MY_CHAIN
and for the subsequent runs:
Skip create: MY_CHAIN
or if you don't care about prints then solution is:
user_chain='MY_CHAIN'
sudo iptables-save -t filter | awk -F ":| " "/^:${user_chain:?} /"' {rc = 1;}; END { exit !rc }' || \
sudo iptables -t filter -N "${user_chain:?}"
Keep in mind that above examples address only the IPv4
, if you want to address IPv6
then change
iptables
toip6tables
iptables-save
toip6tables-save
in the provided solutions.
Explaination:
iptables-save -t filter
outputs all rules for theIPv4
filter
table including chains names (they are prefixed with:
) - remove-t filter
for outputting rules and chains names for all tablesawk -F ":| " "/^:${user_chain:?} /"' {rc = 1;}; END { exit !rc }'
exits with code0
ifuser_chain
was found and with ec =1
if not found.|| sudo iptables -t filter -N "${user_chain:?}"
createsuser_chain
ifawk
exited with1
code (auser_chain
was not found)

- 5,644
- 6
- 44
- 71
I was wondering what is the best way to check if a user chain exist and if it does not create it.
If you would accept redefining your requirement to:
I would like to ensure that a user chain exists.
Then quick solution could be:
sudo iptables -N MY_CHAIN || ec=$? && [ ${ec:?} -eq 1 ] || (exit ${ec:?})
The above command ensures that MY_CHAIN
exists and exits with 0
code in cases:
iptables exit code
- comment
0
- chainMY_CHAIN
created1
- iptables errorChain already exists.
In cases iptables
exits with different code than 0
or 1
then command as above exits with that code, for example:
2
-iptables v1.8.7 (nf_tables): chain name MY_CHAIN111111111111111111111111111111111111111' too long (must be under 29 chars)
4
-iptables v1.8.7 (nf_tables): Could not fetch rule set generation id: Permission denied (you must be root)

- 5,644
- 6
- 44
- 71