iptables rules are volatile by default; they live only in memory and disappear when the system reboots.
Let’s see iptables-save in action. Imagine you’ve just set up a firewall with a few rules:
# Allow SSH traffic
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP traffic
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Drop all other incoming traffic
sudo iptables -A INPUT -j DROP
# Allow established connections to return
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
After running these, your firewall is active. But if you reboot now, you’re back to square one. To make these rules permanent, we use iptables-save to dump the current rules to a file, and then a script to load them back on boot.
Here’s how it works:
-
Saving the Rules: The
iptables-savecommand writes the current in-memory rules to standard output. We redirect this to a file, typically/etc/iptables/rules.v4for IPv4.sudo iptables-save > /etc/iptables/rules.v4This file will contain your rules in a specific, human-readable format, like this:
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -p tcp --dport 22 -j ACCEPT -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -j DROP -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT COMMIT # Completed on Mon Mar 11 10:30:00 2024The
*filterindicates the table (the defaultfiltertable). Lines starting with:define chains and their default policies. Lines starting with-Aappend rules to chains.COMMITsignifies the end of the rules for that table. -
Loading the Rules on Boot: The
iptables-restorecommand reads a file (or standard input) and applies the rules within it. To make this happen at boot, we typically use a systemd service or an init script.For systemd, you’d create a service file like
/etc/systemd/system/iptables-restore.service:[Unit] Description=Restore iptables rules Before=network.target Comment=Restore iptables rules from /etc/iptables/rules.v4 [Service] Type=oneshot ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4 ExecStop=/sbin/iptables-save > /etc/iptables/rules.v4.current # Optional: save current rules on stop RemainAfterExit=yes [Install] WantedBy=multi-user.targetThen, enable and start it:
sudo systemctl enable iptables-restore.service sudo systemctl start iptables-restore.serviceThe
Before=network.targetensures that the rules are restored before the network interfaces are fully brought up, which is crucial for firewalls.Type=oneshotmeans the service runs a command once and then exits. -
The
iptables-saveFormat: Theiptables-saveformat is a declarative way to represent your firewall state. Each section starts with a table name (e.g.,*filter,*nat). Within each table, chains are defined (:), and rules are appended (-A) or inserted (-I). TheCOMMITkeyword marks the end of a table’s definition. This structured format is precisely whatiptables-restoreexpects.
The key to persistence is the iptables-save command writing the current state to a file, and iptables-restore reading that file during the boot process. This ensures your firewall configuration survives reboots, maintaining your security posture without manual intervention.
The next logical step is to handle IPv6 rules, which requires a similar process but uses ip6tables-save and ip6tables-restore with a separate rules file, typically /etc/iptables/rules.v6.