如何从iptables中删除特定规则?

411

我在端口8006和8007上分别托管特殊的HTTP和HTTPS服务。我使用iptables来“激活”服务器,即路由传入的HTTP和HTTPS端口:

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 

这个方法十分有效。不过,我想再创建另一个脚本,以便将我的服务器再次禁用;也就是将iptables恢复到运行上述代码之前的状态。然而,我很难找出删除这些规则的语法。唯一有效的方法似乎是完全清空:

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

但这也会删除其他不需要的iptables规则。


5
我发现对于ACCEPT行,最好使用-I而不是-A。这是因为通常情况下(例如对于INPUT链),最后一行是DROPREJECT,而您希望您的规则出现在它之前。 -A将新规则放在最后一条规则之后,而-I将其放在开头。 - Mark Lakata
将此问题移至 https://unix.stackexchange.com/,因为它有非常有用的答案。 - Artur Klemens
8个回答

580

执行相同的命令,但将“-A”替换为“-D”。例如:

iptables -A ...

变为

iptables -D ...

11
如果您有多个相同的规则,它不会删除所有这些规则。 - ETech
8
尝试执行此-D命令多次,它将删除所有内容。 - Zhenyu Li
5
我使用了相同的命令,但是用的是-D而不是-I。但是我得到了BAD RULE(是否存在匹配规则)的错误提示... - Ben
5
如果您使用了 -I-R 添加了一条规则,则仍然可以使用 -D 删除该规则。 - David Xia
1
因为其他答案解释了如何从特定表中删除,如果您要删除的规则在特定表中,则这非常重要,所以我会将其降级。 - Andrew Koster
显示剩余2条评论

537

您还可以使用规则的编号(--line-numbers):

iptables -L INPUT --line-numbers

示例输出:

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

所以如果您想删除第二条规则:
iptables -D INPUT 2

更新

如果您使用(过)特定的表格(例如nat),则必须将其添加到删除命令中(感谢@ThorSummoner的评论)。

sudo iptables -t nat -D PREROUTING 1

6
这两种解决方案都不错,但当行号未知时,这个方案在脚本设置中无法使用。因此,我认为另一个解决方案更通用,因此更正确。 - Jeroen Ooms
2
如果您不知道行号,可以使用注释(例如answer among)或使用grep查找您的规则:iptables -L INPUT --line-numbers | grep -oP "([0-9]{1,3}).*tcp.*domain" | cut -d" " -f1 - domi27
8
只有在表格无法在任何时间点插入规则的情况下,这种情况才是可以的。否则,在观察行号和执行删除规则之间,行号可能会发生变化。在这种情况下,假设时间窗口很短以至于“不太可能发生”是不安全的。 - Nick
22
请记住,如果您删除了一条规则,则其余规则的行号会发生变化。因此,如果您需要删除第5、10和12条规则...请按照12、10、然后是5的顺序进行删除。 - TomOnTime
5
在尝试删除PREROUTING规则时,我必须指定“-t nat”,例如:sudo iptables -t nat --line-numbers -L,并且使用“-t nat”删除它们,例如:sudo iptables -t nat -D PREROUTING 1。(也许值得将这些信息添加到答案中?) - ThorSummoner
显示剩余4条评论

39
最适合我的并且没有任何问题的解决方案是这样的:
1. 添加一条带有注释的临时规则:
comment=$(cat /proc/sys/kernel/random/uuid | sed 's/\-//g')
iptables -A ..... -m comment --comment "${comment}" -j REQUIRED_ACTION

2. 当您添加规则后,如果想要删除它(或者所有带有此注释的内容),请执行以下操作:

iptables-save | grep -v "${comment}" | iptables-restore

因此,您将会删除所有符合$comment条件的规则,并保留其他行不变。这个解决方案在过去的两个月中使用了大约每天100次规则更改 - 没有问题。希望这能够帮助到您。


