如何检查 iptables 规则是否已存在?

sev*_*ver 51 iptables

我需要向 iptables 添加规则以阻止从 Internet 连接到 tcp 端口。

由于我的脚本可能被多次调用,而且没有删除规则的脚本,所以我想在插入之前检查iptables规则是否已经存在——否则INPUT链中会有很多dup规则。

如何检查 iptables 规则是否已存在?

Mar*_*ICE 54

-C --check最近的 iptables 版本中有一个新选项。

# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
iptables: Bad rule (does a matching rule exist in that chain?).
# echo $?
1

# iptables -A INPUT -p tcp --dport 8080 --jump ACCEPT

# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
# echo $?
0
Run Code Online (Sandbox Code Playgroud)

对于较旧的 iptables 版本,我会使用 Garrett 建议:

# iptables-save | grep -- "-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT"
Run Code Online (Sandbox Code Playgroud)


Kaz*_*Kaz 12

-C选项并不令人满意,因为它对检查时间到使用时间 (TOCTTOU) 竞争条件开放。如果两个进程尝试在大约同一时间添加相同的规则,-C则不会保护它们避免添加两次。

所以,它真的不比grep解决方案更好。对 输出的准确文本处理作业iptables-save可以像 一样可靠地工作-C,因为该输出是表状态的可靠快照。

需要的是一个--ensure选项,该选项仅在规则不存在时自动检查并添加规则。此外,如果将规则移动到正确的位置会很好,如果新规则不存在,则将插入该位置(--ensure-move)。例如,如果iptables -I 1用于在链的头部创建规则,但该规则已存在于第七个位置,则现有规则应移至第一个位置。

如果没有这些功能,我认为一个可行的解决方法是基于此伪代码编写一个 shell 脚本循环:

while true ; do
  # delete all copies of the rule first

  while copies_of_rule_exist ; do
    iptables -D $RULE
  done

  # now try to add the rule

  iptables -A $RULE # or -I 

  # At this point there may be duplicates due to races.
  # Bail out of loop if there is exactly one, otherwise
  # start again.
  if exactly_one_copy_of_rule_exists ; then
    break;
  fi
done
Run Code Online (Sandbox Code Playgroud)

这段代码可以旋转;它不保证两个或更多的赛车手会在固定的迭代次数内出局。可以添加一些随机指数退避睡眠来帮助解决这个问题。

  • 我想补充一点,这个命令并不令人满意,原因很简单,您必须确定添加规则的确切方式。我用我的设置进行了测试,但它找不到规则,因为我没有指定确切的关键字和值...... (2认同)

小智 8

这可能看起来有点倒退,但它对我有用 - 先尝试删除规则。

iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP;

您应该会收到类似于以下内容的消息:

iptables:错误规则(该链中是否存在匹配规则?)

然后只需像往常一样添加您的规则:

iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP;

  • 在防火墙中打开一个不需要的漏洞,只是为了模拟幂等命令,可能不是一个好主意。当然,这个漏洞是暂时的,但它仍然增加了攻击者的机会。如果有什么东西打断了替换规则的添加,那么这个漏洞可能会无限期地存在。 (5认同)
  • 好点@sampablokuper:出于安全原因,该策略可能仅适用于 ACCEPT 规则,而不适合 DROP 规则 (2认同)
  • 我最终也做了同样的事情! (2认同)