Save and Restore iptables Rules

LinuxBeginner
Practice Now

Introduction

Rules added with the iptables command change the live kernel firewall, but a live change alone is not a durable configuration. Administrators commonly serialize IPv4 rules with iptables-save and reload that format with iptables-restore. On Debian and Ubuntu systems, /etc/iptables/rules.v4 is a conventional persistence file when an appropriate boot-time loader is enabled.

Think of the workflow as three separate layers. The live ruleset is what the kernel enforces now. A saved rules file is only text on disk until a tool or service restores it. A baseline backup is a known starting point kept for rollback. Changing one layer does not silently update the other two, so administrators must deliberately save, restore, and verify each transition.

In this lab, you will preserve the original firewall as a rollback point, add and save a narrow service rule, validate the saved file before applying it, simulate a ruleset reload, and finally restore the original baseline. This workflow separates three important states: the live rules, the saved rules file, and the rollback copy.

Back Up the Live IPv4 Firewall

In this step, you will capture the starting firewall state before making a change. A rollback file gives you a known-good state if later commands do not behave as expected.

Move to the project directory.

cd /home/labex/project

Confirm that the test service is available before changing the rules.

curl --noproxy '*' --fail --silent http://127.0.0.1:18087/status

This is a control test. 127.0.0.1 uses the loopback interface, --noproxy '*' keeps the request local even if proxy variables are configured, and --fail --silent gives a clean response with a reliable exit status. Establishing a working baseline makes later firewall behavior easier to interpret.

Use iptables-save to print the complete IPv4 ruleset. The pipe sends that output to tee, which writes baseline.v4 while leaving the command easy to run as the regular learner account.

sudo iptables-save | tee baseline.v4 >/dev/null

The privilege boundary is intentional: sudo iptables-save reads the protected kernel ruleset, while the unprivileged tee writes into your project directory. The final redirection sends tee's duplicate screen output to /dev/null; it does not empty the file. The resulting backup contains all serialized IPv4 tables and chains reported by this host, not just the one rule you will add later.

Inspect the beginning of the saved file.

head -n 12 baseline.v4

The exact counters can vary, but the file uses an iptables-restore format organized into table sections. A minimal filter section resembles:

*filter
:INPUT ACCEPT ...
...
COMMIT

Each section starts with a table name such as *filter, declares its chains and policies, lists rules, and ends with COMMIT. iptables-restore applies a table section only when it reaches that marker. Do not treat the file as an arbitrary list of standalone shell commands.

Confirm that the file contains a filter table marker and a commit marker.

grep -E '^\*filter$|^COMMIT$' baseline.v4

Add and Save the Service Rule

In this step, you will add an explicit allow rule to the live firewall and save the resulting ruleset to the conventional IPv4 persistence path.

Insert a rule at the beginning of INPUT that accepts loopback TCP traffic for port 18087. The interface and port restrictions keep the rule specific to this exercise.

sudo iptables -I INPUT 1 -i lo -p tcp --dport 18087 -j ACCEPT

INPUT covers traffic addressed to the host itself. -I INPUT 1 places the rule first, -i lo restricts it to the loopback interface, -p tcp --dport 18087 selects the test service, and -j ACCEPT permits a match. An explicit, narrowly scoped rule is easier to audit and remove than a broad rule that accepts many services.

Check the live rule. A zero exit status means the exact match and target exist; the nftables-backed implementation on this host also prints a normalized form of the matching rule.

sudo iptables -C INPUT -i lo -p tcp --dport 18087 -j ACCEPT

Save the full live IPv4 ruleset. sudo tee is used because /etc/iptables requires administrative write access.

sudo iptables-save | sudo tee /etc/iptables/rules.v4 >/dev/null

This command takes a new snapshot after the rule was added. sudo is required on both sides of the pipe for different reasons: the left side reads firewall state, and the right side opens a root-owned destination file. Merely creating rules.v4 does not activate or schedule anything; it prepares a file that a restore command or boot-time service can consume.

