If your Linux server is reachable on port 22, it's being attacked. This isn't paranoia — it's arithmetic. Internet-facing SSH servers receive thousands of login attempts daily from automated scanners probing default credentials, weak passwords, and common usernames. Most small-team servers have no idea this is happening because nobody's watching the logs.
This post covers how to detect SSH brute-force attacks, understand the attack patterns in your auth logs, and stop them permanently.
The auth.log: Where the Evidence Lives
On Debian and Ubuntu servers, every authentication event is written to /var/log/auth.log. On CentOS and RHEL, it's /var/log/secure. These files contain every SSH login attempt — successful and failed.
A single brute-force run looks like this in the logs:
Apr 30 04:12:33 server sshd[4821]: Invalid user admin from 198.51.100.42 port 47832
Apr 30 04:12:34 server sshd[4821]: Failed password for invalid user admin from 198.51.100.42 port 47832
Apr 30 04:12:35 server sshd[4822]: Invalid user deploy from 198.51.100.42 port 47933
Apr 30 04:12:36 server sshd[4822]: Failed password for invalid user deploy from 198.51.100.42 port 47933
High-volume attacks produce hundreds of these lines per minute.
Manual Detection
To quickly check if you're under attack:
# Count failed login attempts in the last hour
sudo grep "Failed password" /var/log/auth.log | grep "$(date '+%b %d %H')" | wc -l
# Find the top attacking IPs
sudo grep "Invalid user\|Failed password" /var/log/auth.log \
| awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
# See all unique attacking usernames being tried
sudo grep "Invalid user" /var/log/auth.log \
| awk '{print $8}' | sort | uniq -c | sort -rn | head -20
If the first command returns more than 50 failures in an hour, you're actively being targeted. If the IP list shows a single source making thousands of attempts, that's a targeted credential attack.
Severity Thresholds
Not every failed SSH login is an attack. A developer who mistyped their password three times isn't an attacker. But the pattern matters:
| Failed attempts (recent 50 log lines) | Assessment |
|---|---|
| < 10 | Normal — occasional mistype |
| 10–29 | Warning — automated scanner likely active |
| 30+ | Critical — active brute-force or credential stuffing attack |
Tink monitors auth.log on every scan and automatically raises an ssh_anomaly issue when it detects these thresholds — you don't have to remember to check.
Permanent Fix: fail2ban
fail2ban watches your logs in real time and automatically bans IPs after a configurable number of failures. It's the right long-term solution.
# Install fail2ban
sudo apt-get install -y fail2ban
# Enable and start it
sudo systemctl enable --now fail2ban
# Verify it's protecting SSH
sudo fail2ban-client status sshd
Default configuration bans IPs for 10 minutes after 5 failures. That's usually enough to stop most automated scanners.
For more aggressive protection, create /etc/fail2ban/jail.local:
[sshd]
enabled = true
bantime = 3600
findtime = 600
maxretry = 3
This bans for 1 hour after 3 failures in 10 minutes.
The Real Fix: Key-Only Authentication
Banning IPs is defensive but attackers rotate through botnets faster than bans apply. The permanent fix is eliminating password authentication entirely:
# Verify your key-based login works FIRST — do not skip this step
ssh -i ~/.ssh/your_key user@your-server
# Then disable password authentication
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
# Validate the config change
sudo sshd -t
# Apply it
sudo systemctl reload sshd
With PasswordAuthentication no, brute-force attacks become mathematically impossible — there are no credentials to guess.
Monitoring Continuously
The problem with auth.log analysis is that you have to remember to do it. Attacks happen at 3 AM on holidays. By the time you notice unusual server behavior, the attack may have been running for days.
Tink checks auth.log on every scan automatically. When it detects 10+ failed attempts, it raises a warning and sends a Telegram alert. At 30+ failures, it escalates to critical. The fix plan includes the specific grep commands to verify, fail2ban installation steps, and the sshd_config change — all ready to execute from the dashboard.
SSH brute-force detection isn't exotic security tooling. It's reading a log file that already exists on your server. The only question is whether anyone's reading it.
See the machines
Mechanic is $9/mo per machine. Scout stays free. Paid plans open Stripe checkout.