2
如果您没有iptables-save/restore命令:iptables -S | grep "${comment}" | sed 's/^-A //' | while read rule; do iptables -D $rule; done - Mansour
对于实际应用:CRON 1) 删除旧的“spamhaus”iptables禁止,2) 获取http://www.spamhaus.org/drop/,3) grep CIDR IP和iptables -A INPUT -s $ip_cidr -j -m comment --comment " spamhaus " - Xeoncross
2
@Mansour 或者 iptables -S | sed "/$comment/s/-A/iptables -D/e" ;) 就像这样 - hek2mgl
1
@hek2mgl sed不会放弃,是吧? =] 谢谢,我会记住这个功能的(但我会在一天后忘记语法)。 - Mansour
sed 仅用于从 UUID 中删除“-”。无论如何,一旦掌握了 sed 语法,就永远不会忘记。)) - ETech

36

使用以下命令列出所有的iptables规则:

iptables -S

它的列表格式如下:
-A XYZ -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

然后复制所需行,并将-A替换为-D以删除该行:

iptables -D XYZ -p ...

2
注意!这是不完整的答案。关于“-S”的手册中写道:“与其他iptables命令一样,它适用于指定的表(默认为filter)。”因此,在使用此开关的情况下,应该为所有表重复使用:nat、mangle等。 - pmod
1
在我的情况下,我得到了 iptables: Bad rule (does a matching rule exist in that chain?). 现在怎么办? - Abdull
1
啊,我明白了——我的删除命令缺少表格规范。因此,如果您使用“sudo iptables -S -t nat”列出来自表格“nat”的所有规则,并且您想要删除返回的规则之一,则仅复制是不够的。您必须添加“-t nat”,例如“sudo iptables -D ... -t nat”。 - Abdull
易于理解! - sknight

18

使用-D命令,这是man页面的解释:

-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.

请注意,像所有其他命令(-A-I)一样,这个命令也只对某些表格起作用。如果您不是在默认表格(filter 表格)上工作,请使用 -t TABLENAME 指定目标表格。

删除匹配规则

iptables -D INPUT -i eth0 -p tcp --dport 443 -j ACCEPT

注意:此操作仅删除第一个匹配的规则。如果有多个匹配的规则(在iptables中可能会出现),请多次运行此命令。

按编号删除规则

iptables -D INPUT 2

除了计算数量外,您还可以使用--line-number参数列出行号,例如:
iptables -t nat -nL --line-number

我发现使用 --line-number 是最好的。 - Davuz
是的!太棒了!不想整个运行 iptables -F - Dev Anand Sadasivam

7
假设您想要删除NAT规则,
请使用以下命令列出附加的IPtables:
# 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

如果您想从IPtables中删除NAT规则,只需执行以下命令:
# sudo iptables -F -t nat -v

Flushing chain `PREROUTING'
Flushing chain `INPUT'
Flushing chain `OUTPUT'
Flushing chain `POSTROUTING'

然后,你可以验证,
# sudo iptables -L -t nat -v

4
您也可以使用以下语法。
 iptables -D <chain name> <rule number>

例如
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

删除规则

接受 所有 -- 10.0.0.0/8 任何地方

iptables -D HTTPS 2

1
这是一行代码,用于删除与搜索匹配的iptables规则。此示例搜索与IP地址192.168.1.27匹配的所有规则,并删除它们。您需要编辑自己的搜索条件来替换该IP地址。
eval `iptables --list-rules | grep '192.168.1.27' | sed 's/^-A /iptables -D /g;s/$/;/g'`

工作原理:

它使用这个问题的被接受的答案,并使用-D而不是-A来运行规则。

  • iptables --list-rules列出所有现有的规则。即使您使用-I-R添加了它们,此列表也会显示所有规则与-A一起。
  • | grep '192.168.1.27'将列表过滤为只有您要删除的规则(在本例中是某些特定IP地址的规则)。
  • | sed 进行搜索和替换
    • s/^-A /iptables -D /giptables -D替换每个规则开头的-A,使其成为可执行的命令以删除规则。
    • s/$/;/g将每个规则的结尾替换为分号,以在运行多个命令时分隔它们。
  • eval ...将所有输出作为脚本运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接