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.
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.
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.
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:
table elements.chain elements.conditions.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.
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.
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.
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.
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.
iptables-rules root.--verbose for source tracing and when to leave comments out.--combine only when grouped consecutive actions suit the XML consumer.