当你的网站接入cloudflare并开启CDN proxy后就万事大吉了吗?其实不然,即使VPS的iptables IN Put默认drop之于源站IP的443/80也会暴露公网,会遭受针对源站IP的DDoS
解决方法&原理
cloudflare有白名单网站 利用脚本仅限cloudflare白名单IP访问443、80端口
第一层:DNS -> 只解析到 Cloudflare第二层:iptables -> 仅允许 Cloudflare IP第三层:Cloudflare -> WAF、Bot 防护、HTTPS
✓ Cloudflare IP -> 443 、80端口
✗ 其他所有 IP -> DROP
cloudflare白名单IP
https://www.cloudflare.com/zh-tw/ips
步骤
1ssh登录VPS
sudo su #获取root权限
#!/bin/bash
CF_IPV4_URL="https://www.cloudflare.com/ips-v4"
CF_IPV6_URL="https://www.cloudflare.com/ips-v6"
CF_IP_DIR="/etc/cloudflare"
CF_IPV4_FILE="${CF_IP_DIR}/cf-ips-v4"
CF_IPV6_FILE="${CF_IP_DIR}/cf-ips-v6"
# 创建目录并设置权限
sudo mkdir -p "$CF_IP_DIR" || { echo "无法创建目录 $CF_IP_DIR"; exit 1; }
sudo chmod 755 "$CF_IP_DIR"
download_cf_ips() {
local max_retries=3
local retry_delay=5
# 下载 IPv4
for ((i=1; i<=max_retries; i++)); do
if curl -sSf --connect-timeout 10 "$CF_IPV4_URL" -o "${CF_IPV4_FILE}.tmp" 2>/tmp/cf_curl_error.log; then
break
else
echo "IPv4 下载失败(尝试 $i/$max_retries),错误日志:"
cat /tmp/cf_curl_error.log
if [ $i -eq $max_retries ]; then
echo "错误:无法下载 IPv4 列表!"
return 1
fi
sleep $retry_delay
fi
done
# 下载 IPv6
for ((i=1; i<=max_retries; i++)); do
if curl -sSf --connect-timeout 10 "$CF_IPV6_URL" -o "${CF_IPV6_FILE}.tmp" 2>>/tmp/cf_curl_error.log; then
break
else
echo "IPv6 下载失败(尝试 $i/$max_retries),错误日志:"
cat /tmp/cf_curl_error.log
if [ $i -eq $max_retries ]; then
echo "错误:无法下载 IPv6 列表!"
return 1
fi
sleep $retry_delay
fi
done
# 移动临时文件
sudo mv "${CF_IPV4_FILE}.tmp" "$CF_IPV4_FILE" || { echo "移动 IPv4 文件失败"; return 1; }
sudo mv "${CF_IPV6_FILE}.tmp" "$CF_IPV6_FILE" || { echo "移动 IPv6 文件失败"; return 1; }
return 0
}
if ! download_cf_ips; then
exit 1
fi
# 创建并清空链(IPv4 和 IPv6)
create_chain() {
local ipt_cmd="$1"
local chain="$2"
if ! $ipt_cmd -L "$chain" >/dev/null 2>&1; then
$ipt_cmd -N "$chain" || { echo "无法创建链 $chain"; exit 1; }
fi
$ipt_cmd -F "$chain"
}
create_chain iptables CF_INPUT
create_chain ip6tables CF_INPUT
# 填充规则(IPv4)
while read -r ip; do
iptables -A CF_INPUT -s "$ip" -p tcp -m multiport --dports 80,443 -j ACCEPT
done < "$CF_IPV4_FILE"
# 填充规则(IPv6)
while read -r ip; do
ip6tables -A CF_INPUT -s "$ip" -p tcp -m multiport --dports 80,443 -j ACCEPT
done < "$CF_IPV6_FILE"
# 拒绝非 Cloudflare 的 80/443 流量
iptables -A CF_INPUT -p tcp -m multiport --dports 80,443 -j DROP
ip6tables -A CF_INPUT -p tcp -m multiport --dports 80,443 -j DROP
# 将链挂载到 INPUT
insert_rule() {
local ipt_cmd="$1"
if ! $ipt_cmd -C INPUT -p tcp -m multiport --dports 80,443 -j CF_INPUT >/dev/null 2>&1; then
$ipt_cmd -I INPUT 1 -p tcp -m multiport --dports 80,443 -j CF_INPUT
fi
}
insert_rule iptables
insert_rule ip6tables
# 保存规则(适用于 Debian/Ubuntu)
if command -v iptables-save &> /dev/null; then
iptables-save | sudo tee /etc/iptables/rules.v4 >/dev/null
ip6tables-save | sudo tee /etc/iptables/rules.v6 >/dev/null
fi
echo "----------------------------------------"
echo " 已成功配置仅允许 Cloudflare IP 访问 80/443 端口!"
echo " 请手动执行以下操作确保 SSH 访问:"
echo "----------------------------------------"
echo "1. 允许 SSH 端口(如果尚未允许):"
echo " iptables -A INPUT -p tcp --dport 22 -j ACCEPT"
echo " ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT"
echo "2. 设置默认入站策略为 DROP(谨慎操作!):"
echo " iptables -P INPUT DROP"
echo " ip6tables -P INPUT DROP"
echo "3. 保存规则:"
echo " iptables-save > /etc/iptables/rules.v4"
echo " ip6tables-save > /etc/iptables/rules.v6"
echo "----------------------------------------"
运行脚本后会自动下载cloudflare IPV4/6白名单并设置443,80端口仅限白名单IP访问
我们可以通过以下几种方法来验证 Cloudflare IP 规则是否正确应用到了 443 端口:
sudo iptables -L CF_INPUT -n -v
sudo ip6tables -L CF_INPUT -n -v
通过上述方案可以显著提高vps的安全,即使源站IP暴露攻击者也无法绕过cloud flare进行攻击

Comments 1 条评论
蛮不错的