Every server with a public IP address gets scanned and login-attempted within minutes of going online. Seeing thousands of failed attempts is normal. This guide shows how to check whether any of them succeeded.
1. Look at the failures first
$ sudo lastb | head -50 $ sudo lastb | wc -l
lastb lists failed login attempts. Thousands of entries from many different countries, trying usernames like admin, test, oracle, and root, is automated scanning. It means bots found your IP address, not that anyone targeted you.
The failures do not matter. What matters is whether anything succeeded.
2. Look at what succeeded
$ last -20 $ who $ w
last shows successful logins with times and source addresses. Read this list carefully. Every entry should be you, from an address you recognize. who and w show who is logged in right now.
If you see a successful login from an address you do not know, treat the server as compromised and go to step 6.
3. Read the auth log
$ sudo grep "Accepted" /var/log/auth.log$ sudo grep "Accepted" /var/log/secureAccepted password or Accepted publickey lines are successful logins. This is the single most useful search on the whole server. Check the username, the time, and the source address on every line.
If your logs have already rotated, use the journal instead: sudo journalctl -u sshd | grep Accepted.
4. Check for accounts that should not exist
An attacker who gets in usually adds a way back.
$ awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd $ awk -F: '$2 == "" {print $1}' /etc/shadow $ sudo grep -rn "" /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys
The first command lists normal user accounts; you should recognize all of them. The second lists accounts with no password, which should return nothing. The third prints every SSH key that can log in. An unknown key is a serious finding.
5. Check what is running and listening
$ ps aux --sort=-%cpu | head -15 $ ss -tulnp $ sudo crontab -l $ ls -la /etc/cron.d/
Look for processes you did not start, especially ones using a lot of CPU, which usually means crypto mining. ss shows every listening port; anything you cannot explain deserves attention. Cron entries are the other common place to hide a restart mechanism.
High CPU with no obvious cause is the classic sign
The most common outcome of a compromised VPS is a crypto miner. It runs at 100% CPU and often hides under a normal looking process name. If your server is suddenly slow and ps shows an unfamiliar process at the top, look there first.
6. If you find a real compromise
Do not clean it up and carry on. Once someone has had root, you cannot be sure what is left behind.
- Take a snapshot of the server first, so you have evidence and can look again later.
- Copy off only your data, never binaries or system files.
- Reinstall the operating system from scratch.
- Change every password and key that was on the server, including any it could reach.
- Rebuild with key-only SSH login and a firewall before restoring the data.
7. Reduce the noise
You will not stop the scanning, but you can stop it reaching anything:
- Turn off password authentication and use SSH keys.
- Set
PermitRootLogin no. - Install fail2ban so repeated failures get banned automatically.
- Keep the firewall closed to everything you do not use.
Our guide on the first ten minutes on a new VPS sets all of these up in one pass. With keys only, a brute force attempt cannot succeed no matter how many times it runs, and the log noise becomes harmless.
Quick reference
| Question | Command |
|---|---|
| What failed? | sudo lastb | head -50 |
| What succeeded? | last -20 |
| Who is on now? | who, w |
| Successful SSH logins | grep Accepted /var/log/auth.log |
| Unknown accounts | awk -F: '$3 >= 1000 {print $1}' /etc/passwd |
| Unknown keys | cat ~/.ssh/authorized_keys |
Where to go next
If everything in last is you, the server is fine. Switch to key-only login and stop reading the failure logs. If it is not you, reinstall the server instead of cleaning it up.