服务器访问黑白名单批量添加删除脚本
运维服务器时,经常需要封禁恶意 IP 或放行特定 IP。
手动一条条敲 iptables 规则不仅慢,还容易漏掉或输错。
本文带零基础用户手写一个能批量添加/删除黑白名单的 shell 脚本,只要准备好 IP 列表文件,一条命令就能完成全部操作。
适用场景与准备工作
这个脚本适合以下场景:
- 网站或 API 被大量恶意扫描,需要快速批量封禁来源 IP。
- 内部服务只允许指定 IP 段访问,需要批量加入白名单。
- 临时解封一批 IP,一次性删除旧规则。
准备条件:
- 一台 Linux 服务器(CentOS 7+ 或 Ubuntu 18.04+ 均可),拥有 root 权限。
- iptables 服务已安装且运行中。未安装时执行:
# CentOS
yum install -y iptables-services && systemctl start iptables && systemctl enable iptables
# Ubuntu
apt install -y iptables-persistent
- 准备一个纯文本的 IP 列表文件,每行一个 IP 或 IP 段(如 192.168.1.0/24),不需要引号或逗号。例如
/root/blacklist.txt。
批量添加黑名单脚本详解
创建一个脚本文件 add_blacklist.sh,内容如下:
#!/bin/bash
# 批量添加 IP 到 iptables INPUT 链(黑名单)
IP_LIST="/root/blacklist.txt"
CHAIN_NAME="INPUT"
if [ ! -f "$IP_LIST" ]; then
echo "错误:IP 列表文件 $IP_LIST 不存在"
exit 1
fi
while IFS= read -r ip; do
# 跳过空行和注释
[[ -z "$ip" || "$ip" =~ ^# ]] && continue
# 添加规则(DROP 所有来源 IP 的流量)
iptables -A $CHAIN_NAME -s "$ip" -j DROP
if [ $? -eq 0 ]; then
echo "已添加黑名单: $ip"
else
echo "添加失败: $ip"
fi
done < "$IP_LIST"
关键说明:
CHAIN_NAME可根据需要改为FORWARD或自定义链。-A表示追加规则到链末尾。若要插到最前面(优先生效),可将-A改为-I $CHAIN_NAME 1。- 脚本会自动跳过以
#开头的注释行和空行,方便 IP 列表文件中写备注。
保存后赋予执行权限:
chmod +x add_blacklist.sh
执行脚本前建议先备份当前规则:iptables-save > /root/iptables_backup_$(date +%Y%m%d).rules
批量删除白名单脚本详解
白名单脚本类似,只是将动作改为 ACCEPT,并放到 INPUT 链靠前位置(或者使用 -I 插入)。
不过更常见的白名单场景是“仅允许白名单 IP 访问,其余拒绝”,这时需要配合策略顺序。
以下脚本用于批量添加白名单规则(允许来源 IP 访问):
#!/bin/bash
# 批量添加白名单 IP 到 iptables INPUT 链(放行)
IP_LIST="/root/whitelist.txt"
CHAIN_NAME="INPUT"
if [ ! -f "$IP_LIST" ]; then
echo "错误:IP 列表文件 $IP_LIST 不存在"
exit 1
fi
# 先设置默认策略为 DROP(如果不希望放行其他 IP)
# iptables -P INPUT DROP # 谨慎使用,先确保 SSH 已加白
while IFS= read -r ip; do
[[ -z "$ip" || "$ip" =~ ^# ]] && continue
iptables -I $CHAIN_NAME 1 -s "$ip" -j ACCEPT
if [ $? -eq 0 ]; then
echo "已添加白名单: $ip"
else
echo "添加失败: $ip"
fi
done < "$IP_LIST"
删除规则:如果要从黑名单或白名单中移除一批 IP,可以使用 -D 参数。
下面是一个通用的批量删除脚本(移除匹配-s和-j动作的规则):
#!/bin/bash
# 批量删除指定 IP 的 iptables 规则(不限动作)
IP_LIST="/root/delete_list.txt"
CHAIN_NAME="INPUT"
ACTION="DROP" # 改为 ACCEPT 可删除白名单规则
while IFS= read -r ip; do
[[ -z "$ip" || "$ip" =~ ^# ]] && continue
# 使用 -D 删除,注意一条规则可能匹配多个,只删除第一条匹配
iptables -D $CHAIN_NAME -s "$ip" -j $ACTION 2>/dev/null
if [ $? -eq 0 ]; then
echo "已删除规则: $ip ($ACTION)"
else
echo "未找到规则: $ip"
fi
done < "$IP_LIST"
注意: iptables -D 只能删除与指定参数完全匹配的第一条规则。
如果同 IP 有多个规则(如同时有 ACCEPT 和 DROP),需要指定 -D 多次或使用规则序号删除。
常见错误与避坑提醒
- 规则没有持久化:重启后 iptables 规则会丢失。需要在执行完脚本后保存:
# CentOS
service iptables save
# Ubuntu(安装 iptables-persistent 后)
netfilter-persistent save
- IP 列表格式错误:不要包含空格、多余逗号或协议前缀。每行一个 IP 或 CIDR 段即可。
- 脚本执行后 SSH 断开:如果你正在通过 SSH 操作,并且脚本将默认策略改为 DROP 或误删白名单,可能导致自己被封。建议先用
tmux或screen保持会话,或先在测试环境验证。 - 重复添加规则:每次执行
-A都会追加相同规则,导致多条重复。可以考虑先检查是否已存在:iptables -C INPUT -s 1.2.3.4 -j DROP(-C检查是否存在)。如果不需要检查,也可以用脚本先清空链再批量添加(但会中断现有连接)。
效果验证与问题排查
添加完成后,用以下命令查看规则:
iptables -L INPUT -n --line-numbers
重点关注:
- 新增的 IP 是否出现在链中。
- 规则顺序是否符合预期(白名单靠前,黑名单可靠后)。
- 计数器
pkts和bytes是否增长(代表有匹配流量)。
测试某个 IP 是否被封:
# 从另一台机器尝试 ping 或 curl,或者直接在本机用 iptables 的 -vL 看计数器
ping -c 3 被封IP
# 如果回显“Destination Host Unreachable”或超时,说明规则生效。
常见异常:
- 执行脚本提示“iptables: No chain/target/match by that name”:检查
CHAIN_NAME是否拼写正确,先用iptables -L查看可用链。 - 批量删除时有些 IP 未删除:可能是规则序号不在预期位置。可以使用
iptables -L INPUT -n --line-numbers获取准确序号,再用iptables -D INPUT <序号>手动删除。 - 添加白名单后仍无法访问:检查是否还有更高优先级的 DROP 规则(如默认策略或前面的黑名单)。调整规则顺序。
批量管理黑白名单的脚本非常实用,尤其当 IP 列表频繁更新时。
你可以将 IP 列表文件放在定时任务中,结合防火墙和 fail2ban 实现自动化封禁。
如果你在使用宝塔面板或 Nginx,也可以参考我们的相关教程。