我正在尝试以编程方式创建用户链并在
iptables
中删除它们。我想知道检查用户链是否存在以及是否不创建的最佳方法是什么。
使用
iptables(8)
列出链,将 stdout/stderr 重定向到 /dev/null
,并检查退出代码。如果链存在,iptables
将退出true。
这个 shell 函数来自我的 iptables 前端脚本:
chain_exists()
{
[ $# -lt 1 -o $# -gt 2 ] && {
echo "Usage: chain_exists <chain_name> [table]" >&2
return 1
}
local chain_name="$1" ; shift
[ $# -eq 1 ] && local table="--table $1"
iptables $table -n --list "$chain_name" >/dev/null 2>&1
}
请注意,我使用
-n
选项,以便 iptables 不会尝试将 IP 地址解析为主机名。如果没有这个,你会发现这个功能会很慢。
然后您可以使用此函数有条件地创建一条链:
chain_exists foo || create_chain foo ...
其中
create_chain
是创建链的另一个函数。你可以直接调用 iptables
,但是上面的命名使得发生的事情变得非常明显。
sudo iptables-save
将
IPv4
的所有规则输出到 STDOUT,包括链名称(以 :
为前缀)
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
...
其中
*filter
是表名称。
sudo ip6tables-save
做同样的事情,但是对于
IPv6
如果您想要包含仅适用于
filter
表的链名称的规则,请添加选项:-t filter
这样:
sudo iptables-save -t filter
对于
IPv4
,
或
sudo ip6tables-save -t filter
对于
IPv6
您可以使用
awk
解析 STDOUT 以仅获取链名称:
sudo iptables-save -t filter | awk -F ":| " '/^:/ {print $2;}'
输出:
INPUT
FORWARD
...
和:
user_chain
名字和 grep -q "${user_chain:?}"
&&
如果是这样,则打印您跳过创建它 printf "Skip create: ${user_chain:?}\n"
||
使用 sudo iptables -t filter -N "${user_chain:?}"
&&
告知您已这样做:printf "Created: ${user_chain:?}\n
整个解决方案:
user_chain='MY_CHAIN'
sudo iptables-save -t filter | awk -F ":| " '/^:/ {print $2;}' | grep -q "${user_chain:?}" && printf "Skip create: ${user_chain:?}\n" || \
{ sudo iptables -t filter -N "${user_chain:?}" && printf "Created: ${user_chain:?}\n" ;}
第一次运行时的输出:
Created: MY_CHAIN
对于后续运行:
Skip create: MY_CHAIN
我想知道检查用户链是否存在以及是否不创建的最佳方法是什么。
如果您接受重新定义您的要求:
我想确保用户链存在。
那么快速而肮脏的解决方案可能是:
sudo iptables -N MY_CHAIN || true
这将确保
MY_CHAIN
存在(已创建或已经存在),并且在最坏的情况下只会打印:
iptables: Chain already exists.
但不会破坏您的脚本执行。证明:
sudo iptables -N MY_CHAIN || true && printf "I am still executing\n"
输出:
iptables: Chain already exists.
I am still executing