原文传送门:halo.4w.ink/?p=019ce628…
刚买的云服务器,一查
lastb 居然满屏幕都是爆破记录? 别再只改 SSH 端口了,那只是掩耳盗铃。分享一套我最近刚落地的自动化防御方案:
1.你的服务器正在被“围攻”吗?
如果你拥有一台暴露在公网上的 Linux 服务器,不妨现在就执行一下
lastb 命令。
看到那满屏幕、甚至几分钟就跳动一次的 ssh:notty 记录了吗?这些都是来自全球各地的自动化脚本,正在利用弱口令字典对你的 22 端口进行疯狂的暴力破解。在黑暗的网络角落里,数以万计的机器人每天都在不停地尝试敲开你的大门。
2.改端口真的安全吗?
很多管理员的第一反应是修改 SSH 默认端口。诚然,这能过滤掉 90% 的低级扫描,但在专业的端口扫描工具(如 Nmap)面前,这种做法无异于掩耳盗铃。
- 防护滞后:你不知道谁在攻击你,直到服务器被攻破的那一刻。
- 反馈缺失:传统的防火墙只会默默地拦截,管理员无法实时感知攻击频率和来源,处于信息孤岛。
- 误伤隐患:如果你自己输错密码被锁,可能需要通过繁琐的控制台(VNC)去救援。
我们真正需要的,不是一个死板的“防盗门”,而是一个带监控的智能安保系统:它既能自动驱逐入侵者,又能第一时间把“抓获现场”的消息推送到你的手机上。
3.Fail2Ban + Webhook 的强强联手
为了实现这种“自动防御+即时反馈”的机制,我们将目光投向了两个利器:
- Fail2Ban(防火墙守卫) :它是 Linux 下最著名的入侵防御框架。通过监听日志文件,它能在检测到多次登录失败后,自动调用
iptables或ufw策略将恶意 IP 永久或暂时封禁。 - Webhook(即时通讯桥梁) :它是现代应用间通信的纽带。我们将 Fail2Ban 的封禁动作(Action)与企业微信、飞书或钉钉的 Webhook API 进行联动。
最终效果: 只要有人尝试爆破你的 SSH 密码,Fail2Ban 会在几秒钟内将其 IP “拉黑”,并在你的手机即时通讯工具中弹出一张精美的告警卡片,告诉你: “别担心,不速之客已被拦截!”
4.Fail2Ban 安装配置
创建一个sh文件,将下方内容复制至文件中保存,通过 bash you-file-name.sh执行
💡该脚本会自动识别系统版本并安装必要的 rsyslog 组件,确保日志能够被正常读取。
#!/bin/bash
# Install Fail2ban
# Support Ubuntu/Debian/CentOS/RHEL/Almalinux/Alpine/Arch Linux
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
VERSION=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
VERSION=$(lsb_release -sr)
elif [ -f /etc/redhat-release ]; then
OS="rhel"
VERSION=$(grep -oE '[0-9]+.[0-9]+' /etc/redhat-release)
elif [ -f /etc/alpine-release ]; then
OS="alpine"
VERSION=$(cat /etc/alpine-release)
else
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
VERSION=$(uname -r)
fi
}
install_fail2ban() {
echo -e "${GREEN}Detected system: $OS $VERSION${NC}"
case "$OS" in
ubuntu|debian)
apt-get update
if ! command -v rsyslogd >/dev/null 2>&1; then
echo -e "${YELLOW}rsyslog not installed. installing rsyslog...${NC}"
apt-get install -y rsyslog
else
echo -e "${GREEN}rsyslog is already installed.${NC}"
fi
apt-get install -y fail2ban
;;
centos|rhel|fedora|almalinux)
if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
dnf install -y epel-release
dnf install -y fail2ban
else
yum install -y epel-release
yum install -y fail2ban
fi
;;
alpine)
apk add --no-cache fail2ban
;;
arch)
pacman -Sy --noconfirm fail2ban
;;
*)
echo -e "${RED}Unsupported system${NC}"
exit 1
;;
esac
}
configure_fail2ban() {
echo -e "${GREEN}Configure Fail2ban...${NC}"
FAIL2BAN_CONF="/etc/fail2ban/jail.local"
LOG_FILE=""
BAN_ACTION=""
if systemctl is-active --quiet firewalld 2>/dev/null; then
BAN_ACTION="firewallcmd-ipset"
elif systemctl is-active --quiet ufw 2>/dev/null || service ufw status 2>/dev/null | grep -q "active"; then
BAN_ACTION="ufw"
else
BAN_ACTION="iptables-allports"
fi
if [ -f /var/log/secure ]; then
LOG_FILE="/var/log/secure"
else
LOG_FILE="/var/log/auth.log"
[ -f "$LOG_FILE" ] || touch "$LOG_FILE"
fi
cat <<EOF > "$FAIL2BAN_CONF"
#DEFAULT-START
[DEFAULT]
bantime = 600
findtime = 300
maxretry = 5
banaction = $BAN_ACTION
action = %(action_mwl)s
#DEFAULT-END
[sshd]
ignoreip = 127.0.0.1/8
enabled = true
filter = sshd
port = 22
maxretry = 5
findtime = 300
bantime = 600
banaction = $BAN_ACTION
action = %(action_mwl)s
logpath = $LOG_FILE
EOF
}
start_service() {
echo -e "${GREEN}Start Fail2ban...${NC}"
case "$OS" in
ubuntu|debian)
systemctl enable fail2ban
systemctl restart fail2ban
;;
centos|rhel|fedora|almalinux)
systemctl enable fail2ban
systemctl restart fail2ban
;;
alpine)
rc-update add fail2ban
rc-service fail2ban start
;;
arch)
systemctl enable fail2ban
systemctl restart fail2ban
;;
*)
echo -e "${YELLOW}The service cannot be started automatically. Please start manually!${NC}"
;;
esac
if command -v systemctl &> /dev/null; then
systemctl status fail2ban || true
else
rc-service fail2ban status || true
fi
echo -e "${GREEN}Fail2ban is installed and started${NC}"
}
main() {
detect_os
install_fail2ban
configure_fail2ban
start_service
}
main "$@"
5.Fail2Ban 配置文件修改
如果你使用了第 4 节的一键脚本,基本的 jail.local 已经创建好了。本节主要用于讲解各项参数的含义,方便你进行个性化微调(如修改封禁时长、白名单等)
配置文件目录: /etc/fail2ban/jail.local
[sshd]
# 激活此监狱配置,设置为 true 才会生效
enabled = true
# 监控的端口号,如果你修改了 SSH 默认端口(比如改为 2222),这里也要同步修改
port = 22
# 指定使用的过滤器,通常对应 /etc/fail2ban/filter.d/sshd.conf,定义了匹配错误登录的正则表达式
filter = sshd
# Fail2Ban 扫描的日志文件路径。Ubuntu/Debian 通常是 /var/log/auth.log,CentOS 则是 /var/log/secure
logpath = /var/log/auth.log
# 最大尝试次数。在 findtime 时间段内,如果失败次数达到 2 次,该 IP 就会被封禁
maxretry = 2
# 统计失败次数的时间范围。这里指 60 秒内如果失败 2 次,即触发封禁条件
findtime = 60s
# 封禁时长。设置为 -1 代表“永久封禁”(慎用,除非你有极强的安全信心或配置了白名单)
bantime = -1
# 触发封禁后执行的动作(Action)。
# 这里采取了多 Action 组合模式:
# 1. 调用 ufw 动作进行防火墙拦截
# 2. 调用自定义的 wechat-webhook 动作发送微信通知
# 注意:多行 action 的写法中,后续行必须有缩进,以表示它们隶属于同一个 action 配置项
action = ufw
wechat-webhook
⚠️ 重要提醒:在正式重启 Fail2Ban 之前,请务必在 [sshd] 段落中加入 ignoreip = 127.0.0.1/8 你的办公室或家里的公网IP 。 否则,万一你自己输错两次密码,由于设置了 bantime = -1 ,你将被永久锁在服务器外!
6.联动Webhook脚本
mkdir -p /etc/fail2ban/action.d/
vim /etc/fail2ban/action.d/wechat-webhook.conf
💡 小贴士:如果收到通知的时间比北京时间慢了 8 小时,请参考以下命令修正系统时区: sudo timedatectl set-timezone Asia/Shanghai 。
粘贴以下内容(替换你的 Webhook 地址)
[Definition]
# 封禁动作(红色/橙色警告)
actionban = curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=[替换你的key]" -H "Content-Type: application/json" -d "{"msgtype":"markdown","markdown":{"content":"⚠️ **SSH暴力破解告警**\n> 被封禁IP:<font color=\"warning\"> <ip> </font>\n> 封禁时间:$(date +'%%Y-%%m-%%d %%H:%%M:%%S')\n> 失败次数:<failures>次\n> 封禁时长:永久封禁"}}"
# 封禁时长:<bantime>秒,我的配置bantime = -1所以是永久封禁
# 解封动作(绿色通知)
actionunban = curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=[替换你的key]" -H "Content-Type: application/json" -d "{"msgtype":"markdown","markdown":{"content":"✅ **SSH封禁自动解除**\n> 解禁IP:<font color=\"comment\"> <ip> </font>\n> 解禁时间:$(date +'%%Y-%%m-%%d %%H:%%M:%%S')\n> 状态:防火墙规则已移除"}}"
[Init]
7.配置文件检查
# 配置文件自检
fail2ban-client -t
# 返回OK: configuration test is successful 就是通过
# 重启fail2ban
systemctl restart fail2ban
8.通知测试
手动封禁
fail2ban-client set sshd banip 1.4.4.4
手动解封
fail2ban-client set sshd unbanip 1.4.4.4
当有人爆破时,你会收到这样的红色预警
当管理员确认安全并手动解封后,会收到绿色通知
9.常用命令
# 重启服务
sudo systemctl restart fail2ban
# 重载配置-不重启服务,仅重新加载配置文件,更平滑
sudo fail2ban-client reload
# 启动/停止/查看服务状态
sudo systemctl start fail2ban
sudo systemctl stop fail2ban
sudo systemctl status fail2ban
# 状态查询命令
查看 Fail2Ban 运行概况(可以看到当前激活了哪些“监狱”)
sudo fail2ban-client status
# 查看特定监狱的详细信息
sudo fail2ban-client status sshd
# 手动解禁某个IP
sudo fail2ban-client set sshd unbanip <你的IP地址>
# 手动封禁某个IP
sudo fail2ban-client set sshd banip <恶意IP地址>