Build a Persistent firewalld IP Set from XML
You will create a named firewalld IP set containing a small list of IPv4 addresses, load it as permanent configuration, and bind it to a zone as a source. The examples use firewalld 2.1.1, installed on the system used for this guide. Allow about ten minutes if firewalld is already running and you have root access.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the firewalld package, an active firewalld daemon for runtime checks, and a shell account that can use sudo. The XML file is configuration, not a command to paste into a shell. Keep a copy of the original file if you are editing an existing set.
1. Check the supported set types
Start with a read-only query. The mandatory type attribute in an IP set XML file must be one of the types supported by this installation. For an address list, hash:ip is the usual choice, but do not assume that another host has the same support.
$ firewall-cmd --get-ipset-types
Expected output is a space-separated list of types. Confirm that hash:ip appears before continuing. The command does not create or change an IP set.
2. Create the permanent XML file
Permanent custom IP sets belong under /etc/firewalld/ipsets/. The file name becomes the set name, so this example creates trusted_scanners from trusted_scanners.xml. The system-wide /usr/lib/firewalld/ipsets/ directory is also documented, but it is intended for packaged defaults. Put local administration in /etc.
This example has two entries. Replace the documentation addresses with addresses that are valid for your network. Do not add a broad network range when you mean to allow a few hosts.
<?xml version="1.0" encoding="utf-8"?>
<ipset type="hash:ip">
<short>Trusted scanners</short>
<description>IPv4 scanners allowed to reach the inspection service</description>
<entry>192.0.2.10</entry>
<entry>192.0.2.11</entry>
</ipset>
Create the directory and file with elevated privileges. An editor is preferable for a real change because it leaves you with a visible file to review:
$ sudo install -d -m 0755 /etc/firewalld/ipsets
$ sudoedit /etc/firewalld/ipsets/trusted_scanners.xml
Check the file before asking firewalld to read it:
$ sudo sed -n '1,120p' /etc/firewalld/ipsets/trusted_scanners.xml
$ sudo xmllint --noout /etc/firewalld/ipsets/trusted_scanners.xml
If xmllint is not installed, use firewalld's own configuration check later. XML validity alone does not prove that the type, options or entries make sense to firewalld.
Checkpoint: the file is in the right place
- The file is exactly
/etc/firewalld/ipsets/trusted_scanners.xml. - The root element is used once and has the mandatory
typeattribute. - Each address is inside its own
entryelement. - The addresses are examples from the reserved documentation range, not accidental production addresses.
3. Validate permanent firewalld configuration
Run the configuration check before reloading. It checks permanent configuration, including XML validity and semantics. This command needs the daemon to be available when using firewall-cmd:
$ sudo firewall-cmd --check-config
success
The exact success output can vary by firewalld build. A non-zero result is a stop sign. Read the error, correct the XML, and run the check again. Do not reload a firewall whose permanent configuration has just failed validation.
4. Load and inspect the IP set
Reloading makes the current permanent configuration become the runtime configuration. This can discard unrelated runtime-only changes, so check with the operator responsible for the host before doing it. A normal reload keeps connection state; --complete-reload can terminate active connections and is not needed for this task.
$ sudo firewall-cmd --reload
success
$ firewall-cmd --get-ipsets
trusted_scanners
$ firewall-cmd --info-ipset=trusted_scanners
$ firewall-cmd --ipset=trusted_scanners --get-entries
The information command should show the set type and metadata. The final command should list 192.0.2.10 and 192.0.2.11. These inspection commands are read-only and do not require elevation on a normally configured host.
5. Use the set in a zone
An IP set is only a collection until a firewalld rule uses it. To treat its members as sources for the public zone, add the source as ipset:trusted_scanners. This example writes the binding to the permanent configuration:
$ sudo firewall-cmd --permanent --zone=public --add-source=ipset:trusted_scanners
success
$ sudo firewall-cmd --reload
success
$ firewall-cmd --zone=public --list-sources
The last command should include ipset:trusted_scanners. The binding does not itself open a service or port. It selects traffic by source for the zone's existing policy. Review the zone with firewall-cmd --zone=public --list-all before relying on the result.
Do not use this pattern as a substitute for a rule review. A source set can grant access to every service already allowed by that zone. Keep the set narrow, document who maintains it, and treat changes to its entries as security-sensitive.
6. Add or remove entries safely
For a small change, edit the permanent XML, validate it, and reload. Avoid changing only the runtime set and assuming it will survive a reboot. The --permanent option controls disk configuration; without it, an entry change is runtime-only.
$ sudoedit /etc/firewalld/ipsets/trusted_scanners.xml
$ sudo firewall-cmd --check-config
$ sudo firewall-cmd --reload
$ firewall-cmd --ipset=trusted_scanners --get-entries
When you need an immediate runtime change, firewall-cmd --ipset=trusted_scanners --add-entry=192.0.2.12 changes only the running configuration. Repeat the operation with --permanent if it must persist, then reload or otherwise bring the two configurations into agreement. Verify both views when the distinction matters:
$ firewall-cmd --ipset=trusted_scanners --get-entries
$ firewall-cmd --permanent --ipset=trusted_scanners --get-entries
Recovery and undo
If the reload reports an error, restore the last known-good XML backup and run --check-config again. If the set is valid but the zone binding is wrong, remove the permanent binding and reload:
$ sudo firewall-cmd --permanent --zone=public --remove-source=ipset:trusted_scanners
$ sudo firewall-cmd --reload
To remove the set itself, first remove every zone or policy reference to it, confirm the resulting configuration, then delete the permanent set. Deleting a set is destructive to its entries:
$ sudo firewall-cmd --permanent --delete-ipset=trusted_scanners
$ sudo firewall-cmd --check-config
$ sudo firewall-cmd --reload
If the command rejects deletion because something still refers to the set, inspect zone and policy configuration rather than forcing a file removal. Keeping the XML until all references are gone makes recovery straightforward.
Done means
firewall-cmd --get-ipset-typesconfirmed the selected type.- The set XML is under
/etc/firewalld/ipsets/with a valid root, type and entries. firewall-cmd --check-configpassed before the reload.- The runtime and permanent entry lists match after the reload.
- The zone binding is intentional, visible in
--list-sources, and covered by a recovery plan.