我有 CentOS 7 VPS。
IPtables 包含 2000 条 IP 拦截规则。重新加载时需要 80 秒才能完成。
在这 80 秒内,我注意到大约有 15 秒,我的网站变得无响应,无法通过浏览器访问任何页面。重新加载完成后,网站恢复正常,页面可以访问。
我想问一下,当重新加载 IPTables 规则时是否会出现网络无响应的情况?
这是主要结构:
/sbin/iptables -F FORWARD
/sbin/iptables -F OUTPUT
/sbin/iptables -Z FORWARD
/sbin/iptables -Z OUTPUT
/sbin/iptables -P INPUT DROP
/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
/sbin/iptables -A INPUT -m state --state INVALID -j DROP
/sbin/iptables -P OUTPUT DROP
/sbin/iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
/sbin/iptables -A OUTPUT -m state --state INVALID -j DROP
/sbin/iptables -P FORWARD DROP
/sbin/iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
/sbin/iptables -A FORWARD -m state --state INVALID -j DROP
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A OUTPUT -o lo -j ACCEPT
/sbin/iptables -A FORWARD -i lo -o lo -j ACCEPT
/sbin/iptables -t mangle -F
/sbin/iptables -t mangle -Z
/sbin/iptables -t mangle -P PREROUTING ACCEPT
/sbin/iptables -t mangle -P OUTPUT ACCEPT
/sbin/iptables -t mangle -P INPUT ACCEPT
/sbin/iptables -t mangle -P FORWARD ACCEPT
/sbin/iptables -t mangle -P POSTROUTING ACCEPT
/sbin/iptables -t nat -F
/sbin/iptables -t nat -Z
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
#
# ACCEPT RULES. JUST A FEW
#
#
/sbin/iptables -I INPUT -s 95.104.79.33 -j ACCEPT
/sbin/iptables -I INPUT -s 108.161.176.0/20 -p tcp -m multiport --dports 80,443 -j ACCEPT
#
# BLOCK RULES. EXCERPT. 2000 RULES MORE
#
#
/sbin/iptables -A INPUT -s 9.101.144.4 -j DROP
/sbin/iptables -A INPUT -s 94.229.64.6 -j DROP
/sbin/iptables -A INPUT -s 973.209.49.7 -j DROP
/sbin/iptables -A INPUT -s 98.150.131.8 -j DROP
/sbin/iptables -A INPUT -s 98.168.114.5 -j DROP
/sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 11443 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 11444 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 8447 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 8880 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 443 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 21 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 587 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 25 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 465 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 110 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 995 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 143 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 993 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 106 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 5432 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 9008 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 9080 -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 137 -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 138 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 139 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 445 -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 1194 -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport 53 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 53 -j ACCEPT
/sbin/iptables -A INPUT -p icmp --icmp-type 8/0 -j ACCEPT
/sbin/iptables -A INPUT -j DROP
/sbin/iptables -A OUTPUT -j ACCEPT
/sbin/iptables -A FORWARD -j DROP
实际上我正在使用Plesk
防火墙重新加载 shell 脚本:firewall-active.sh
防火墙-active.sh
#!/bin/bash
#ATTENTION!
#
#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY,
#SO ALL YOUR CHANGES WILL BE LOST THE NEXT TIME THE FILE IS GENERATED.
set -e
echo 0 > /proc/sys/net/ipv4/ip_forward
([ -f /var/lock/subsys/ipchains ] && /etc/init.d/ipchains stop) >/dev/null 2>&1 || true
(rmmod ipchains) >/dev/null 2>&1 || true
apply_rule()
{
iptables_bin="$1"
shift
iptables_version=`/sbin/iptables --version | awk -F '.' '{print $2$3}'`
# Use the native --wait option since v1.4.20
if [ $iptables_version -gt 420 ]; then
$iptables_bin -w $@ 2>/dev/null
return $?
fi
# Emulate --wait for elderly versions
for i in `seq 10`; do
$iptables_bin $@ 2>&1 | grep -q xtable || return 0
sleep 1
done
return 1
}
#
# CREATE DELETE RULES BY USING IPTABLES-SAVE
#
#
/sbin/iptables-save -t filter | grep -- "-A INPUT" | grep -v "fail2ban-\|f2b-" | sed -e "s#^-A#apply_rule /sbin/iptables -D#g" | (echo -e "`declare -f apply_rule`\n" && cat ) | /bin/bash
apply_rule /sbin/iptables -F FORWARD
apply_rule /sbin/iptables -F OUTPUT
apply_rule /sbin/iptables -Z FORWARD
apply_rule /sbin/iptables -Z OUTPUT
apply_rule /sbin/iptables -P INPUT DROP
apply_rule /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
apply_rule /sbin/iptables -A INPUT -m state --state INVALID -j DROP
apply_rule /sbin/iptables -P OUTPUT DROP
apply_rule /sbin/iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
apply_rule /sbin/iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
apply_rule /sbin/iptables -A OUTPUT -m state --state INVALID -j DROP
apply_rule /sbin/iptables -P FORWARD DROP
apply_rule /sbin/iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
apply_rule /sbin/iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
apply_rule /sbin/iptables -A FORWARD -m state --state INVALID -j DROP
apply_rule /sbin/iptables -A INPUT -i lo -j ACCEPT
apply_rule /sbin/iptables -A OUTPUT -o lo -j ACCEPT
apply_rule /sbin/iptables -A FORWARD -i lo -o lo -j ACCEPT
apply_rule /sbin/iptables -t mangle -F
apply_rule /sbin/iptables -t mangle -Z
apply_rule /sbin/iptables -t mangle -P PREROUTING ACCEPT
apply_rule /sbin/iptables -t mangle -P OUTPUT ACCEPT
apply_rule /sbin/iptables -t mangle -P INPUT ACCEPT
apply_rule /sbin/iptables -t mangle -P FORWARD ACCEPT
apply_rule /sbin/iptables -t mangle -P POSTROUTING ACCEPT
apply_rule /sbin/iptables -t nat -F
apply_rule /sbin/iptables -t nat -Z
apply_rule /sbin/iptables -t nat -P PREROUTING ACCEPT
apply_rule /sbin/iptables -t nat -P OUTPUT ACCEPT
apply_rule /sbin/iptables -t nat -P POSTROUTING ACCEPT
#
# ACCEPT RULES. JUST A FEW
#
#
apply_rule /sbin/iptables -I INPUT -s 95.104.79.33 -j ACCEPT
apply_rule /sbin/iptables -I INPUT -s 108.161.176.0/20 -p tcp -m multiport --dports 80,443 -j ACCEPT
#
# BLOCK RULES. EXCERPT. 2000 RULES MORE
#
#
apply_rule /sbin/iptables -A INPUT -s 9.101.144.4 -j DROP
apply_rule /sbin/iptables -A INPUT -s 94.229.64.6 -j DROP
apply_rule /sbin/iptables -A INPUT -s 973.209.49.7 -j DROP
apply_rule /sbin/iptables -A INPUT -s 98.150.131.8 -j DROP
apply_rule /sbin/iptables -A INPUT -s 98.168.114.5 -j DROP
apply_rule /sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 11443 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 11444 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 8447 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 8880 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 443 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 21 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 587 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 25 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 465 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 110 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 995 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 143 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 993 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 106 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 5432 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 9008 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 9080 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p udp --dport 137 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p udp --dport 138 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 139 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 445 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p udp --dport 1194 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p udp --dport 53 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p tcp --dport 53 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -p icmp --icmp-type 8/0 -j ACCEPT
apply_rule /sbin/iptables -A INPUT -j DROP
apply_rule /sbin/iptables -A OUTPUT -j ACCEPT
apply_rule /sbin/iptables -A FORWARD -j DROP
echo 1 > /proc/sys/net/ipv4/ip_forward
#
# End of script
#
它实际上的作用是:
- 首先检查
iptables-save
, - 寻找
-A INPUT
规律, - 将它们转换为
-D
规则以删除它们。
然后重新加载防火墙,如上图所示。由于有 2000 条单独的规则,因此需要 80 秒,其中 15 秒是站点无响应。
我尝试通过并排指定 IP 将这 2000 条独立规则合并为 1 条规则,但这没有意义。因为 iptables 无论如何都会将 2000 条规则添加到表中。重新加载时间减少到 40 秒,但仍然很慢。
请问脚本的哪一部分导致没有响应?
答案1
首先,是的,无响应是意料之中的;原因是重新加载从设置策略和刷新规则集开始。您的脚本所做的第一件事是刷新链INPUT
(实际上,它没有这样做,但我怀疑您只是忽略了前两行),然后将策略设置为DROP
。设置策略并刷新现有规则集后,您将得到一个带有策略的空链DROP
,该策略会立即让任何流量通过。随后重新加载规则后,将恢复正常行为。
更大的问题是规则集的大小。2000 条规则,说实话,太疯狂了。多年来,我管理过一些非常大的iptables
防火墙 - 针对整个站点,而不仅仅是单台机器 - 即使使用了十年,也从未达到 500 条规则。2000 条规则对我来说很像多年来的“哦,开发人员只需要能够从这个地址到达这个端口上的这个地址“,没有推回、合并,也没有对规则集进行任何垃圾收集/清理。坦率地说,对 DENY 策略有 2000 个例外的防火墙与其说是防火墙,不如说是质量差的跳线。
我强烈地感觉到,您需要呼吁用户社区证明该规则集中的每一条规则的合理性,并明确说明不再使用且业务不需要的规则的终止日期。您可能会发现,一些需要保留的规则可以通过使用用户定义的链、-m multiport
使用 CIDR 后缀和-s
/或-d
等进行合并。
直到你得到那套规则沉重修剪后,重新加载将需要一段时间,并且执行此操作时防火墙将无法正常运行。