Search the saved file for the service port. The -- after grep ends option parsing, which is useful when a search pattern could begin with a dash.

sudo grep -- '--dport 18087' /etc/iptables/rules.v4

The output should include an INPUT rule ending in -j ACCEPT. At this point both the live ruleset and the saved file contain the intended rule.

Avoid comparing the new file byte-for-byte with the baseline. Packet counters and rules maintained by other software can legitimately change. For this exercise, the important evidence is that the intended rule exists in both the live state and the saved artifact.

Validate and Restore the Saved Ruleset

In this step, you will remove the live rule, validate the saved file without applying it, and then reload it. This simulates the important part of a reboot-time restore while remaining inside one lab session.

Delete the rule from the live INPUT chain.

sudo iptables -D INPUT -i lo -p tcp --dport 18087 -j ACCEPT

This deletion changes only the kernel's current ruleset. It does not edit /etc/iptables/rules.v4, which is why the saved rule can be restored in a later command. This deliberate mismatch demonstrates the difference between live and saved state.

Confirm that the rule is absent. The check is expected to fail, so || prints a message and lets the workflow continue.

sudo iptables -C INPUT -i lo -p tcp --dport 18087 -j ACCEPT 2>/dev/null || echo "Live rule is absent"

Before applying a saved firewall, use iptables-restore --test. This parses the complete file and reports an error for invalid syntax without replacing the live ruleset.

sudo iptables-restore --test < /etc/iptables/rules.v4

The < operator makes the shell provide the file as standard input to iptables-restore. A silent result means the syntax was accepted; it does not mean the file has already been applied. Validation is an important safety check because a malformed or incomplete ruleset can disrupt connectivity when restored.

A successful validation completes silently. Now restore the saved rules into the live firewall.

sudo iptables-restore < /etc/iptables/rules.v4

Unlike adding one rule with iptables, iptables-restore processes the complete table sections present in the file. Treat it as a high-impact administrative operation: validate first, keep a rollback copy, and verify critical access immediately afterward. In this controlled lab, the saved file was captured from the same host moments earlier.

Check that the service rule returned.

sudo iptables -C INPUT -i lo -p tcp --dport 18087 -j ACCEPT

Confirm that the application remains reachable after the restore.

curl --noproxy '*' --fail --silent http://127.0.0.1:18087/status

Roll Back to the Original Baseline

In this step, you will use the backup from Step 1 to remove the lab change from the live firewall while retaining the saved target ruleset for inspection.

Validate the baseline before applying it.

sudo iptables-restore --test < baseline.v4

Here, baseline.v4 and /etc/iptables/rules.v4 have intentionally different purposes. The baseline represents the original live state, while rules.v4 represents the target state containing the service rule. Restoring one file does not modify the other file.

Restore the original live ruleset.

sudo iptables-restore < baseline.v4

Confirm that the lab rule is no longer live.

sudo iptables -C INPUT -i lo -p tcp --dport 18087 -j ACCEPT 2>/dev/null || echo "Original firewall baseline restored"

The saved target file is a separate artifact and still contains the rule you practiced restoring.

sudo grep -- '--dport 18087' /etc/iptables/rules.v4

This check is the clearest proof of state separation: the live firewall has been rolled back, but the persistence artifact still records the target rule. An administrator could restore it again later or arrange for a persistence service to load it during boot.

Finally, verify that returning to the original permissive baseline keeps the local service reachable.

curl --noproxy '*' --fail --silent http://127.0.0.1:18087/status

In production, confirm which service loads the distribution's persistence file at boot. For example, Debian-based systems often use a package such as iptables-persistent together with netfilter-persistent, but availability and policy vary by host. Saving a correct rules.v4 file prepares the ruleset; an installed and enabled loader determines whether it is automatically restored.

Summary

You backed up the live IPv4 firewall, added and saved a targeted service rule, validated the serialized ruleset with iptables-restore --test, reloaded it into the kernel, and rolled back to the original baseline. You also distinguished the live firewall from its saved persistence and rollback files—an essential habit before changing or restoring packet-filtering state.