How to edit iptables rules

Outdated information

A newer, more flexible access control service, firewalld, is now the default firewall manager for Fedora/CentOS. For most regular users’ needs, firewalld has eliminated the need to edit iptables rules directly.

You may wish to read the Using firewalld Quick Doc instead of this document, as the information provided here is no longer current. It is preserved mainly for historical interest.

In this how-to, we will illustrate how to edit iptables rules using the iptables command and the system configuration file /etc/sysconfig/iptables.

This how-to illustrates editing existing iptables rules, not the initial creation of rules chains.

Command Line Interface

Changes to iptables Rules

The following procedures allow for changes in the behaviour of the firewall while it is running. It is important to understand that every change is applied immediately.

Read the man pages (man iptables) for further explanations and more sophisticated examples.

Listing Rules

Currently running iptables rules can be viewed with the command:

  1. # iptables -L

The following example shows four rules. These rules permit established or related connections, any ICMP traffic, any local traffic as well as incoming connections on port 22. Please note that the output has no indication that the third rule applies only to local traffic. Therefore you might want to add the -v option. This will reveal that the rule only applies to traffic on the loopback interface.

  1. [root@server ~]# iptables -L
  2. Chain INPUT (policy DROP)
  3. target prot opt source destination
  4. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  5. ACCEPT icmp -- anywhere anywhere
  6. ACCEPT all -- anywhere anywhere
  7. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  8. Chain FORWARD (policy ACCEPT)
  9. target prot opt source destination
  10. Chain OUTPUT (policy ACCEPT)
  11. target prot opt source destination

Also remember that rules are applied in order of appearance and that after the first match, no further rules are considered (there are exceptions, please refer to the man pages for details). For example, in case there is a rule rejecting ssh connections and subsequently a second rule permitting ssh connections, the first rule would be applied to incoming ssh connections while the latter would never be evaluated.

Appending Rules

