How can I remove specific rules from iptables?
LinuxFirewallIptablesLinux Problem Overview
I am hosting special HTTP and HTTPS services on the ports 8006 and 8007 respectively. I use iptables to "activate" the server; i.e. to route the incoming HTTP and HTTPS ports:
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 8006 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 8007 -j ACCEPT
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8006
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8007
iptables -A OUTPUT -t nat -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 8006
iptables -A OUTPUT -t nat -d 127.0.0.1 -p tcp --dport 443 -j REDIRECT --to-ports 8007
This works like a charm. However I would like to create another script that disables my server again; i.e. restore iptables to the state it was in before running the lines above. However I am having a hard time figuring out the syntax to remove these rules. The only thing that seems to work is a complete flush:
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
But that will also delete other iptables rules which is undesired.
Linux Solutions
Solution 1 - Linux
Execute the same commands but replace the "-A" with "-D". For example:
iptables -A ...
becomes
iptables -D ...
Solution 2 - Linux
You may also use the rule's number (--line-numbers):
iptables -L INPUT --line-numbers
Example output :
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT udp -- anywhere anywhere udp dpt:domain
2 ACCEPT tcp -- anywhere anywhere tcp dpt:domain
3 ACCEPT udp -- anywhere anywhere udp dpt:bootps
4 ACCEPT tcp -- anywhere anywhere tcp dpt:bootps
So if you would like to delete second rule :
iptables -D INPUT 2
Update
If you use(d) a specific table (eg nat), you have to add it to the delete command (thx to @ThorSummoner for the comment)
sudo iptables -t nat -D PREROUTING 1
Solution 3 - Linux
The best solution that works for me without any problems looks this way:
-
Add temporary rule with some comment:
comment=$(cat /proc/sys/kernel/random/uuid | sed 's/-//g') iptables -A ..... -m comment --comment "${comment}" -j REQUIRED_ACTION
-
When the rule added and you wish to remove it (or everything with this comment), do:
iptables-save | grep -v "${comment}" | iptables-restore
So, you'll 100% delete all rules that match the $comment and leave other lines untouched. This solution works for last 2 months with about 100 changes of rules per day - no issues.Hope, it helps
Solution 4 - Linux
First list all iptables rules with this command:
iptables -S
it lists like:
-A XYZ -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
Then copy the desired line, and just replace -A
with -D
to delete that:
iptables -D XYZ -p ...
Solution 5 - Linux
Use -D
command, this is how man
page explains it:
-D, --delete chain rule-specification
-D, --delete chain rulenum
Delete one or more rules from the selected chain.
There are two versions of this command:
the rule can be specified as a number in the chain (starting at 1 for the first rule) or a rule to match.
Do realize this command, like all other command(-A
, -I
) works on certain table. If you'are not working on the default table(filter
table), use -t TABLENAME
to specify that target table.
Delete a rule to match
iptables -D INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
Note: This only deletes the first rule matched. If you have many rules matched(this can happen in iptables), run this several times.
Delete a rule specified as a number
iptables -D INPUT 2
Other than counting the number you can list the line-number with --line-number
parameter, for example:
iptables -t nat -nL --line-number
Solution 6 - Linux
Assume that, if you want to remove NAT rules,
List the appended IPtables using the command below,
# sudo iptables -L -t nat -v
Chain PREROUTING (policy ACCEPT 18 packets, 1382 bytes)
pkts bytes target prot opt in out source destination
7 420 DNAT tcp -- any any anywhere saltmaster tcp dpt:http to:172.31.5.207:80
0 0 DNAT tcp -- eth0 any anywhere anywhere tcp dpt:http to:172.31.5.207:8080
If you would like to remove the nat rule from the IPtables, just execute the command,
# sudo iptables -F -t nat -v
Flushing chain `PREROUTING'
Flushing chain `INPUT'
Flushing chain `OUTPUT'
Flushing chain `POSTROUTING'
Then, you can verify that,
# sudo iptables -L -t nat -v
Solution 7 - Linux
You can also use the following syntax
iptables -D <chain name> <rule number>
For example
Chain HTTPS
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- 10.0.0.0/8 anywhere
ACCEPT all -- 182.162.0.0/16 anywhere
To delete the rule
> ACCEPT all -- 10.0.0.0/8 anywhere
iptables -D HTTPS 2
Solution 8 - Linux
Here is a one liner that deletes the iptables
rules that match a search. This example searches for all the rules that match the IP address 192.168.1.27
and removes all of them. You would edit in your own search criteria in place of that IP address.
eval `iptables --list-rules | grep '192.168.1.27' | sed 's/^-A /iptables -D /g;s/$/;/g'`
How it works:
It uses the accepted answer to this question and to run rules with -D
rather than -A
.
iptables --list-rules
lists all the existing rules. Even if you added them with-I
or-R
, this list shows them all with-A
| grep '192.168.1.27'
filters the list to just the rules that you want removed (in this case the rules for some specific IP address.)| sed
does a search and replaces/^-A /iptables -D /g
replaces the-A
at the start of each rule withiptables -D
so that it becomes an executable command to remove the rule.s/$/;/g
replaces the end of each rule with a semi-colon to separate multiple commands when they are run
eval ...
takes all that output and runs it as a script.