I am writing a program that takes a snapshot of iptable rules so that they can be restored at a later point. I don’t want to write the rules to a file; I store them as a string in my code.
This worked perfectly making a call out to iptables-save
and capturing the output into a string and then calling iptables-restore
combined with bash process substitution to feed the rules string back into iptables e.g. iptables-restore <(echo "<rules here>")
(have to change this later though to use pipes since Ubuntu won’t support that)
I encountered a case where there was a log-prefix
option with a space on one of the rules that has caused the restore step to break. For example:
[root@host ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "
and the output of iptables-save
:
[root@host ~]# iptables-save
# Generated by iptables-save v1.8.8 (nf_tables) on Wed May 3 21:45:25 2023
*filter
:INPUT ACCEPT [101:5876]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [84:34334]
-A OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
COMMIT
# Completed on Wed May 3 21:45:25 2023
This is the command run by the code:
/bin/sh -c /sbin/iptables-restore <(echo "# Generated by iptables-save v1.8.8 (nf_tables) on Wed May 3 21:45:25 2023
*filter
:INPUT ACCEPT [1936:94741]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [612:2005831]
-A OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
COMMIT
# Completed on Wed May 3 21:45:25 2023
")
Bad argument `BLOCK]'
Error occurred at line: 6
Try `iptables-restore -h' or 'iptables-restore --help' for more information.
If I remove the space between UFW
and BLOCK
it works ok.
I’ve tried escaping the quotation marks in the string too but still the same issue.
Is there some trick to get this to work. Also, I don’t have any control of what could be in the rules and they need to be replaced exactly as taken from the snapshot so preprocessing the string before calling restore wouldn’t work for me.
2
Answers
So it seems after bouncing the issue off a few people in the office I actually have it working. The solution of escaping the quotations was correct e.g.
"[UFW BLOCK] "
. I had thought it wasn't working because I was monitoring the output of the command:which has the escape characters present but when running iptables list I see they are not there:
Apologies for the dumb moment doh!
You did not show any C++ code, but instead of relying on fragile bash argument handling you could use a pipe and use the
/dev/fd/X
syntax:To simplify further, you could use
mkstemp
to generate an anonymous temporary file, dump data into it, and again pass/dev/fd/X
to iptables-restore.EDIT: the mkstemp solution (equally untested):