Turn iptables-save Output into XML with iptables-xml
iptables-xml converts an iptables-save snapshot into structured XML a script can parse properly instead of scraping text. The examples target the installed iptables 1.8.10 package and never touch the running firewall.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need iptables-xml, a shell, and either an iptables-save file or permission to read the host firewall. Reading the live ruleset may need elevated privileges and can expose sensitive network policy. This guide does not restore rules or change the firewall.
1. Check the installed command
Confirm the binary and package version first. These are ordinary, read-only checks:
$ command -v iptables-xml
/usr/bin/iptables-xml
$ dpkg-query -W -f='${Package} ${Version}\n' iptables
iptables 1.8.10-3ubuntu2
The local manual identifies this command as iptables-xml(1) from iptables 1.8.10. Its interface is small: -c or --combine, -v or --verbose, and -h or --help.
Tip
Do not use --version as a version check. This build reports it as an unrecognised option but still exits successfully, which makes it a poor test in a script. Stick with command -v and check the package version instead.
2. Convert a saved ruleset without touching the firewall
iptables-xml reads iptables-save format from standard input and writes XML to standard output. Start with a small fixture so you can learn the shape without reading or changing a real ruleset:
$ printf '%s\n' \
'*filter' \
':INPUT ACCEPT [0:0]' \
'-A INPUT -p tcp --dport 22 -j ACCEPT' \
'COMMIT' | iptables-xml
<iptables-rules version="1.0">
<table name="filter" >
<chain name="INPUT" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule >
<conditions>
<match >
<p >tcp</p>
<dport >22</dport>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
</chain>
</table>
</iptables-rules>
The conversion is mechanical:
- Tables become
tableelements. - Chains become
chainelements. - Match conditions appear under
conditions. - Targets appear under
actions.
The root includes version="1.0", which describes this XML format, not the installed iptables package version.
Use input redirection to save the result. The shell creates or truncates the destination before the converter runs, so choose a new path or make a backup first:
$ iptables-xml < rules.v4 > rules.xml
$ test -s rules.xml && echo 'XML file is non-empty'
XML file is non-empty
For a file named on the command line, pass one input path after the options: iptables-xml rules.v4 > rules.xml. Keep the source file unchanged until you have inspected the result.
3. Export the live ruleset only when you need it
To convert the host's current IPv4 rules, put iptables-save before the converter:
$ sudo iptables-save | iptables-xml > live-rules.xml
$ test -s live-rules.xml && echo 'live XML file is non-empty'
live XML file is non-empty
sudo is shown because reading the live ruleset commonly needs elevated privileges. It is not needed for the conversion itself when the input is already in a readable file. This pipeline does not install, flush, append or restore a rule, but the resulting file may contain your host's firewall layout and counters, so treat it as sensitive operational data.
If the first command says it cannot fetch the ruleset or permission is denied, stop and fix access. Do not replace iptables-save with a command that changes rules. If you do not need the live state, use a saved snapshot or the fixture above instead.
4. Add source-line comments when reviewing a conversion
Use -v or --verbose when you need to trace XML back to its input:
$ iptables-xml --verbose < rules.v4 > rules-trace.xml
$ rg -n '<!-- line ' rules-trace.xml
5:<!-- line 2 :INPUT ACCEPT [0:0] -->
6:<!-- line 3 *-A INPUT *-p tcp *- *-dport 22 *-j ACCEPT -->
The exact line numbers depend on blank lines and comments in the input. These comments are useful during review, but they are not rule data. If another program parses the XML, test whether it ignores comments as XML parsers normally do.
5. Combine consecutive matching actions deliberately
Without options, each input rule becomes its own XML rule. Add -c or --combine to collect consecutive rules with identical matches but different targets:
$ printf '%s\n' \
'*filter' \
':INPUT ACCEPT [0:0]' \
'-A INPUT -p tcp --dport 22 -j MARK --set-mark 10' \
'-A INPUT -p tcp --dport 22 -j LOG --log-prefix "ssh "' \
'COMMIT' | iptables-xml --combine | rg -n 'rule|MARK|LOG|Combine'
4: <rule >
12: <MARK >
15:<!-- Combine action from next rule -->
16: <LOG >
Only consecutive rules with identical matches are eligible. A different port, protocol, interface or other match starts a separate XML rule. Terminating actions such as RETURN, DROP, ACCEPT and QUEUE are not combined with a following target. This option changes the representation, not the live ruleset, but it can change how your XML consumer interprets action order, so use it only when that consumer expects the grouped form.
6. Check the XML before handing it to another tool
Check that the output is non-empty and has the expected root element. If an XML-aware parser is installed, use it as an additional check:
$ test -s rules.xml
$ rg -q '^<iptables-rules version="1.0">$' rules.xml
$ xmllint --noout rules.xml
The last command is optional and belongs to xmllint, not iptables-xml. Inspect a few chains, conditions and actions as well. A successful conversion proves the text was converted; it does not prove a later XML-to-rules workflow preserves the policy you intended.
Warning
The manual describes a possible reverse workflow using an iptables.xslt stylesheet, xsltproc and iptables-restore. Treat that as a separate, high-risk operation. Restoring rules can disrupt active connections and lock out remote access. Do not pipe generated XML into a restore command until you have reviewed it, tested a rollback path and arranged console access or a maintenance window.
Done means
- Binary and version known. The installed binary and iptables package version are known.
- Conversion verified. A saved iptables-save input produces a non-empty XML document with an
iptables-rulesroot. - Verbose mode understood. You know when to use
--verbosefor source tracing and when to leave comments out. - Combine used deliberately. You use
--combineonly when grouped consecutive actions suit the XML consumer. - Firewall untouched. No firewall rule was added, removed, flushed or restored during the conversion.
- Restore treated separately. Any future restore is treated as a separate change with review and recovery access.