凌晨一点多监控终端突然弹出一条告警某台测试服务器的 SSH 端口出现了大量失败认证记录源 IP 不断变化像潮水一样一波接一波涌过来。虽然只是一台不跑核心业务的机器但这个场景在任何一个有公网服务器的团队里都迟早会遇到。SSH 作为 Linux 服务器最常用的远程管理通道天然暴露在公网攻击面上入侵检测和响应不是“要不要做”的问题而是“什么时候做、做到什么程度”的问题。这篇文章围绕“系统安全之 SSH 入侵的检测与响应”展开面向的是运维、开发和兼职管服务器的同学。你会看到 SSH 攻击为什么如此普遍、攻击者的完整思路、如何从日志里发现蛛丝马迹、如何用 fail2ban 这类工具做自动化防御以及真的被入侵之后一套可以照着执行的响应流程。这些内容基于我在实际运维中的处理经验整理尽量说人话能直接落地。1. SSH 入侵为什么是每台服务器的必修课1.1 SSHD 服务为什么总被盯上SSH 服务之所以成为攻击者的首选目标不是因为协议本身有多脆弱而是因为它在公网上的暴露面实在太大了。绝大多数 Linux 服务器都开着 22 端口用来给运维人员提供远程管理入口。这个入口背后连着的是 root 权限、文件系统、数据库和业务进程一旦拿到登录凭据等于拿到了服务器的控制权。很多新手不理解一点攻击者并不是专门“针对”你的服务器而是通过全网扫描把开放 22 端口的 IP 全部捞出来然后批量尝试弱口令。这个过程完全自动化垃圾字典、常见用户名密码组合一轮轮跑命中率虽然低但架不住量大。你只要用了太简单的密码或者把 root 登录直接暴露出去被攻破只是时间问题。我见过太多案例服务器上面跑着小业务平时没人管有一天突然发现 CPU 占用率飙升一查才知道 SSH 被暴力破解成功机器被拿去挖矿了。这里的关键认知是SSH 入侵不挑目标它只看你的系统有没有“敞开的门”。1.2 攻击者的完整思路从扫描到后门理解攻击者的路径才能理解我们防守的重点。SSH 入侵的典型链路大致是这么走的信息收集扫描全网 IP找到开放 TCP 22 端口的机器同时识别 SSH 服务版本。口令尝试使用弱口令字典、常见用户名列表root、admin、test、ubuntu进行批量登录测试或者直接尝试撞库。漏洞利用针对老旧 SSH 服务版本尝试已知 CVE 漏洞或者针对暴露的密钥文件下手。建立持久化登录成功后立刻创建新用户、写入 SSH 公钥、修改系统计划任务确保下次还能再进来。横向移动拿下一台机器后扫描内网其他主机尝试复用密码或跳板渗透其他系统。对照这条链路我们做检测和响应的核心思路就清晰了在“口令尝试”阶段发现异常并封堵在“建立持久化”阶段尽快清理痕迹在“横向移动”发生前隔离风险。注意大量 SSH 爆破其实来自僵尸网络攻击源 IP 往往来自境外或云主机单 IP 请求频率不高但整体态势密集。所以单纯靠“封一个 IP”是不够的必须配合自动化工具和安全组做持续封禁。2. 检测从日志里读懂入侵痕迹2.1 核心日志文件在哪怎么看SSH 登录行为全部被记录在系统日志里。不同发行版日志位置有差异这是很多人第一个踩坑的点Debian / Ubuntu/var/log/auth.logCentOS / RHEL / Rocky / AlmaLinux/var/log/secure日志里最关键的字段是 sshd 打出来的认证记录。典型的一条认证失败记录长这样Jan 12 03:14:22 web01 sshd[12345]: Failed password for invalid user admin from 192.0.2.10 port 51920 ssh2拆开来看Jan 12 03:14:22是时间web01是主机名sshd[12345]是服务名和进程IDFailed password是事件类型表示密码认证失败for invalid user admin表示尝试登录的用户名是 admin而且这个用户根本不存在from 192.0.2.10是攻击来源 IPport 51920是攻击者客户端的源端口ssh2是协议版本而认证成功的记录则长这样Jan 12 03:20:11 web01 sshd[12360]: Accepted publickey for ubuntu from 192.0.2.88 port 60011 ssh2一行记录时间、用户、来源、认证方式全都有了。你不需要读懂每一行但至少要能在看到日志时第一时间分辨出“这是失败尝试还是成功登录”这是整个检测工作的基本功。2.2 五类异常特征命中就要警惕光会看日志还不行得知道什么情况算异常。这是我日常巡检时重点关注的五类特征第一类失败次数异常增多。一台正常服务器一天可能有几条甚至几十条失败记录但如果短短几小时内出现几百甚至几千条基本可以断定正在被爆破。第二类用户名是随机或枚举出来的。攻击者会尝试大量不存在的用户名比如admin、test、oracle、hadoop、甚至user1、a、b这种穷举组合。日志里invalid user出现得越多说明攻击者的字典越宽。第三类来源 IP 地理跨度极大。昨天从某欧洲国家来的 IP今天变成某亚洲地区明天又是某云厂商网段。正常的运维人员不会这样切换来源。第四类来源端口不固定。攻击者每次连接使用的源端口五花八门而真实运维人员的办公网出口 IP 和端口通常是相对固定的。第五类尝试 root 登录。很多服务器已禁用 root 密码登录但攻击者依然会反复尝试root用户名。这个特征一旦高频出现直接判定是攻击行为基本不会误伤。把这五类特征串起来看而不是只看单一维度。比如某台服务器只有三条失败记录来源 IP 却是固定的三个这更可能是运维手误输错密码但如果失败记录集中在短时间内且用户名全部是root、admin等那基本可以确认是爆破。2.3 用命令行快速统计分析查看日志不需要直接翻文件一条命令就能统计出最常见的攻击来源grep sshd /var/log/auth.log | grep Failed password | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -20命令的意思是把认证失败记录里的来源 IP 提取出来排序后统计次数。输出效果类似521 203.0.113.17 487 198.51.100.44 302 192.0.2.66如果想看哪种用户名被尝试得最多grep Failed password /var/log/auth.log | awk {print $9} | sort | uniq -c | sort -nr | head -20对于 CentOS 系列把/var/log/auth.log换成/var/log/secure即可。为什么推荐先做统计再逐个看日志因为日志量太大了几千条记录人肉翻不现实统计结果能帮你快速锁定最危险的来源 IP然后针对性地查看这个 IP 的所有访问行为判断它有没有尝试成功。提示如果日志里同时出现Failed password和Accepted password且来源 IP 相同说明爆破可能已经成功这时候不是封 IP 就算完立刻进入应急响应流程见文章第 4 节。3. 自动化防御fail2ban 与防火墙联动3.1 fail2ban 的工作原理和核心参数手工封 IP 治标不治本攻击源千变万化不可能总盯着日志一条条封。自动化工具里最常用、最成熟的就是 fail2ban。fail2ban 的原理并不复杂监听日志文件用正则表达式匹配失败认证记录如果同一个来源 IP 在指定时间窗口内触发超过阈值就调用防火墙规则临时封禁这个 IP。它把“日志分析”和“防火墙动作”这两件事串起来了全部自动化执行。安装很简单# Ubuntu / Debian apt install fail2ban -y # CentOS / Rocky dnf install fail2ban -y配置文件的默认位置是/etc/fail2ban/jail.conf但官方强烈不建议直接改这个文件因为升级软件时会被覆盖。正确做法是新建/etc/fail2ban/jail.local里面的配置会覆盖默认值。一个最小可用的 SSH 防护配置长这样[DEFAULT] bantime 3600 findtime 600 maxretry 5 ignoreip 127.0.0.1/8 ::1 192.0.2.0/24 [sshd] enabled true backend systemd逐个解释参数这些都是必须理解的bantime封禁时长单位秒。3600 是一小时。设太短会被攻击者反复试探设太长容易误伤正常用户。findtime检测时间窗口单位秒。600 表示十分钟内。maxretry在时间窗口内允许的最大失败次数超过则触发封禁。5 表示十分钟内失败 5 次就封。ignoreip白名单 IP不在白名单里的源 IP 才会被检测。务必把公司出口 IP、运维跳板机 IP 加进去否则可能把自己封了。backend systemd使用 systemd 的 journal 日志作为输入来源适合新版 Debian/Ubuntu老系统上用auto或polling。配置完成后重启服务并查看状态systemctl restart fail2ban fail2ban-client status sshd如果状态输出里 IP 列表不为空说明已经自动封掉了攻击源。解除封禁用fail2ban-client set sshd unbanip 203.0.113.173.2 别只依赖 fail2ban安全组要一起上fail2ban 再稳也有限制它只能封服务器本机层面的连接如果服务器前置了云平台安全组攻击流量可能直接打在安全组层面fail2ban 看不到。所以最稳妥的做法是双管齐下。云平台的安全组就相当于一个“大门外的门禁”它最擅长的是按 IP 和端口做访问控制。日常运维里应该把 SSH 端口的来源限制在固定 IP 或网段内。比如团队只有 5 个固定办公出口 IP安全组里只放行这 5 个 IP 到 22 端口其他 IP 全部拒绝。这个操作一旦完成绝大多数网络扫描基本到不了你的 sshd 进程。我遇到很多案例服务器被爆破了一问才知道安全组里 22 端口是对全网段0.0.0.0/0开放的fail2ban 也没装完全裸奔。这是最典型的配置疏漏。把 fail2ban 和安全组叠加后即使某个 IP 绕过安全组直连到服务器fail2ban 也能在几次失败后自动封禁。而 fail2ban 本身封禁的只是本机防火墙层面的 IP如果攻击者持续换 IP安全组的固定白名单策略才是最终的兜底方案。3.3 SSH 服务自身的加固项配完能挡掉九成脚本除了外部工具SSH 自身的配置同样重要。编辑/etc/ssh/sshd_config这些项建议逐个核验# 禁止 root 直接登录运维人员先登录普通用户再 sudo PermitRootLogin no # 优先使用密钥认证 PubkeyAuthentication yes PasswordAuthentication no # 限制可登录的用户名单 AllowUsers ubuntu ops # 登录失败次数限制 MaxAuthTries 3 # 登录超时时间减少空闲连接 LoginGraceTime 30其中PasswordAuthentication no这条争议最大。如果所有用户都强制使用密钥登录暴力破解基本失效因为攻击者根本没有你的私钥。但前提是团队成员都理解密钥管理否则可能出现办公室里某台电脑丢了私钥所有人都无法登录的窘境。我的建议是如果团队规模小、有精力做好密钥管理直接关掉密码认证如果团队比较大或者有很多外包维护人员至少把MaxAuthTries调低、禁用 root 登录再叠加 fail2ban。安全没有银弹只有根据团队情况做取舍。注意修改 sshd_config 后一定要先执行sshd -t检查语法再重启服务。如果语法错误导致 sshd 起不来你可能会把自己锁在服务器外面。重启前最好保持当前 SSH 连接不要断开重启后再新开一个窗口测试确认能连上再关掉旧会话。4. 应急响应发现入侵后的处置流程4.1 先止损封 IP别急着关机器无论检测手段多完备总有被攻破的可能。真正的考验在于“已经发现被入侵了接下来做什么”。这里容易犯的最大错误是一发现异常就立刻拔网线、关服务器生怕攻击者继续操作。但从应急响应角度看立刻断电会导致内存中的进程信息、网络连接状态、临时文件全部丢失很多关键证据就没了。正确顺序是第一步记录现场时间。写下你发现异常的时间后续排查每一步都要有时间线。第二步阻断来源 IP。如果是正在进行的攻击先在防火墙层面封掉当前的攻击 IP把伤亡最小化。第三步保存进程信息和网络连接快照。执行以下命令把输出保存为文件ps aux /tmp/process_snapshot.txt ss -antp /tmp/network_snapshot.txt w /tmp/login_snapshot.txt last -20 /tmp/lastlog_snapshot.txt这几条命令分别记录了当前进程、网络连接、在线用户和历史登录记录是排查的起点。第四步根据业务影响决定是否断网。如果服务器只是测试环境果断断开外网连接限制攻击者的操作空间如果跑着核心业务要先评估业务影响至少断开对外的不可信流量保留运维通道。第五步立刻通知相关同事尤其是负责同一内网其他服务器的人。横向移动是攻击者的常规操作一台失守不代表只有一台失守。4.2 找人排查入侵痕迹的九个关键位置止损完成后开始排查攻击者是怎么进来的、进来之后做了什么。我按优先级列出平时排查的九个位置1. 登录日志。重点看是否有Accepted password或Accepted publickey记录来源 IP 是否陌生。如果存在说明登录已成功。2. authorized_keys 文件。检查/root/.ssh/authorized_keys和/home/*/.ssh/authorized_keys有没有陌生的公钥内容。攻击者最常用的持久化手段就是写入自己的公钥以后可以随时免密登录。3. 用户列表。查看/etc/passwd有没有新建的、UID 为 0 的用户或者名字看起来正常的隐藏账号。4. 计划任务。检查/etc/crontab、/etc/cron.d/、/var/spool/cron/有没有定时执行的脚本。挖矿程序最爱用这种方式实现持久化。5. 启动项。查看systemctl list-unit-files | grep enabled以及/etc/rc.local有没有异常的服务或自启动脚本。6. bash_history。查看/root/.bash_history和可疑用户的历史命令能还原攻击者执行过哪些命令。7. 进程列表。检查 CPU 和内存占用异常的进程挖矿程序通常会吃掉大量 CPU。用top按 CPU 排序然后查看对应进程的可执行文件路径。8. 网络连接。检查是否有到外部的异常连接挖矿木马会定期与矿池通信。9. 最近修改的文件。用find / -mtime -3 -type f查看最近三天被修改的文件排除正常业务文件后剩下的重点关注。这些位置检查下来80% 的后门都能发现。但要记住入侵者可能会故意清理痕迹比如删除日志、修改文件时间戳所以排查时要保持“总有漏网之鱼”的心态尤其是日志已经出现异常的情况下不能轻易下结论说“没发现问题”。4.3 收尾清理、加固、复盘确认入侵路径后开始清理和加固清理恶意账户和密钥。删除攻击者创建的用户移除 authorized_keys 里的陌生公钥删除恶意计划任务和启动项结束后再次扫描一遍确认没有残留。重置密码和密钥。所有可能被攻破的账户密码全部重置包括普通用户、数据库密码、应用配置里的密码。如果有理由怀疑私钥泄露重新生成 SSH 密钥对并替换。修复入口漏洞。如果是弱口令被爆破立刻改成强密码并开启密钥认证如果是漏洞利用升级 SSH 版本或系统补丁如果是配置错误按第 3 节的加固项逐条修复。持续监控。修复后不能直接不管至少观察 24 到 48 小时确认没有再次出现异常登录和可疑进程。此时可以引入更轻量的监控比如定时检查登录日志、系统进程告警通知到人。复盘报告。把时间线、入侵路径、影响范围、修复措施写清楚。很多人跳过这一步觉得浪费时间但在实战中复盘报告是提升整个团队安全水位最有效的手段。下次再遇到同类事件能直接照着流程走而不是又从头摸索一遍。响应动作优先级关键注意点记录时间与现状最高开启个人时间线记录每步操作留痕阻断攻击来源最高封禁防火墙 云安全组双重阻断保存进程/网络快照高防止强制宕机导致内存证据丢失排查后门痕迹高九个关键位置逐一排查记录可疑项断网隔离视情况测试环境直接断网生产环境评估影响清理与加固中先收集证据再清理修改前保留原始数据恢复与监控中修复后持续观察 24 小时以上复盘总结中输出事件报告补充监控盲区5. 常见问题与排查技巧实录5.1 常见问题速查表长期处理 SSH 入侵相关事件我把高频问题整理成一张速查表遇到问题先对号入座现象可能原因处理方式日志大量 Failed password无成功记录爆破未成功封禁来源 IP配置 fail2ban检查密码强度日志出现 Accepted password来源陌生已被成功登录进入应急响应排查后门与影响范围authorized_keys 出现陌生公钥已植入 SSH 后门删除公钥排查所有用户的 authorized_keys服务器 CPU 飙高进程名异常被植入挖矿程序定位进程文件清理计划任务和启动项日志文件被清空攻击者清理痕迹检查 bash_history、lastlog、进程快照fail2ban 误封办公网 IP阈值设置太敏感把办公网 IP 加入 ignoreip调高 maxretry攻击源一直换 IP封不过来云节点僵尸网络安全组限制来源 IP 段关停密码登录SSH 端口改为非 22 仍被爆破攻击者全端口扫描依靠密钥认证 安全组限制端口隐藏只是辅助5.2 几个我在实战中踩过的坑坑一fail2ban 把公司 IP 全封了。有次调整 fail2ban 配置忘记把办公室出口 IP 加进白名单结果一个同事连续输错几次密码整个办公室的 IP 被封了一小时。那之后我养成了一个习惯任何服务器在启用 fail2ban 前先把ignoreip配置好并且先在测试环境的 IP 段验证再放到生产。坑二看到登录成功记录以为只是“尝试成功但没权限”。那次攻击者用一个普通用户的弱口令登录成功但因为系统里 sudoers 配置不当居然提权到了 root。问题不在于 SSH 本身而在于系统内部权限控制太松。所以检测到 SSH 登录成功之后还要立刻看这个用户在系统内部的权限边界而不仅仅是“能登录”。坑三只封了服务器本机防火墙忘了云安全组。攻击源 IP 虽然被封了但云平台安全组层面没有同步封禁攻击者通过其他方式继续访问其他端口。现在我的思路是任何封禁动作先看是否能在安全组层面做永久封禁再做服务器本机封禁双管齐下。坑四日志轮转把线索转没了。某次排查时发现 auth.log 已经被 logrotate 轮转压缩攻击时间窗口的日志不在了排查难度立刻变大。从那以后我在重要服务器上对 auth.log 做了更长的保留周期并且把日志同步到远端日志中心保证攻击者即使清理了本机文件远端还有备份。这一步对溯源来说价值极大。坑五拿到服务器权限后第一件事是改密码而不是留证据。有一次发现异常登录我下意识先改了 root 密码结果攻击者原来的登录会话没断开他反而借助已有会话做了更多操作。应急响应的第一原则不是“改密码”而是“断会话”先踢掉所有可疑会话、封掉可疑来源再做密码更新。5.3 监控告警的落地建议把检测做到“实时”而不是“事后翻日志”需要一套轻量监控方案。不一定要上复杂的商业产品一个简单的方案是用 cron 每五分钟扫描一次 auth.log 中的失败记录超过阈值就用脚本调用防火墙封禁 IP同时推送告警到钉钉、企业微信群或邮件。更省事的方案就是直接用 fail2ban 自带的邮件告警在 jail.local 里配置action %(action_mwl)s它能在封禁 IP 的同时把日志摘要和新 IP 发送到指定邮箱。有条件的话把 auth.log 通过 rsyslog 远程转发到专门的日志服务器彻底避免攻击者删本机日志导致溯源失败。这套组合下来不需要额外购买任何商业产品成本几乎为零但已经能把“发现入侵”的时间从以天计缩短到以分钟计。写在最后安全不是一次性动作而是持续状态我自己处理过的服务器入侵事件里真正通过极其复杂的 0day 漏洞进来的案例少之又少绝大多数都是弱口令、默认配置、未及时升级、没做访问控制这些低级问题。这不是说漏洞利用不存在而是说明大部分攻击者都是“捡软柿子捏”。做安全防御不需要一开始就堆砌各种复杂系统。把日志看明白把 fail2ban 配好把 SSH 加固项过一遍把应急响应流程跑通这几件基础事做完服务器面对 SSH 类攻击的防御能力就已经超过了绝大多数同行。关键是这些动作要形成习惯定期巡检而不是等收到告警才想起来。如果你现在手头正好有一台公网服务器可以按照这篇文章里的思路做一次完整的体检翻一遍 auth.log看看最近有没有异常登录检查 fail2ban 是否在跑核对一下 sshd_config 里的关键项确认安全组是否放行了多余的 IP。整套流程下来不需要太多时间但能让你对自己的系统心里有底。安全这件事永远是“先知道有什么再决定怎么防”。
阅读完成 · 觉得有帮助?