Most break-ins are discovered late because nobody looks at who logs in. An attacker with a stolen password logs in exactly like you do, and the log line looks normal unless you know which IPs and keys are yours. This guide shows how to audit SSH logins on a Linux server, map each login to a key, check aaPanel (BaoTa) panel logins, and send a Telegram message every time someone logs in, so a stranger stands out within seconds.
who # interactive sessions
ss -tnp | grep sshd # every SSH connection, including tunnels without a terminal
ssh -N) does not open a terminal, so it does not appear in who or w. Always check ss -tnp or ps -ef | grep "sshd:" as well. A connection from an IP you do not recognise that has been open for days is a serious warning sign.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
Each line shows the method, user, source IP and, for keys, the key fingerprint:
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...
Summarise them to see every source IP and method at a glance:
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
If you only log in with keys, any Accepted password line is suspicious.
List the fingerprints of every key that may log in, then compare them with the fingerprints in the log:
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
Every key should have a comment you recognise (such as alice@laptop). Remove keys you cannot explain, and check that nobody added extra key files through AuthorizedKeysFile in /etc/ssh/sshd_config.
In aaPanel, the home page shows the latest panel logins, and Logs → Panel logs lists every login with its IP. You can also read them from the command line:
sqlite3 /www/server/panel/data/default.db \
"select addtime, log from logs where type in ('Login','用户登录') order by id desc limit 30"
After a login, check what that session did in the same logs (file uploads, downloads, cron jobs, new sites). Then turn on Google Authenticator (two-step verification) in Settings, set a security entrance and limit panel access by IP where you can, as described in the aaPanel security hardening guide.
Create a Telegram bot with @BotFather, send it a message, and get your chat ID as shown in the AI daily server report guide. Then create the alert script:
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
Hook it into PAM so it runs for every SSH session, including key logins and tunnels:
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)
Keep your current SSH window open, log in from a second window and check that the Telegram message arrives. The optional keyword and the 5-second timeout mean a Telegram outage never blocks your login.
Accepted line for that user from journalctl -u ssh -n 20 inside the script. Keep the script short: it runs on every login.Non-interactive sessions (scp, sftp, tunnels) often do not write to wtmp. The SSH log and the PAM alert above catch them.
Check /var/log/auth.log.1 and the compressed .gz files (zgrep Accepted /var/log/auth.log*). For longer history, send logs to another server or keep the Telegram alerts.
Still stuck after following these steps? Open a support ticket and the IMIDC 24/7 technical team will help. Include the server IP and the suspicious log lines so we can pinpoint the issue faster.