有人悄悄登了你的 VPS?用 Telegram Bot / 微信 Server酱 打造登录与宕机实时警报
2026-08-14 · DevCraft Studio
有人悄悄登录了你的 VPS 你却毫不知情?黑客爆破成功的第一时间收到警报才能止损。本文手把手教你用 Telegram Bot 或微信 Server酱 / PushDeer,通过修改 /etc/pam.d/sshd,实现 SSH 登录、宕机与资源告警的实时推送到手机,附完整脚本。
延伸阅读
更多相关攻略推荐:Ollama AI系列(2):VPS上的AI推理与API应用、Ollama AI系列(2):VPS上的AI推理与API应用、【CPU选型 01】搭载 AMD Ryzen 9950X 的 VPS、ARM / Ampere 席卷 VPS:性价比真香还是兼容陷阱?、Ollama AI系列(2):VPS上的AI推理与API应用。
一、为什么你一定要给 VPS 装个"登录报警器"
先说个扎心的事实:只要你买了一台面向公网的 VPS,并且开着 SSH(端口 22),你的机器基本从开机那一刻起就一直在被路人扫描。那些自动化的爆破脚本,会拿着成百上千个常见弱密码,对着全网的 IP 段一遍遍尝试登录。你没看错,这不是夸张,是每天每夜都在发生的事。
很多新手觉得:"我密码够复杂,怕什么。"但问题是,密码再复杂,你也没法保证哪天某个服务的漏洞被爆出来,或者你手滑把密钥权限设成了 644,又或者运维小伙伴的电脑中了木马。一旦真的有人登录成功,而你毫无察觉,那台机器可能几分钟内就变成了别人的肉鸡:挂挖矿、做跳板、发垃圾邮件,甚至拿去攻击别人。
真正的止损窗口,就是"登录发生后的那几秒"。如果你能在有人成功登录的第一时间,在手机上收到一条带 IP、带时间的推送,你就有可能立刻改密码、封 IP、甚至直接关机排查。反过来,如果你要等服务器已经被用来发攻击流量、被机房拉黑了才发现,那就晚了,账号可能被封,钱也退不回来。
所以这篇文章要教你的,不是什么高深运维,而是一套便宜、简单、几乎零成本的"报警器":只要有人通过 SSH 登录你的 VPS,或者你的机器 CPU 飙到 100%、磁盘快满了,手机立刻弹消息。下面一步一步来。
二、原理其实特别简单:有人 SSH 登录,就触发一条消息
很多同学一听到"监控告警"就觉得要搭一套 Prometheus + Grafana,或者买个商业监控服务,吓得直接划走。其实完全不用。我们用的思路就一句话:让系统在"登录成功"这个动作发生时,顺手帮你发条消息。
Linux 的登录流程走的是 PAM(Pluggable Authentication Modules,可插拔认证模块)。SSH 登录成功后,PAM 会进入"会话(session)"阶段,而这个阶段是可以挂外部脚本的。换句话说,我们往 PAM 配置里塞一行命令,告诉它:"每次开会话,顺便跑一下我这个脚本"。脚本里干的事也很朴素:拼一段文字(谁、从哪个 IP、什么时间登录的),然后用 curl 调一下 Telegram 或者微信的接口,把这段话发到你的手机上。
整套链路就三步:第一,搞一个能发消息的机器人;第二,写个发消息的小脚本;第三,把脚本挂到 PAM 上。下面我们分别拆开讲,每一步都会给可直接抄的命令。
三、第一步:先搞一个 Telegram Bot(30 秒搞定)
Telegram 的 Bot 接口对个人是完全免费的,也没有什么资质审核,这是它最香的地方。打开 Telegram,搜索 @BotFather(这是官方用来管理机器人的机器人,别搜错了),点进去发一条消息:
- 发送 /newbot
- 它会先问你机器人的"显示名称",随便起,比如 My VPS Alarm
- 接着问"用户名",这个必须以 bot 结尾,比如 my_vps_alarm_bot
- 确认后,BotFather 会回你一长串 token,长这样:123456789:AAExampleTokenStringHere
这个 token 就是你机器人的"密码",谁拿到它谁就能操控你的机器人,所以千万别贴到公开仓库、博客或者截图发群里。万一泄露了,回去给 BotFather 发 /revoke 就能作废旧 token、换新的一串。
拿到 token 后,先验证一下没敲错。在终端里执行:
- curl https://api.telegram.org/bot你的TOKEN/getMe
- 如果返回里 "ok": true,还带出你的 bot 信息,说明 token 没问题
这里有个冷知识:Telegram 的机器人不能主动给一个没找过它的人发消息。所以下一步,你得先去"撩"它一下,把它的 chat_id 拿到手,它才知道该往哪个会话推消息。
四、拿到 chat_id:机器人不能主动找你,得你先"撩"它
在 Telegram 里点开你刚创建的机器人,随便发一条消息,比如 "hello"。然后回到终端,执行:
- curl https://api.telegram.org/bot你的TOKEN/getUpdates
- 在返回的 JSON 里找 message.chat.id 这个数字,比如 5123456789
这个 chat.id 就是你的私人会话地址,记下来。如果你更想推到群里(比如把几台服务器的告警都汇总到一个群),那就把机器人拉进群,在群里发句话,再用同样的方法 getUpdates 读群聊的 chat.id,群聊的 id 是负数,正常,照用就行。
嫌手动解析 JSON 麻烦的话,也可以把机器人发给 @get_id_bot 之类的工具号,它会直接把你的 id 回给你,省事。但核心逻辑不变:先有会话,才有 chat.id。
五、写告警脚本:把登录的 IP、时间、用户名抓出来
现在写一个发消息的脚本,比如放到 /usr/local/bin/ssh_login_alert.sh。PAM 在调用脚本时会自动塞进来几个环境变量,我们直接用就行:
- PAM_USER:登录的用户名,比如 root 或者 ubuntu
- PAM_RHOST:登录来源的公网 IP,这是最关键的字段
- PAM_SERVICE:服务名,这里通常是 sshd
- PAM_TTY:终端类型,SSH 登录一般是 ssh
脚本大致长这样(把 TOKEN 和 CHAT_ID 换成你自己的):
- #!/bin/bash
- TOKEN="你的TOKEN"
- CHAT_ID="你的CHAT_ID"
- USER_NAME="${PAM_USER:-unknown}"
- SRC_IP="${PAM_RHOST:-unknown}"
- NOW=$(date '+%Y-%m-%d %H:%M:%S')
- HOST=$(hostname)
- TEXT="VPS 登录提醒:用户 $USER_NAME 从 $SRC_IP 于 $NOW 登录了 $HOST"
- curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" -d "chat_id=$CHAT_ID" -d "text=$TEXT"
写完记得给执行权限:chmod 700 /usr/local/bin/ssh_login_alert.sh,并且把属主设为 root,避免被别的用户篡改。想先测试一下?可以手动模拟一次 PAM 调用:
- sudo env PAM_USER=test PAM_RHOST=1.2.3.4 /usr/local/bin/ssh_login_alert.sh
- 手机上如果立刻收到消息,说明脚本链路通了
小提示:有时候密钥登录下 PAM_RHOST 可能为空,稳妥起见脚本里可以拿 SSH_CONNECTION 变量兜底,把它的第一个字段也当成来源 IP,这样不会漏报。
六、挂到 PAM:改 /etc/pam.d/sshd
这一步是把脚本真正接进登录流程。先备份,宁可麻烦也别省:
- sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak
- 确认 SSH 真的在用 PAM:sudo sshd -T | grep usepam,看到 usepam yes 再继续
然后编辑 /etc/pam.d/sshd,在文件末尾加一行:
- session optional pam_exec.so /usr/local/bin/ssh_login_alert.sh
这里有两个坑要专门提醒你。第一,控制位一定要用 optional,而不是 required。optional 的意思是:就算这个脚本执行失败(比如网络抽风、Telegram 接口连不上),登录照样成功,不影响你正常进门。如果你手滑写成 required,而某天脚本出错,你就可能被自己挡在门外,进不去服务器了,那才叫尴尬。第二,改 PAM 的时候,一定保持一个已经登录的 SSH 会话不要关,万一配错至少还能从那个旧会话里救回来。
改完退出,再从另一台机器 SSH 登录一次,手机上应该马上弹出登录提醒。再去翻系统日志确认没报错:sudo journalctl -u ssh --since "10 min ago",搜 pam_exec 或者 telegram 关键字即可。
七、微信党怎么办:Server酱 / PushDeer 同样能推
不是所有人都用 Telegram,国内很多朋友更习惯微信。方案也简单,最省事的是 Server酱(ServerChan)。去 sct.ftqq.com 用 GitHub 登录,拿到一个 SendKey,然后用一行 curl 就能推到微信:
- curl -X POST "https://sctapi.ftqq.com/你的SendKey.send" -d "title=VPS登录提醒" -d "desp=root 从 1.2.3.4 登录"
- 接口返回 JSON 里 code 为 0 表示成功
注意几个细节:免费版每天只有 5 条额度,做登录告警完全够用,但别拿它刷屏;title 里不能带换行;desp 支持 Markdown,可以写好看点。如果你的 SendKey 是以 sctp 开头,要把地址换成 https://你的uid.push.ft07.com/send/你的SendKey.send,uid 是 sctp 和 t 之间的那串数字。
另一个选择是 PushDeer,它是国内开发者做的,接口是 https://api2.pushdeer.com/message/push,参数带 pushkey、text、desp,也能直接在 App 里收消息,还能作为 Server酱的通道来用。两个都行,看你手机里装哪个顺手。把上面脚本里的 curl 那行换成对应的微信接口,其余逻辑完全不变。
八、进阶:CPU 飙到 100%、磁盘快满,也给你报警
登录提醒只是开胃菜。你还可以顺手监控几个最要命的资源指标,用 crontab 每 5 分钟跑一次就行。逻辑很直白:
- 磁盘:用 df 看根分区使用率,超过 90%(也就是剩余小于 10%)就告警
- CPU:如果 1 分钟平均负载长期接近核心数,或者某个进程长时间占满单核,就告警
- 内存:可用内存低于某个阈值,或者开始频繁用 swap,也提醒一下
这种脚本同样用 curl 调 Telegram 或 Server酱接口发消息,只是触发条件从"登录"变成了"指标越线"。举个例子,检查磁盘的片段可以是:用 df -P / 取出使用率数字,和 90 比较,大于就发"磁盘快满"的提醒。把它丢进 crontab:
- */5 * * * * /usr/local/bin/vps_resource_check.sh
宕机怎么报?宕机时你自己的脚本当然跑不了,得靠外部。可以用免费的 Uptime Robot 或者 Uptime Kuma 这类监控,每隔一两分钟 ping 一下你 VPS 的端口,连续几次不通就往邮箱或微信推"服务器疑似宕机"。外部监控 + 内部告警,这套组合拳基本就把常见意外都罩住了。