Linux 伺服器

誰登入了我的伺服器?審計 SSH 和寶塔面板登入,每次登入傳送 Telegram 提醒

6 個步驟 8 分鐘閱讀 18 次閱讀 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 和可疑的日誌記錄,以便我們更快定位問題。

這篇文章有幫助嗎?

相關教程