Linux 服务器

谁登录了我的服务器?审计 SSH 和宝塔面板登录,每次登录发送 Telegram 提醒

6 个步骤 8 分钟阅读 22 次阅读 0
本文目录

大多数入侵之所以发现得晚,是因为没人查看谁登录过。攻击者用偷来的密码登录,和您本人登录没有任何区别;除非您清楚哪些 IP 和密钥是自己的,否则日志看起来一切正常。本文介绍如何审计 Linux 服务器的 SSH 登录、将每次登录对应到具体密钥、检查宝塔面板登录记录,并在每次有人登录时发送 Telegram 消息,让陌生登录在几秒内就暴露出来。

第 1 步:查看当前登录的用户

who                 # interactive sessions
ss -tnp | grep sshd # every SSH connection, including tunnels without a terminal
仅用于端口转发的 SSH 会话(ssh -N)不会打开终端,因此不会出现在 who 或 w 中。务必同时检查 ss -tnp 或 ps -ef | grep "sshd:"。如果有来自陌生 IP 的连接已经持续了好几天,这是严重的危险信号。

第 2 步:查看登录历史

last -a | head -30          # successful logins (from /var/log/wtmp)
lastb -a | head -30         # failed logins (from /var/log/btmp)

# Successful SSH logins with the method used (password or key)
grep "Accepted" /var/log/auth.log | tail -50        # Debian / Ubuntu
grep "Accepted" /var/log/secure | tail -50          # Rocky / AlmaLinux / CentOS
journalctl -u ssh -u sshd --since "7 days ago" | grep Accepted

每一行都会显示登录方式、用户、来源 IP,密钥登录还会显示密钥指纹:

Accepted password for root from 198.51.100.7 port 51234 ssh2
Accepted publickey for root from 203.0.113.20 port 60122 ssh2: ED25519 SHA256:Xq3vR8...

汇总统计,即可一目了然地看到所有来源 IP 和登录方式:

grep -h "Accepted" /var/log/auth.log* 2>/dev/null | awk '{for(i=1;i<=NF;i++){if($i=="Accepted")m=$(i+1); if($i=="from")ip=$(i+1)}; print m, ip}' | sort | uniq -c | sort -rn

如果您只使用密钥登录,那么任何 Accepted password 记录都值得怀疑。

第 3 步:将密钥指纹与您的密钥对应

列出所有可登录密钥的指纹,再与日志中的指纹进行比对:

ssh-keygen -lf /root/.ssh/authorized_keys
for h in /home/*; do [ -f "$h/.ssh/authorized_keys" ] && ssh-keygen -lf "$h/.ssh/authorized_keys"; done

每个密钥都应带有您认识的注释(例如 alice@laptop)。删除无法解释来源的密钥,并检查是否有人通过 /etc/ssh/sshd_config 中的 AuthorizedKeysFile 添加了额外的密钥文件。

第 4 步:检查宝塔面板登录记录

在宝塔面板中,首页会显示最近的面板登录,日志 → 面板日志 中列出了每次登录及其 IP。也可以通过命令行读取:

sqlite3 /www/server/panel/data/default.db \
  "select addtime, log from logs where type in ('Login','用户登录') order by id desc limit 30"

发现登录记录后,在同一日志中检查该会话做了什么(上传、下载文件,计划任务,新建网站)。然后在 设置 中开启 Google 身份验证器(两步验证),设置安全入口,并尽可能按 IP 限制面板访问,具体请参阅 宝塔面板安全加固指南。

第 5 步:每次 SSH 登录都收到 Telegram 消息

通过 @BotFather 创建一个 Telegram 机器人,给它发一条消息,然后按照 AI 服务器日报指南 获取您的 chat ID。接着创建告警脚本:

cat > /usr/local/bin/ssh-login-alert.sh <<'EOF'
#!/bin/bash
# Called by PAM when an SSH session opens: send user, source IP and host to Telegram
[ "$PAM_TYPE" = "open_session" ] || exit 0
TG_TOKEN="123456789:replace-with-your-bot-token"
TG_CHAT="123456789"
TEXT="SSH login on $(hostname): user=${PAM_USER} from=${PAM_RHOST} at $(date '+%F %T %Z')"
curl -s -m 5 "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
  --data-urlencode "chat_id=${TG_CHAT}" --data-urlencode "text=${TEXT}" >/dev/null 2>&1 &
exit 0
EOF
chmod 700 /usr/local/bin/ssh-login-alert.sh

将其接入 PAM,使每个 SSH 会话(包括密钥登录和隧道)都会触发它:

echo "session optional pam_exec.so /usr/local/bin/ssh-login-alert.sh" >> /etc/pam.d/sshd
grep -i "^UsePAM" /etc/ssh/sshd_config   # must be "UsePAM yes" (the default on most systems)

保持当前 SSH 窗口不要关闭,从第二个窗口登录,确认能收到 Telegram 消息。optional 关键字和 5 秒超时可以确保 Telegram 故障时绝不会影响您登录。

如需在告警中加入密钥指纹,可在脚本中从 journalctl -u ssh -n 20 读取该用户最新的 Accepted 记录。脚本要尽量简短:每次登录都会运行它。

第 6 步:让登录凭据难以被盗用

  • 只使用密钥登录并禁用密码:Linux SSH 密钥登录。
  • 切勿在多台服务器上使用同一个 root 密码。否则一个密码被盗,所有机器都会被打开,包括跳板机和管理服务器。
  • 使用 Fail2ban 拦截暴力破解,并尽可能不让面板端口对公网开放。
  • 如果发现无法解释的登录,在做任何其他修改之前,请先按照 检查 Linux 服务器是否被入侵 进行排查,并更换该服务器能接触到的所有密码和密钥。

常见问题

last 没有任何记录,但 auth.log 里有登录

非交互式会话(scp、sftp、隧道)通常不会写入 wtmp。SSH 日志和上面的 PAM 告警可以捕获这些登录。

日志文件会轮转,最多能查多久以前的记录?

检查 /var/log/auth.log.1 和压缩的 .gz 文件(zgrep Accepted /var/log/auth.log*)。如需更长时间的历史,请将日志发送到另一台服务器,或保留 Telegram 告警消息。

按照以上步骤操作后仍未解决?请 提交工单,IMIDC 7×24 小时技术团队将为您处理。请附上服务器 IP 和可疑的日志记录,以便我们更快定位问题。

这篇文章有帮助吗?

相关教程