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

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

我需要向 iptables 添加一条规则来阻止来自 Internet 的 tcp 端口的连接。

因为我的脚本可能会被调用多次,并且没有删除规则的脚本,所以我想在插入之前检查 iptables 规则是否已经存在 - 否则 INPUT 链中会有很多重复的规则。

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

答案1

-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

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

# iptables-save | grep -- "-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT"

答案2

-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

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

答案3

这可能看起来有点倒退,但对我来说却很有效。

请先尝试删除该规则。

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

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

iptables: Bad rule (does a matching rule exist in that chain?)

然后只需像平常一样添加规则:

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

答案4

为了避免脚本中出现重复的规则,请添加以下行。

iptables -C -INPUT -p tcp --dport 8080 --jump ACCEPT || iptables -A -INPUT -p tcp --dport 8080 --jump ACCEPT

第一次运行上述命令时,我们会看到以下消息

iptables: Bad rule (does a matching rule exist in that chain?). 

这仅供参考。但命令的后半部分将确保添加规则。

相关内容