iptables-save and iptables-restore are your go-to tools for backing up and reapplying your firewall rules. Think of them as git commit and git checkout for your network security.
Let’s see iptables-save in action. This command dumps your current iptables rules to standard output in a format that iptables-restore can understand.
sudo iptables-save
This will output something like:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --dport 22 -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT
-A OUTPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
The output is structured by table (filter, nat, mangle, etc.), with each table containing its chains (:INPUT ACCEPT [0:0]) and rules (-A INPUT -i lo -j ACCEPT). The COMMIT line signifies the end of rules for that table.
To save this to a file, you’d redirect the output:
sudo iptables-save > /etc/iptables/rules.v4
Now, how do you get these rules back? That’s where iptables-restore comes in. It reads the rules from standard input.
sudo iptables-restore < /etc/iptables/rules.v4
This command will apply the rules from the specified file. It’s crucial to understand that iptables-restore replaces the current rules in the specified table with the ones from the file. It doesn’t merge them.
The typical workflow involves:
- Saving your current, working rules to a file.
- Making changes to your firewall (e.g., adding a new port, blocking an IP).
- If the changes break something, restoring from your saved file.
- If the changes work, saving the new configuration over the old backup file.
This process is often automated on system startup and shutdown. Many Linux distributions use scripts that run iptables-save when the service stops and iptables-restore when it starts. If you’re managing this manually, you’d typically add these commands to your system’s init scripts or service files.
For example, using systemd:
You could create a service file like /etc/systemd/system/iptables-restore.service that runs iptables-restore on boot.
[Unit]
Description=Restore iptables rules
Before=network-pre.target
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4
ExecStop=/sbin/iptables-save /etc/iptables/rules.v4 # Optional: save on shutdown
[Install]
WantedBy=multi-user.target
And then enable and start it:
sudo systemctl enable iptables-restore.service
sudo systemctl start iptables-restore.service
The iptables-save command has options to specify which tables to save. By default, it saves all tables. If you only want to save the filter table, you’d use:
sudo iptables-save -t filter > /etc/iptables/filter.rules
Similarly, iptables-restore can also target specific tables:
sudo iptables-restore -t filter < /etc/iptables/filter.rules
This is useful if you’re only modifying rules in one table and don’t want to accidentally overwrite others.
A common pitfall is running iptables-restore without ensuring the rules file is correct. If your rules.v4 file has syntax errors or invalid rules, iptables-restore will fail, potentially leaving your firewall in an inconsistent or unprotected state. It’s a good practice to test new rules incrementally and save backups frequently.
The iptables-restore command has a --test flag that allows you to check the syntax of the rules file without actually applying them. This is invaluable for preventing errors.
sudo iptables-restore --test < /etc/iptables/rules.v4
If this command exits with a status code of 0 and no output, your rules file is syntactically valid. Any errors will be printed to stderr.
When restoring, the iptables-restore command uses the --counters and --modprobe options by default. --counters preserves the packet and byte counters for your rules, which can be useful for monitoring and debugging. --modprobe attempts to load necessary kernel modules for the rules (like xt_state for RELATED,ESTABLISHED tracking). If you want a clean slate with zeroed counters, you can use --noflush to prevent clearing existing rules before applying new ones, but this is rarely what you want for a full restore.
The most surprising thing about iptables-save and iptables-restore is how they handle rule ordering. When you iptables-restore a file, it doesn’t just append rules; it replaces the entire chain with the rules listed in the file for that chain, in the exact order they appear. This means the sequence of rules matters critically. If you have a rule that accepts all traffic and then a rule that drops specific traffic, the drop rule will never be hit because the accept rule matches first.
The next thing you’ll likely encounter is managing rules across different network interfaces or for specific IP addresses, leading you to explore the vast array of iptables match modules and target extensions.