The following adds a rule at the end of the specified chain of iptables:

  1. [root@server ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
  2. [root@server ~]# iptables -L
  3. Chain INPUT (policy DROP)
  4. target prot opt source destination
  5. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  6. ACCEPT icmp -- anywhere anywhere
  7. ACCEPT all -- anywhere anywhere
  8. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  9. ACCEPT tcp -- anywhere anywhere tcp dpt:http
  10. Chain FORWARD (policy ACCEPT)
  11. target prot opt source destination
  12. Chain OUTPUT (policy ACCEPT)
  13. target prot opt source destination

Notice the last line in the INPUT chain. There are now five rules.

Deleting Rules

To delete a rule you need to know its position in the chain. The following will delete the rule from the previous example. To do so, the rule in the fifth position has to be deleted:

  1. [root@server ~]# iptables -D INPUT 5
  2. [root@server ~]# iptables -L
  3. Chain INPUT (policy DROP)
  4. target prot opt source destination
  5. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  6. ACCEPT icmp -- anywhere anywhere
  7. ACCEPT all -- anywhere anywhere
  8. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  9. Chain FORWARD (policy ACCEPT)
  10. target prot opt source destination
  11. Chain OUTPUT (policy ACCEPT)
  12. target prot opt source destination

Inserting Rules

You can also insert rules at a specific position. To insert a rule at the top (i.e. first) position, use:

  1. [root@server ~]# iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
  2. [root@server ~]# iptables -L
  3. Chain INPUT (policy DROP)
  4. target prot opt source destination
  5. ACCEPT tcp -- anywhere anywhere tcp dpt:http
  6. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  7. ACCEPT icmp -- anywhere anywhere
  8. ACCEPT all -- anywhere anywhere
  9. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  10. Chain FORWARD (policy ACCEPT)
  11. target prot opt source destination
  12. Chain OUTPUT (policy ACCEPT)
  13. target prot opt source destination

The number given after the chain name indicates the position of your new rule after the insertion. So, for example, if you want to insert a rule at the third position, you specify the number 3. Afterwards your new rule is at position 3, while the old rule from position 3 is now shifted to position 4.

Replacing Rules

Rules may be specified to replace existing rules in the chain.

In the previous example, the first rule grants access to tcp port 80 from any source. To restrict the access to sources within a local net, the following command replaces the first rule:

  1. [root@server ~]# iptables -R INPUT 1 -p tcp -s 192.168.0.0/24 --dport 80 -j ACCEPT
  2. [root@server ~]# iptables -L
  3. Chain INPUT (policy DROP)
  4. target prot opt source destination
  5. ACCEPT tcp -- 192.168.0.0/24 anywhere tcp dpt:http
  6. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  7. ACCEPT icmp -- anywhere anywhere
  8. ACCEPT all -- anywhere anywhere
  9. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  10. Chain FORWARD (policy ACCEPT)
  11. target prot opt source destination
  12. Chain OUTPUT (policy ACCEPT)
  13. target prot opt source destination

Flushing Rules

To flush or clear all iptables rules, use the --flush, -F option:

  1. # iptables -F <chain>

Specifying a chain is optional. Without a given chain, all chains are flushed. Remember that the new rule set is immediately active. Depending on the default policies, you might loose access to a remote machine by flushing the rules.

To flush all rules in the OUTPUT chain use:

  1. # iptables -F OUTPUT

Making changes persistent

All changes to iptables rules using the CLI commands will be lost upon system reboot. However, iptables comes with two useful utilities: iptables-save and iptables-restore.

iptables-save prints a dump of current rule set to stdout. This may be redirected to a file:

  1. [root@server ~]# iptables-save > iptables.dump
  2. [root@server ~]# cat iptables.dump
  3. # Generated by iptables-save v1.4.12 on Wed Dec 7 20:10:49 2011
  4. *filter
  5. :INPUT DROP [45:2307]
  6. :FORWARD ACCEPT [0:0]
  7. :OUTPUT ACCEPT [1571:4260654]
  8. -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  9. -A INPUT -p icmp -j ACCEPT
  10. -A INPUT -i lo -j ACCEPT
  11. -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
  12. COMMIT
  13. # Completed on Wed Dec 7 20:10:49 2011

Use iptables-restore to restore a dump of rules made by iptables-save.

  1. [root@server ~]# iptables-restore < iptables.dump
  2. [root@server ~]# iptables -L
  3. Chain INPUT (policy DROP)
  4. target prot opt source destination
  5. ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
  6. ACCEPT icmp -- anywhere anywhere
  7. ACCEPT all -- anywhere anywhere
  8. ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
  9. Chain FORWARD (policy ACCEPT)
  10. target prot opt source destination
  11. Chain OUTPUT (policy ACCEPT)
  12. target prot opt source destination

In the default configuration, stopping or restarting the iptables service will discard the running configuration. This behavior can be changed by setting IPTABLES_SAVE_ON_STOP="yes" or IPTABLES_SAVE_ON_RESTART="yes" in /etc/sysconfig/iptables-config. If these values are set, the configuration will be automatically dumped to /etc/sysconfig/iptables and /etc/sysconfig/ip6tables for IPv4 and IPv6 respectively.

If you prefer, you may edit these files directly. Restart the iptables service or restore the rules to apply your changes. The rules are in the same format as you would specify them on the command line:

  1. # Generated by iptables-save v1.4.12 on Wed Dec 7 20:22:39 2011
  2. *filter
  3. :INPUT DROP [157:36334]
  4. :FORWARD ACCEPT [0:0]
  5. :OUTPUT ACCEPT [48876:76493439]
  6. -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  7. -A INPUT -p icmp -j ACCEPT
  8. -A INPUT -i lo -j ACCEPT
  9. -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
  10. COMMIT
  11. # Completed on Wed Dec 7 20:22:39 2011

The numbers in brackets are counters and usually you don’t have to mangle them. If needed, you can reset packet and byte counters using the -Z or --zero option:

  1. # iptables -Z <chain> <rule_number>

It is possible to reset only a single rule counter. This might become handy if you want to know how many packets were captured for a specific rule.