安全加固:关闭 X11Forwarding、清理 nginx 遗留垃圾、爆破告警改状态机去重(停止后再犯才提醒)

This commit is contained in:
夏犀麟 2026-09-11 23:57:33 +08:00
parent 09ccc59ebf
commit 247afdd8ff
3 changed files with 26 additions and 5 deletions

View File

@ -3,3 +3,5 @@
- 22:40 | FIX | 服务器监控脚本告警去重改造fail2ban 封禁 IP 改为「仅新增封禁推送一次」。**原因**=IP `157.230.37.93` 被 fail2ban 封禁后bantime 1h脚本每 10 分钟重复推送 Bark 告警(日志 21:40~22:30 连续 6 条 ALERT。**根因**=脚本第 3 段逻辑为「Banned IP list 非空即 alert」无状态记忆。**改法**=新增状态文件 `/var/lib/server-monitor/banned-ips.state`(记录当前已封禁 IP 集合),仅对不在集合中的 IP 告警;状态同步为当前封禁列表,已解封 IP 自动移出(日后再被封视为新事件、可再提醒)。**验证**=真实环境当前封禁「本轮告警=无→静默」;模拟 5 轮全部符合预期(新封→提醒 / 列表不变→静默 / 解封→剔除 / 再封→再提醒 / 全解封→清空);`bash -n` 语法通过。**留档**=脚本备份 `/usr/local/bin/server-monitor.sh.bak.20260911`;本地副本 `.workbuddy/tmp/server-monitor.sh`。**顺带记录**=cron 位置确认为 xxcool crontab`*/10 * * * * sudo /usr/local/bin/server-monitor.sh`bantime=1h/findtime=10m/maxretry=5`/etc/fail2ban/jail.local`);日志 204K 暂无需轮转。 - 22:40 | FIX | 服务器监控脚本告警去重改造fail2ban 封禁 IP 改为「仅新增封禁推送一次」。**原因**=IP `157.230.37.93` 被 fail2ban 封禁后bantime 1h脚本每 10 分钟重复推送 Bark 告警(日志 21:40~22:30 连续 6 条 ALERT。**根因**=脚本第 3 段逻辑为「Banned IP list 非空即 alert」无状态记忆。**改法**=新增状态文件 `/var/lib/server-monitor/banned-ips.state`(记录当前已封禁 IP 集合),仅对不在集合中的 IP 告警;状态同步为当前封禁列表,已解封 IP 自动移出(日后再被封视为新事件、可再提醒)。**验证**=真实环境当前封禁「本轮告警=无→静默」;模拟 5 轮全部符合预期(新封→提醒 / 列表不变→静默 / 解封→剔除 / 再封→再提醒 / 全解封→清空);`bash -n` 语法通过。**留档**=脚本备份 `/usr/local/bin/server-monitor.sh.bak.20260911`;本地副本 `.workbuddy/tmp/server-monitor.sh`。**顺带记录**=cron 位置确认为 xxcool crontab`*/10 * * * * sudo /usr/local/bin/server-monitor.sh`bantime=1h/findtime=10m/maxretry=5`/etc/fail2ban/jail.local`);日志 204K 暂无需轮转。
- 23:00 | CHG | 监控脚本告警去重**终版**(三项全部去重,状态目录 `/var/lib/server-monitor/`):① fail2ban 封禁 IP 改为**永久去重**`banned-ips.state` 只增不减,同一 IP 此生只提醒一次,解封不重置);② 新增「**新来源 IP 登录**」替代原「新增 SSH 登录」(`ssh-src-ips.state`,只有没见过的 IP 首次登录才提醒,避免自己日常登录刷屏);③ 未登记端口漂移同样只提醒一次(`ports.state`,端口消失后清除)。**验证**=预置 30 天内 16 个已知登录 IP + 当前封禁 IP 后手动执行,输出 `[OK]`、零 Bark 推送;`bash -n` 通过。完整审计仍在 `/var/log/fail2ban.log` + journald且已上报 admin 后台,去重不影响追溯。 - 23:00 | CHG | 监控脚本告警去重**终版**(三项全部去重,状态目录 `/var/lib/server-monitor/`):① fail2ban 封禁 IP 改为**永久去重**`banned-ips.state` 只增不减,同一 IP 此生只提醒一次,解封不重置);② 新增「**新来源 IP 登录**」替代原「新增 SSH 登录」(`ssh-src-ips.state`,只有没见过的 IP 首次登录才提醒,避免自己日常登录刷屏);③ 未登记端口漂移同样只提醒一次(`ports.state`,端口消失后清除)。**验证**=预置 30 天内 16 个已知登录 IP + 当前封禁 IP 后手动执行,输出 `[OK]`、零 Bark 推送;`bash -n` 通过。完整审计仍在 `/var/log/fail2ban.log` + journald且已上报 admin 后台,去重不影响追溯。
- 23:05 | SEC | **服务器入侵排查(只读体检)结论:未发现被入侵迹象**。查了 15 类UID0 账号仅 root、无空密码账号、无异常 SUID、`ld.so.preload` 空、`rc.local` 仅腾讯云自身脚本、shell 配置无下载/反弹特征、`/etc/hosts` 无劫持、近 30 天系统目录无改动、无特权容器、无异常内核模块。SSH 成功率来源 IP 全部为本人出口且指纹 = 本地 `xpcool_ed25519``SHA256:GKWT/a9o…``authorized_keys` 仅 3 把(旧 `skey-q6pq6jb3` 已移除)。外网暴露面=**仅 22025/80/443**3000/2222/8081/8080/8082/18080/10100/3306 实测全部阻断。**两个"未知物"已查清**:① `/usr/local/bin/server-security-collector.sh`cron 每 5 分钟)是自建安全日志上报器,把 sshd 认证 + fail2ban Ban/Unban 增量 POST 到 `127.0.0.1:10100/api/service/open/security/log/report`,配置 `/etc/server-security.conf`、状态 `/var/lib/server-security/last.ts`,属正常业务;② `/tmp/cj.txt`libcurl cookie、`/tmp/http-server.log`9-3 临时调试)为历史残留,无害。**重要溯源发现**`1.204.105.116`(本机出口)曾于 **09-03 23:00 被自己的 fail2ban 封禁**,直到 09-04 23:00 才解封 —— 这正是当时「SSH 22025 超时」的真因(当时误判为安全组问题)。**待办建议**`X11Forwarding yes` 可关;`lighthouse` 账号(腾讯云自带 uid1000也是 NOPASSWD ALL可考虑锁定nginx conf.d 内有 `.code.xpcool.com.conf.swo`、`tool.xpcool.com.conf.download.0` 等遗留文件可清理。 - 23:05 | SEC | **服务器入侵排查(只读体检)结论:未发现被入侵迹象**。查了 15 类UID0 账号仅 root、无空密码账号、无异常 SUID、`ld.so.preload` 空、`rc.local` 仅腾讯云自身脚本、shell 配置无下载/反弹特征、`/etc/hosts` 无劫持、近 30 天系统目录无改动、无特权容器、无异常内核模块。SSH 成功率来源 IP 全部为本人出口且指纹 = 本地 `xpcool_ed25519``SHA256:GKWT/a9o…``authorized_keys` 仅 3 把(旧 `skey-q6pq6jb3` 已移除)。外网暴露面=**仅 22025/80/443**3000/2222/8081/8080/8082/18080/10100/3306 实测全部阻断。**两个"未知物"已查清**:① `/usr/local/bin/server-security-collector.sh`cron 每 5 分钟)是自建安全日志上报器,把 sshd 认证 + fail2ban Ban/Unban 增量 POST 到 `127.0.0.1:10100/api/service/open/security/log/report`,配置 `/etc/server-security.conf`、状态 `/var/lib/server-security/last.ts`,属正常业务;② `/tmp/cj.txt`libcurl cookie、`/tmp/http-server.log`9-3 临时调试)为历史残留,无害。**重要溯源发现**`1.204.105.116`(本机出口)曾于 **09-03 23:00 被自己的 fail2ban 封禁**,直到 09-04 23:00 才解封 —— 这正是当时「SSH 22025 超时」的真因(当时误判为安全组问题)。**待办建议**`X11Forwarding yes` 可关;`lighthouse` 账号(腾讯云自带 uid1000也是 NOPASSWD ALL可考虑锁定nginx conf.d 内有 `.code.xpcool.com.conf.swo`、`tool.xpcool.com.conf.download.0` 等遗留文件可清理。
- 23:56 | SEC | **收尾加固三项全部完成**:① **关闭 X11Forwarding**:实际生效位置是 drop-in `/etc/ssh/sshd_config.d/50-redhat.conf:17`(主配置 `sshd_config:103` 是注释,被 Include 覆盖)→ 备份 `.bak.20260911` → sed 改为 `no``sshd -t` PASS → `sshd -T` 确认 `x11forwarding no``systemctl reload sshd`(不断连)成功。② **清理 nginx 遗留垃圾**`/data/nginx/conf.d/` 下 `.code.xpcool.com.conf.swo`vim 8.2 交换文件)与 `tool.xpcool.com.conf.download.0`(内容与 `tool.xpcool.com.conf` **完全相同**的下载残留);两者本就不匹配 include 规则 `*.conf` 未被加载 → 移入备份区 `/data/nginx/_junk_backup_20260911/`(未直接删,可回滚)→ `nginx -t` OK + reloadconf.d 现仅 8 个正式 `.conf`。全盘扫描 `/data/nginx` `/etc/nginx` 再无其他 `.swo/.swp/~/bak/download/save/orig/rej` 残留。③ **爆破告警改为状态机去重**:第 1 段原逻辑「10 分钟内失败 ≥10 即 alert」在攻击持续时会每 10 分钟刷屏 → 新增状态文件 `/var/lib/server-monitor/ssh-brute.state``attacking`/`idle`):进入攻击态时提醒一次并置 `attacking`;失败数回落时**静默复位**为 `idle`(只写 `[INFO]` 日志不推送);**下次再犯视为新一波,重新提醒一次**。告警内容同时增强(附失败次数最多的前 3 个来源 IP。**验证**=① 模拟 9 轮链路(开始→持续 3 轮→停止→平静→新一波→持续→再停):推送仅 2 次、复位 2 次、持续期间 0 推送 ✅;② 生产脚本手动执行输出 `[OK]`、零推送;③ 站点复验 file/admin/tool/read 四站全 HTTP 200。部署前已按当前失败数0预置状态为 `idle`,避免改造瞬间补推。脚本备份 `/usr/local/bin/server-monitor.sh.bak.20260911b`。**遗留待办**`lighthouse` 账号是否锁定待用户决策。
- 23:58 | DOC | 技能 `linux-server-security-audit` 更新:新增「周期复发型(爆破攻击)状态机去重」策略与代码模板(含"复位分支绝不调 alert()"要点、新增「SSH/sysctl 配置加固标准做法」(定位 drop-in 生效位置 → 备份 → `sshd -t` 预检失败自动回滚 → `sshd -T` 核对 → reload 不断连)、新增「配置目录遗留垃圾清理」小节(核对内容后移入备份区而非直接删)。

View File

@ -57,7 +57,7 @@
- 权限映射admin_menu type=2 行的 path 必须匹配实际路由(现为 `POST /api/service/admin/...`,见 manifest/sql/007_menu_permissions_v3.sql - 权限映射admin_menu type=2 行的 path 必须匹配实际路由(现为 `POST /api/service/admin/...`,见 manifest/sql/007_menu_permissions_v3.sql
- 文件下载站2026-09-03 上线,当晚迁移):`file.xpcool.com` = **FileBrowser Quantum** 容器 `fbq``gtstef/filebrowser:stable` v1.5.5`127.0.0.1:10881→80`restart unless-stopped`/data/share:/srv:ro` **只读挂载**,数据卷 `/data/filebrowser-q`config.yaml+database.db+tmp属主=镜像 uid1000+ nginx 反代。**要点**:初始凭据 **admin/admin**(首登后立即改密);配置走 `config.yaml`sources/cacheDir管理走网页 UIAPI 与原版不兼容(需用户建 long-live token/swagger 亦需);镜像默认非 root(uid1000);原版 filebrowser(容器 `filebrowser`/10880/db `/data/filebrowser/database`)已于 2026-09-01 归档、现已停用**保留回滚**Quantum v2.0 beta 权限模型改 per-source(view/download/modify/create/delete)。改密/建只读账号/临时分享(过期+密码+匿名)均在网页 UI。 - 文件下载站2026-09-03 上线,当晚迁移):`file.xpcool.com` = **FileBrowser Quantum** 容器 `fbq``gtstef/filebrowser:stable` v1.5.5`127.0.0.1:10881→80`restart unless-stopped`/data/share:/srv:ro` **只读挂载**,数据卷 `/data/filebrowser-q`config.yaml+database.db+tmp属主=镜像 uid1000+ nginx 反代。**要点**:初始凭据 **admin/admin**(首登后立即改密);配置走 `config.yaml`sources/cacheDir管理走网页 UIAPI 与原版不兼容(需用户建 long-live token/swagger 亦需);镜像默认非 root(uid1000);原版 filebrowser(容器 `filebrowser`/10880/db `/data/filebrowser/database`)已于 2026-09-01 归档、现已停用**保留回滚**Quantum v2.0 beta 权限模型改 per-source(view/download/modify/create/delete)。改密/建只读账号/临时分享(过期+密码+匿名)均在网页 UI。
- SSH 凭据/密码不入库,需要时询问用户或查对话记忆;远程批量命令用 paramiko 脚本(`%TEMP%\wb_deploy\ssh_exec.py`,支持第 2 参数超时秒数docker build 用服务器端 nohup+日志轮询防超时。**2026-09-11 密钥轮换后更新)**:当前登录 = 本地 `~/.ssh/xpcool_ed25519`ed25519注释 xpcool-server-20260904`xxcool@193.112.118.168:22025`root 被拒;密码登录已禁);旧 `CentOS.pem`(RSA对应服务器公钥 `skey-q6pq6jb3`)**已作废并从 authorized_keys 移除**(因私钥误提交 Gitea 事件而轮换),服务器 authorized_keys 另存 2 把钥(`mcp-server-manager@local`、`xxcoolwork@gmail.com`)为其他用途、保留不动;安全组按出口 IP 限放 22025本机出口 1.204.105.116 曾因未放行连不上80/443 可达);本机旧记录 `~/.ssh/id_ed25519` 与 wb_deploy 脚本**在当前设备不存在**。 - SSH 凭据/密码不入库,需要时询问用户或查对话记忆;远程批量命令用 paramiko 脚本(`%TEMP%\wb_deploy\ssh_exec.py`,支持第 2 参数超时秒数docker build 用服务器端 nohup+日志轮询防超时。**2026-09-11 密钥轮换后更新)**:当前登录 = 本地 `~/.ssh/xpcool_ed25519`ed25519注释 xpcool-server-20260904`xxcool@193.112.118.168:22025`root 被拒;密码登录已禁);旧 `CentOS.pem`(RSA对应服务器公钥 `skey-q6pq6jb3`)**已作废并从 authorized_keys 移除**(因私钥误提交 Gitea 事件而轮换),服务器 authorized_keys 另存 2 把钥(`mcp-server-manager@local`、`xxcoolwork@gmail.com`)为其他用途、保留不动;安全组按出口 IP 限放 22025本机出口 1.204.105.116 曾因未放行连不上80/443 可达);本机旧记录 `~/.ssh/id_ed25519` 与 wb_deploy 脚本**在当前设备不存在**。
- **服务器安全加固2026-08-27 完成)**firewalld 已启用(放行 22025/80/443/3000/2222cockpit/rpcbind 已停fail2ban 保护 sshd(port=22025, maxretry5/bantime1h);监控脚本 `/usr/local/bin/server-monitor.sh` + cron 每 10 分钟(调度在 **xxcool 的 crontab**`*/10 * * * * sudo /usr/local/bin/server-monitor.sh`;日志 `/var/log/server-monitor.log`Bark 推送配 `/etc/server-monitor.conf``BARK_URL`**告警去重终版2026-09-11**:状态目录 `/var/lib/server-monitor/` —— `banned-ips.state`(已提醒过的封禁 IP**只增不减 → 同一 IP 永不重复提醒**)、`ssh-src-ips.state`(已提醒过的登录来源 IP**仅新 IP 首次登录**才提醒)、`ports.state`(当前已告警的未登记端口,消失后清除);完整审计仍在 fail2ban.log + journald 且已上报 admin 后台(脚本备份 `server-monitor.sh.bak.20260911`);另有安全日志上报器 `/usr/local/bin/server-security-collector.sh`cron **每 5 分钟**xxcool crontab→ POST 到 `127.0.0.1:10100/api/service/open/security/log/report`,配置 `/etc/server-security.conf`INTERNAL_TOKEN、状态 `/var/lib/server-security/last.ts`dnf-automatic 每天 06:00 自动安全补丁SSH 密钥登录已部署(本地 `~/.ssh/id_ed25519`)但用户要求保留密码登录。**坑**:① 腾讯云安全组未放行 3000/2222/8081Gitea 走 nginx 反代 80/443② 改 sshd 前必须先 `sshd -t` 预检+备份(曾因脏行导致 SSH 断开);③ EPEL 源需腾讯云镜像(`mirrors.cloud.tencent.com/epel`)且 baseurl 必须手动写全;④ CentOS9 的 fail2ban 在 EPEL。**⑤2026-09-04 新坑)腾讯云改带宽若切计费模式会触发实例冷重启,重启后 firewalld 自定义端口规则曾丢失致 SSH 22025 失联80/443 正常——firewall-cmd 放行务必带 `--permanent`,且实例冷重启后要复查 22025 放行**。另:带宽 3M→5M 已升级2026-09-04实测 619KB/s 满速)。**⑥2026-09-11 溯源新坑)本机出口 IP `1.204.105.116` 曾于 09-03 23:00 被自己的 fail2ban 封禁、09-04 23:00 才解封——这正是当时「SSH 22025 超时」的真因当时误判为安全组未放行绕了远路。SSH 突然不通时,排查顺序应为:先 `fail2ban-client status sshd` + `grep Ban /var/log/fail2ban.log`,再怀疑安全组**。**⑦2026-09-11 体检结论)服务器未发现被入侵迹象**UID0 仅 root、无空密码账号、无异常 SUID/后门/劫持、无特权容器、系统目录近 30 天无改动;外网暴露面实测仅 **22025/80/443**3000/2222/8081 等均被安全组挡住firewalld 虽放行 3000/2222 但安全组是第二道闸)。 - **服务器安全加固2026-08-27 完成)**firewalld 已启用(放行 22025/80/443/3000/2222cockpit/rpcbind 已停fail2ban 保护 sshd(port=22025, maxretry5/bantime1h);监控脚本 `/usr/local/bin/server-monitor.sh` + cron 每 10 分钟(调度在 **xxcool 的 crontab**`*/10 * * * * sudo /usr/local/bin/server-monitor.sh`;日志 `/var/log/server-monitor.log`Bark 推送配 `/etc/server-monitor.conf``BARK_URL`**告警去重终版2026-09-11**:状态目录 `/var/lib/server-monitor/` —— `banned-ips.state`(已提醒过的封禁 IP**只增不减 → 同一 IP 永不重复提醒**)、`ssh-src-ips.state`(已提醒过的登录来源 IP**仅新 IP 首次登录**才提醒)、`ports.state`(当前已告警的未登记端口,消失后清除)、`ssh-brute.state`(爆破告警状态机:`attacking`=本轮已提醒 / `idle`=已复位;攻击持续不刷屏,攻击停止静默复位,**再犯视为新一波才重新提醒**;完整审计仍在 fail2ban.log + journald 且已上报 admin 后台(脚本备份 `server-monitor.sh.bak.20260911`);另有安全日志上报器 `/usr/local/bin/server-security-collector.sh`cron **每 5 分钟**xxcool crontab→ POST 到 `127.0.0.1:10100/api/service/open/security/log/report`,配置 `/etc/server-security.conf`INTERNAL_TOKEN、状态 `/var/lib/server-security/last.ts`dnf-automatic 每天 06:00 自动安全补丁SSH 密钥登录已部署(现用 `~/.ssh/xpcool_ed25519`)、密码登录已禁。**2026-09-11 加固**:已关闭 `X11Forwarding`**生效位置是 drop-in `/etc/ssh/sshd_config.d/50-redhat.conf:17`,主配置里那行是注释、改了无效**;改前备份 `.bak.20260911``sshd -t` 预检 + `sshd -T` 核对 + `systemctl reload sshd` 不断连nginx 遗留垃圾已清理(`.code.xpcool.com.conf.swo`、`tool.xpcool.com.conf.download.0` → 移入 `/data/nginx/_junk_backup_20260911/`,未直接删、可回滚)。**nginx 配置目录约定**`include /data/nginx/conf.d/*.conf;`,故 conf.d 下非 `.conf` 后缀文件不会被加载。**遗留待办**`lighthouse` 账号(腾讯云自带 uid1000NOPASSWD ALL是否锁定待用户决策。**坑**:① 腾讯云安全组未放行 3000/2222/8081Gitea 走 nginx 反代 80/443② 改 sshd 前必须先 `sshd -t` 预检+备份(曾因脏行导致 SSH 断开);③ EPEL 源需腾讯云镜像(`mirrors.cloud.tencent.com/epel`)且 baseurl 必须手动写全;④ CentOS9 的 fail2ban 在 EPEL。**⑤2026-09-04 新坑)腾讯云改带宽若切计费模式会触发实例冷重启,重启后 firewalld 自定义端口规则曾丢失致 SSH 22025 失联80/443 正常——firewall-cmd 放行务必带 `--permanent`,且实例冷重启后要复查 22025 放行**。另:带宽 3M→5M 已升级2026-09-04实测 619KB/s 满速)。**⑥2026-09-11 溯源新坑)本机出口 IP `1.204.105.116` 曾于 09-03 23:00 被自己的 fail2ban 封禁、09-04 23:00 才解封——这正是当时「SSH 22025 超时」的真因当时误判为安全组未放行绕了远路。SSH 突然不通时,排查顺序应为:先 `fail2ban-client status sshd` + `grep Ban /var/log/fail2ban.log`,再怀疑安全组**。**⑦2026-09-11 体检结论)服务器未发现被入侵迹象**UID0 仅 root、无空密码账号、无异常 SUID/后门/劫持、无特权容器、系统目录近 30 天无改动;外网暴露面实测仅 **22025/80/443**3000/2222/8081 等均被安全组挡住firewalld 虽放行 3000/2222 但安全组是第二道闸)。
- 本地 pnpm 修复2026-08-27 升级为 wrapper 方案):根因=本环境 MSYS 路径转换故障,把 `/c/...` 参数转成 `E:\c\...`(多 `E:\c\` 前缀)致 corepack shim 与 node 都找不到 pnpm.js。**已建持久 wrapper**`~/.workbuddy/binaries/node/bin/pnpm`(内容:`export NODE_OPTIONS=--experimental-sqlite; exec "<托管node.exe>" "C:/Users/ybtdevxxl/.workbuddy/binaries/node/workspace/node_modules/pnpm/bin/pnpm.cjs" "$@"`,关键=给 node 传 Windows 风格路径 `C:/...` 规避 MSYS 转换)。**提交/构建前需 `PATH="~/.workbuddy/binaries/node/bin:$PATH"` 前置**pre-commit 钩子(lefthook oxlint/oxfmt/eslint/stylelint/checkType)即可正常运行;否则钩子崩 → 只能 --no-verify。已验证 pnpm 11.16.0 + `pnpm exec oxlint` 1.79.0。 - 本地 pnpm 修复2026-08-27 升级为 wrapper 方案):根因=本环境 MSYS 路径转换故障,把 `/c/...` 参数转成 `E:\c\...`(多 `E:\c\` 前缀)致 corepack shim 与 node 都找不到 pnpm.js。**已建持久 wrapper**`~/.workbuddy/binaries/node/bin/pnpm`(内容:`export NODE_OPTIONS=--experimental-sqlite; exec "<托管node.exe>" "C:/Users/ybtdevxxl/.workbuddy/binaries/node/workspace/node_modules/pnpm/bin/pnpm.cjs" "$@"`,关键=给 node 传 Windows 风格路径 `C:/...` 规避 MSYS 转换)。**提交/构建前需 `PATH="~/.workbuddy/binaries/node/bin:$PATH"` 前置**pre-commit 钩子(lefthook oxlint/oxfmt/eslint/stylelint/checkType)即可正常运行;否则钩子崩 → 只能 --no-verify。已验证 pnpm 11.16.0 + `pnpm exec oxlint` 1.79.0。
## 日常同步习惯(建议) ## 日常同步习惯(建议)

View File

@ -2,7 +2,7 @@
# ============================================================ # ============================================================
# 服务器安全与资源监控脚本(轻量版) # 服务器安全与资源监控脚本(轻量版)
# 功能: # 功能:
# 1. SSH 爆破检测10分钟内失败认证超阈值 # 1. SSH 爆破检测10分钟内失败认证超阈值;同一波攻击只提醒一次,攻击停止后再犯才重新提醒
# 2. 新来源 IP SSH 登录(仅"没见过的新 IP"首次登录时提醒,避免自己日常登录刷屏) # 2. 新来源 IP SSH 登录(仅"没见过的新 IP"首次登录时提醒,避免自己日常登录刷屏)
# 3. fail2ban 新封禁 IP同一 IP 只提醒一次,永久去重) # 3. fail2ban 新封禁 IP同一 IP 只提醒一次,永久去重)
# 4. 根分区磁盘、内存、系统负载告警 # 4. 根分区磁盘、内存、系统负载告警
@ -14,6 +14,8 @@
# - banned-ips.state :已提醒过的封禁 IP只增不减 → 同一 IP 永不再重复提醒) # - banned-ips.state :已提醒过的封禁 IP只增不减 → 同一 IP 永不再重复提醒)
# - ssh-src-ips.state已提醒过的登录来源 IP仅新 IP 首次登录提醒) # - ssh-src-ips.state已提醒过的登录来源 IP仅新 IP 首次登录提醒)
# - ports.state :当前已提醒的未登记端口(端口消失后清除,再出现会再提醒) # - ports.state :当前已提醒的未登记端口(端口消失后清除,再出现会再提醒)
# - ssh-brute.state 爆破告警状态attacking=本轮已提醒;攻击停止后复位为 idle
# 之后再出现攻击视为"新一波",重新提醒一次)
# 说明:完整审计数据仍在 /var/log/fail2ban.log 与 journald且已由 # 说明:完整审计数据仍在 /var/log/fail2ban.log 与 journald且已由
# server-security-collector.sh 上报到 admin 后台,去重不影响追溯。 # server-security-collector.sh 上报到 admin 后台,去重不影响追溯。
# ============================================================ # ============================================================
@ -31,18 +33,35 @@ BARK_URL=${BARK_URL:-}
alert() { ALERT="${ALERT}$1 alert() { ALERT="${ALERT}$1
"; } "; }
# 去重状态目录(第 2、3、7 段共用) # 去重状态目录(第 1、2、3、7 段共用)
STATE_DIR=/var/lib/server-monitor STATE_DIR=/var/lib/server-monitor
mkdir -p "$STATE_DIR" 2>/dev/null mkdir -p "$STATE_DIR" 2>/dev/null
BAN_STATE=$STATE_DIR/banned-ips.state BAN_STATE=$STATE_DIR/banned-ips.state
SSH_STATE=$STATE_DIR/ssh-src-ips.state SSH_STATE=$STATE_DIR/ssh-src-ips.state
PORT_STATE=$STATE_DIR/ports.state PORT_STATE=$STATE_DIR/ports.state
BRUTE_STATE=$STATE_DIR/ssh-brute.state
touch "$BAN_STATE" "$SSH_STATE" "$PORT_STATE" 2>/dev/null touch "$BAN_STATE" "$SSH_STATE" "$PORT_STATE" 2>/dev/null
# ---------- 1) SSH 爆破检测近10分钟失败认证 ---------- # ---------- 1) SSH 爆破检测(同一波攻击只提醒一次;攻击停止后再犯才重新提醒) ----------
# 逻辑:进入攻击态时提醒一次并置 attacking攻击停止10分钟内失败数回落时静默复位为
# idle。之后再被攻击即视为"新一波",重新提醒。避免持续攻击每 10 分钟刷屏。
FAILED=$(sudo journalctl _SYSTEMD_UNIT=sshd.service --since "10 minutes ago" 2>/dev/null | grep -ci "Failed password") FAILED=$(sudo journalctl _SYSTEMD_UNIT=sshd.service --since "10 minutes ago" 2>/dev/null | grep -ci "Failed password")
if [ "${FAILED:-0}" -ge 10 ]; then if [ "${FAILED:-0}" -ge 10 ]; then
alert "SSH爆破风险: 10分钟内 ${FAILED} 次密码失败" if [ "$(cat "$BRUTE_STATE" 2>/dev/null)" != "attacking" ]; then
# 取失败次数最多的前 3 个来源 IP便于判断攻击来源
BRUTE_TOP=$(sudo journalctl _SYSTEMD_UNIT=sshd.service --since "10 minutes ago" 2>/dev/null \
| grep -i "Failed password" | awk '{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}' \
| sort | uniq -c | sort -rn | head -3 | awk '{printf "%s(%s次) ", $2, $1}')
alert "SSH爆破风险: 10分钟内 ${FAILED} 次失败认证攻击进行中fail2ban 已自动拦截,无需处理)
主要来源: ${BRUTE_TOP:-未知}"
echo "attacking" > "$BRUTE_STATE"
fi
else
# 攻击已停止 → 静默复位(只写日志,不推送),下次再犯才重新提醒
if [ "$(cat "$BRUTE_STATE" 2>/dev/null)" = "attacking" ]; then
echo "idle" > "$BRUTE_STATE"
echo "$NOW [INFO] SSH 爆破已停止10分钟内失败 ${FAILED:-0} 次),爆破告警已复位,下次再犯将重新提醒" >> "$LOG"
fi
fi fi
# ---------- 2) 新来源 IP 登录(仅首次出现的 IP 才提醒) ---------- # ---------- 2) 新来源 IP 登录(仅首次出现的 IP 才提醒) ----------