外观
Fail2ban 管理面板
约 1797 字大约 6 分钟
Shell安全防护Fail2ban运维工具
2026-01-16
交互式 Fail2ban 管理脚本,无需手动编辑配置文件,通过菜单管理封禁、白名单和参数。
功能特性
| 特性 | 说明 |
|---|---|
| 🛡️ 一键安装 | 自动检测并安装 Fail2ban |
| ⚙️ 参数配置 | 菜单式修改封禁参数 |
| 🔓 解封管理 | 快速解封被封禁的 IP |
| 📋 白名单 | 添加 IP 到白名单 |
| 📊 日志查看 | 查看封禁/解封记录 |
| 📈 指数封禁 | 支持递增封禁时长配置 |
快速开始
# 下载脚本
curl -sL https://script.merma.cn/scripts/shell/SecurityScript/fail2ban_manager.sh -o fail2ban_manager.sh
chmod +x fail2ban_manager.sh
# 运行管理面板 (需要 root 权限)
sudo ./fail2ban_manager.sh演示效果
################################################
# Fail2ban 管理面板 (v1.0) #
################################################
状态: 运行中 (Active) | 当前封禁数: 3
------------------------------------------------
1. 最大重试次数 [5]
2. 初始封禁时长 [600] 600秒
3. 监测时间窗口 [3600] 3600秒
------------------------------------------------
4. 手动解封 IP
5. 添加白名单
6. 查看封禁日志
7. 指数封禁设置 ->
------------------------------------------------
8. 开启/停止 服务
0. 退出
请选择 [0-8]:指数封禁设置
=== 高级: 指数封禁设置 ===
说明: 对重复犯错的 IP 封禁时间成倍增加。
-------------------------------------------
1. 递增模式开关 [开启]
2. 增长系数 [2] 2倍
3. 封禁上限 [86400] 86400秒
-------------------------------------------
0. 返回功能说明
| 功能 | 说明 |
|---|---|
| 最大重试次数 | 允许的失败登录尝试次数 |
| 初始封禁时长 | 首次封禁的持续时间 |
| 监测时间窗口 | 统计失败尝试的时间范围 |
| 手动解封 IP | 立即解除指定 IP 的封禁 |
| 添加白名单 | 将 IP 加入白名单永不封禁 |
| 指数封禁 | 重复违规者封禁时间递增 |
配置文件
脚本会自动管理 /etc/fail2ban/jail.local 配置文件:
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 600
findtime = 3600
backend = auto
banaction = iptables-multiport
ignoreip = 127.0.0.1/8环境要求
- 操作系统: Linux (RockyLinux, Ubuntu, Debian, CentOS)
- 权限: root
- 依赖: fail2ban (脚本可自动安装)
注意事项
- 运行前请确保使用 root 用户或 sudo
- 建议先将当前 SSH 连接 IP 加入白名单
- 修改配置后会自动重启 Fail2ban 服务
脚本源码
点击展开查看完整源码
#!/bin/bash
# ==============================================================================
# Fail2ban Interactive Manager (F2B Panel) - Chinese Version
# Description: Linux Fail2ban 管理脚本 (中文版)
# Author: Kequans & ISFZY
# License: MIT License
# ==============================================================================
RED="\033[31m"; GREEN="\033[32m"; YELLOW="\033[33m"
BLUE="\033[36m"; GRAY="\033[90m"; PLAIN="\033[0m"
JAIL_CONF="/etc/fail2ban/jail.local"
LOG_FILE="/var/log/fail2ban.log"
[[ $EUID -ne 0 ]] && echo -e "${RED}错误:${PLAIN} 必须使用 root 用户运行此脚本!" && exit 1
check_install() {
if ! command -v fail2ban-client >/dev/null 2>&1; then
echo -e "${YELLOW}未检测到 Fail2ban 服务。${PLAIN}"
read -p "是否立即安装 Fail2ban 和 Rsyslog?(y/n): " install_confirm
if [[ "$install_confirm" == "y" ]]; then
echo -e "${BLUE}正在安装 Fail2ban 和 Rsyslog...${PLAIN}"
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y fail2ban rsyslog
elif command -v yum >/dev/null 2>&1; then
yum install -y fail2ban rsyslog
else
echo -e "${RED}未识别的包管理器,请手动安装 Fail2ban。${PLAIN}"; exit 1
fi
[ ! -f /var/log/auth.log ] && touch /var/log/auth.log
systemctl enable rsyslog && systemctl start rsyslog
if [ ! -f "$JAIL_CONF" ]; then
cat > "$JAIL_CONF" << 'EOF'
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 600
findtime = 3600
backend = auto
banaction = iptables-multiport
ignoreip = 127.0.0.1/8
EOF
fi
systemctl enable fail2ban && systemctl restart fail2ban
echo -e "${GREEN}安装并启动完成!${PLAIN}"; sleep 2
else
echo -e "${RED}已取消安装。${PLAIN}"; exit 0
fi
fi
[ ! -f "$JAIL_CONF" ] && cp /etc/fail2ban/jail.conf "$JAIL_CONF"
}
get_conf() { grep "^${1}\s*=" "$JAIL_CONF" | awk -F'=' '{print $2}' | tr -d ' '; }
set_conf() {
local key=$1 val=$2
if grep -q "^${key}\s*=" "$JAIL_CONF"; then
sed -i "s/^${key}\s*=.*/${key} = ${val}/" "$JAIL_CONF"
elif grep -q "\[sshd\]" "$JAIL_CONF"; then
sed -i "/\[sshd\]/a ${key} = ${val}" "$JAIL_CONF"
else
echo "${key} = ${val}" >> "$JAIL_CONF"
fi
}
restart_f2b() {
echo -e "${BLUE}正在重载 Fail2ban 配置...${PLAIN}"
systemctl restart fail2ban; sleep 1
fail2ban-client ping >/dev/null 2>&1 && echo -e "${GREEN}成功!配置已生效。${PLAIN}" || echo -e "${RED}Fail2ban 重启失败。${PLAIN}"
read -n 1 -s -r -p "按任意键继续..."
}
get_status() {
if fail2ban-client ping >/dev/null 2>&1; then
local count=$(fail2ban-client status sshd 2>/dev/null | grep "Currently banned" | grep -o "[0-9]*")
echo -e "${GREEN}运行中 (Active)${PLAIN} | 当前封禁数: ${RED}${count:-0}${PLAIN}"
else
echo -e "${RED}已停止 (Stopped)${PLAIN}"
fi
}
fmt_unit() {
local val=$1 type=$2
[[ "$val" =~ ^[0-9]+$ ]] && { [ "$type" == "time" ] && echo "${val}秒" || [ "$type" == "factor" ] && echo "${val}倍" || echo "$val"; } || echo "$val"
}
validate_time() { [[ "$1" =~ ^[0-9]+[smhdw]?$ ]]; }
validate_int() { [[ "$1" =~ ^[0-9]+(\.[0-9]+)?$ ]]; }
change_param() {
local name=$1 key=$2 type=$3 current=$(get_conf "$key")
echo -e "\n${BLUE}正在修改: ${name}${PLAIN}\n当前值: ${GREEN}$(fmt_unit "$current" "$type")${PLAIN}"
[ "$type" == "time" ] && echo -e "${GRAY}(支持后缀: s=秒, m=分, h=小时, d=天)${PLAIN}"
while true; do
read -p "请输入新值 (留空取消): " new_val; [ -z "$new_val" ] && return
{ [ "$type" == "time" ] && validate_time "$new_val"; } || { [ "$type" == "int" ] && validate_int "$new_val"; } || { [ "$type" == "factor" ] && validate_int "$new_val"; } && break
echo -e "${RED}格式错误,请重试。${PLAIN}"
done
set_conf "$key" "$new_val"; restart_f2b
}
toggle_service() {
echo -e "\n${BLUE}--- 服务开关 ---${PLAIN}"
if fail2ban-client ping >/dev/null 2>&1; then
read -p "是否停止并禁用 Fail2ban? (y/n): " confirm
[[ "$confirm" == "y" ]] && { systemctl stop fail2ban; systemctl disable fail2ban; echo -e "${RED}服务已停止。${PLAIN}"; }
else
read -p "是否启用并启动 Fail2ban? (y/n): " confirm
[[ "$confirm" == "y" ]] && { systemctl enable fail2ban; systemctl start fail2ban; echo -e "${GREEN}服务已启动。${PLAIN}"; }
fi
read -n 1 -s -r -p "按任意键继续..."
}
unban_ip() {
echo -e "\n${BLUE}--- 手动解封 IP ---${PLAIN}"
local banned_list=$(fail2ban-client status sshd 2>/dev/null | grep "Banned IP list" | awk -F':' '{print $2}' | sed 's/^[ \t]*//')
echo -e "当前被封禁列表: ${RED}${banned_list:-无}${PLAIN}"
read -p "输入要解封的 IP (留空取消): " target_ip; [ -z "$target_ip" ] && return
fail2ban-client set sshd unbanip "$target_ip" && echo -e "${GREEN}解封成功: $target_ip${PLAIN}" || echo -e "${RED}操作失败。${PLAIN}"
read -n 1 -s -r -p "按任意键继续..."
}
add_whitelist() {
echo -e "\n${BLUE}--- 白名单管理 ---${PLAIN}"
local current_list=$(grep "^ignoreip" "$JAIL_CONF" | awk -F'=' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//')
echo -e "当前白名单: ${YELLOW}${current_list:-无}${PLAIN}"
local current_ip=$(echo $SSH_CLIENT | awk '{print $1}')
read -p "输入要放行的 IP (回车默认本机 ${current_ip}): " input_ip
[ -z "$input_ip" ] && input_ip="$current_ip"
[ -z "$input_ip" ] && { echo -e "${RED}无法获取 IP。${PLAIN}"; return; }
echo "$current_list" | grep -Fq "$input_ip" && echo -e "${YELLOW}该 IP 已在白名单中。${PLAIN}" || { sed -i "/^ignoreip/ s/$/ ${input_ip}/" "$JAIL_CONF"; restart_f2b; }
}
view_logs() {
clear; echo -e "${BLUE}=== 审计日志 (最近 20 条) ===${PLAIN}"
[ -f "$LOG_FILE" ] && grep -E "(Ban|Unban)" "$LOG_FILE" 2>/dev/null | tail -n 20 | awk '{gsub(/Unban/, "\033[32m&\033[0m"); gsub(/Ban/, "\033[31m&\033[0m"); print}' || echo -e "${YELLOW}日志文件不存在${PLAIN}"
echo "----------------------------------------------"; read -n 1 -s -r -p "按任意键返回..."
}
menu_exponential() {
while true; do
clear
local inc=$(get_conf "bantime.increment") fac=$(get_conf "bantime.factor") max=$(get_conf "bantime.maxtime")
[ "$inc" == "true" ] && S_INC="${GREEN}开启${PLAIN}" || S_INC="${RED}关闭${PLAIN}"
echo -e "${BLUE}=== 高级: 指数封禁设置 ===${PLAIN}\n说明: 对重复犯错的 IP 封禁时间成倍增加。\n-------------------------------------------"
echo -e " 1. 递增模式开关 [${S_INC}]\n 2. 增长系数 [${YELLOW}${fac:-未设置}${PLAIN}]\n 3. 封禁上限 [${YELLOW}${max:-未设置}${PLAIN}]\n-------------------------------------------\n 0. 返回\n"
read -p "请选择 [0-3]: " sc
case "$sc" in
1) [ "$inc" == "true" ] && ns="false" || ns="true"; set_conf "bantime.increment" "$ns"; restart_f2b ;;
2) change_param "增长系数 (倍数)" "bantime.factor" "factor" ;;
3) change_param "封禁上限 (时间)" "bantime.maxtime" "time" ;;
0) return ;;
esac
done
}
menu_main() {
check_install
while true; do
clear
VAL_MAX=$(get_conf "maxretry"); VAL_BAN=$(get_conf "bantime"); VAL_FIND=$(get_conf "findtime")
echo -e "${BLUE}################################################${PLAIN}"
echo -e "${BLUE}# Fail2ban 管理面板 (v1.0) #${PLAIN}"
echo -e "${BLUE}################################################${PLAIN}"
echo -e " 状态: $(get_status)\n------------------------------------------------"
echo -e " 1. 最大重试次数 [${YELLOW}${VAL_MAX}${PLAIN}]"
echo -e " 2. 初始封禁时长 [${YELLOW}${VAL_BAN}${PLAIN}] $(fmt_unit "${VAL_BAN}" "time")"
echo -e " 3. 监测时间窗口 [${YELLOW}${VAL_FIND}${PLAIN}] $(fmt_unit "${VAL_FIND}" "time")"
echo -e "------------------------------------------------"
echo -e " 4. 手动解封 IP\n 5. 添加白名单\n 6. 查看封禁日志\n 7. 指数封禁设置 ->"
echo -e "------------------------------------------------\n 8. 开启/停止 服务\n 0. 退出\n"
read -p "请选择 [0-8]: " choice
case "$choice" in
1) change_param "最大重试次数" "maxretry" "int" ;;
2) change_param "初始封禁时长" "bantime" "time" ;;
3) change_param "监测时间窗口" "findtime" "time" ;;
4) unban_ip ;; 5) add_whitelist ;; 6) view_logs ;; 7) menu_exponential ;; 8) toggle_service ;;
0) clear; exit 0 ;;
esac
done
}
menu_main