【问题标题】:How can I remove specific rules from iptables? [closed]如何从 iptables 中删除特定规则? [关闭]
【发布时间】:2012-04-29 03:46:13
【问题描述】:

我分别在端口 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 规则。

【问题讨论】:

  • 我发现ACCEPT 行最好使用-I 而不是-A。这是因为通常情况下,最后一行(例如 INPUT 链)是 DROPREJECT 并且您希望您的规则在此之前出现。 -A 将新规则放在最后一条规则之后,而 -I 将它放在开头。

标签: linux firewall iptables


【解决方案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 /g 将每条规则开头的 -A 替换为 iptables -D,使其成为删除规则的可执行命令。
    • s/$/;/g 将每个规则的末尾替换为分号,以便在运行时分隔多个命令
  • eval ... 获取所有输出并将其作为脚本运行。

【讨论】:

    【解决方案2】:

    你也可以使用下面的语法

     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
    

    【讨论】:

      【解决方案3】:

      首先用这个命令列出所有 iptables 规则:

      iptables -S
      

      列出如下:

      -A XYZ -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
      

      然后复制所需的行,只需将-A 替换为-D 即可删除:

      iptables -D XYZ -p ...
      

      【讨论】:

      • 注意!这是不完整的答案。来自关于“-S”的手册:“像所有其他 iptables 命令一样,它适用于指定的表(过滤器是默认值)。”。因此,如果使用此开关 - 应该对所有表重复:nat、mangle 等
      • 在我的情况下,我得到iptables: Bad rule (does a matching rule exist in that chain?). 现在怎么办?
      • 啊,想通了 - 我的删除命令缺少表规范。因此,如果您列出表 natsudo iptables -S -t nat 中的所有规则并且您想删除返回的规则之一,复制是不够的。您必须添加-t nat,例如sudo iptables -D ... -t nat.
      • 通俗易懂!
      【解决方案4】:

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

      iptables -A ...
      

      变成

      iptables -D ...
      

      【讨论】:

      • 如果你有多个规则,它不会全部删除。
      • 尝试多次执行这个-D命令,会全部删除。
      • 我执行了相同的命令,但使用 -D 而不是 -I。但我得到了错误的规则(是否存在匹配规则)......
      • 如果您使用-I-R 添加规则,您仍然可以使用-D 将其删除。
      • 只是一个注释。我使用“iptables -A ...”创建了一个规则,该规则出现但无效。在使用 'iptables -D ...' 时,响应是 Bad rule。即便如此,这条规则也被删除了。使用“sudo iptables -nvL”可以看到该规则。我使用的链是'INPUT'。
      【解决方案5】:

      假设,如果你想删除 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
      

      【讨论】:

        【解决方案6】:

        使用-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 的最好
        • 是的!高超!不想要整个iptables -F
        【解决方案7】:

        您也可以使用规则的编号(--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
        

        更新

        如果你使用(d)一个特定的表(例如 nat),你必须将它添加到删除命令中(感谢@ThorSummoner 的评论)

        sudo iptables -t nat -D PREROUTING 1
        

        【讨论】:

        • 两种解决方案都很好,但是当行号未知时,这个解决方案在脚本设置中不起作用。所以另一个解决方案更通用,因此更正确,IMO。
        • 好吧,如果您不知道该行,您可以使用评论(例如其中的答案)或为您的规则做一个 grep:iptables -L INPUT --line-numbers | grep -oP "([0-9]{1,3}).*tcp.*domain" | cut -d" " -f1
        • 只有在表格不能在任何时间点插入规则时才可以。否则,行号可能会在观察它们和执行删除规则之间发生变化。在这种情况下,假设时间窗口太短以至于“不可能发生”是不安全的。
        • 请记住,如果您删除一条规则,则其余规则的行号会更改。因此,如果您需要删除规则 5、10 和 12... 删除它们 12、10 和 5。
        • 尝试删除 PREROUTING 规则时,我必须指定 -t nat,例如:sudo iptables -t nat --line-numbers -L,并使用 -t nat 删除它们,例如:sudo iptables -t nat -D PREROUTING 1(可能值得添加到答案中?)
        【解决方案8】:

        对我来说没有任何问题的最佳解决方案如下所示:
        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
        

        因此,您将 100% 删除与 $comment 匹配的所有规则,而其他行保持不变。此解决方案在过去 2 个月内有效,每天更改约 100 次规则 - 没有问题。希望,它会有所帮助

        【讨论】:

        • 如果您没有 iptables-save/restore:iptables -S | grep "${comment}" | sed 's/^-A //' | while read rule; do iptables -D $rule; done
        • 实际使用:CRON 1) 删除旧的 spamhaus iptables 禁令,2) 抓取 spamhaus.org/drop,3) grep 获取 CIDR IP 和 iptables -A INPUT -s $ip_cidr -j -m comment --comment "spamhaus"
        • @Mansour 或iptables -S | sed "/$comment/s/-A/iptables -D/e" ;) 喜欢this
        • @hek2mgl sed 不会放弃,是吗? =] 谢谢,我会记住这个功能(我会在一天内忘记语法)。
        • sed 仅用于从 uuid 中删除“-”。无论如何,一旦您掌握了 sed 语法,就永远不会忘记它。 ))
        猜你喜欢
        • 1970-01-01
        • 2012-01-04
        • 2014-01-30
        • 2015-05-17
        • 1970-01-01
        • 2016-01-09
        • 2016-02-01
        • 2014-01-11
        • 1970-01-01
        相关资源
        最近更新 更多