Home / Blog / Cheat Sheets
Linux SSH Log Cheat Sheet for Beginner SOC Analysts
Where Linux keeps SSH logs, what each common log line means and the simple grep and journalctl commands that tell you who logged in, from where and how.
Most Linux servers are managed over SSH (Secure Shell), so SSH logs are often the first place you look when a Linux alert lands in your queue. This cheat sheet shows new analysts where those logs live, how to read the most common lines and which short commands answer the basic questions: who logged in, from where, and did anyone try to guess a password?
Scenario: Your SIEM (Security Information and Event Management system, the tool that collects and searches logs) raises "Possible SSH brute force on WEB-07". The alert says 450 failed logins in ten minutes from 203.0.113.50. Your lead asks two questions: is it still happening, and did any login succeed? You can answer both with a few lines on the command line.
Where are SSH logs kept?
The SSH server program is called sshd (the SSH daemon, a program that runs in the background). It writes its messages through the system logger. Where they end up depends on the Linux distribution, which is the flavour of Linux the server runs.
| Distribution | Where to look | Notes |
|---|---|---|
| Ubuntu | /var/log/auth.log | Also in the journal. The service is called ssh. |
| Debian 12 and later | journalctl | rsyslog is no longer installed by default, so auth.log may not exist. |
| RHEL, Rocky, AlmaLinux, Fedora | /var/log/secure | RHEL is Red Hat Enterprise Linux. The service is usually sshd. |
| Any systemd system | journalctl | The journal is a binary log. You read it with the journalctl command. |
Note: Reading these logs needs elevated rights, so most commands below start with sudo. On a production server, only run read commands and follow your team's rules for accessing client or company systems. Often you will search the same logs in the SIEM instead.
What do the common log lines mean?
Each SSH log line starts with a date, the host name and the process name with its process ID, for example sshd[2214]:. The useful part is the message after that. These are the messages you will see most.
Accepted password for alice from 10.0.4.22 port 51514 ssh2
Accepted publickey for alice from 10.0.4.22 port 51514 ssh2: ED25519 SHA256:k3Xb...
Failed password for alice from 203.0.113.50 port 40022 ssh2
Failed password for invalid user admin from 203.0.113.50 port 40188 ssh2
Invalid user admin from 203.0.113.50 port 40188
Connection closed by authenticating user alice 203.0.113.50 port 40022 [preauth]
pam_unix(sshd:session): session opened for user alice(uid=1001) by (uid=0)
Disconnected from user alice 10.0.4.22 port 51514
| Message | Plain meaning | Why you care |
|---|---|---|
Accepted password | Login worked using a password | A success. Check it was expected. |
Accepted publickey | Login worked using an SSH key | Keys are normal for admins. Note which key fingerprint was used. |
Failed password for | The account exists, the password was wrong | Many of these is password guessing. |
invalid user | The username does not exist on this server | Scanners try common names such as admin, test and oracle. |
[preauth] | Happened before login finished | The connection never got a session. |
session opened | PAM started a session for the user | PAM (Pluggable Authentication Modules) handles login checks. This confirms a real session. |
Disconnected from user | A logged in user left | Gives you the session end time. |
Tip: From OpenSSH 9.8, the server is split into two programs, and some messages are tagged sshd-session instead of sshd. If a search for sshd misses lines on a newer server, include both names. Exact wording can also vary a little between versions, so always check a few real lines first.
Search the log file with grep
grep prints every line that contains the text you give it. It is the quickest way to start.
sudo grep "Failed password" /var/log/auth.log
sudo grep "Accepted" /var/log/auth.log
sudo grep "203.0.113.50" /var/log/auth.log
- Line 1 shows every failed password attempt.
- Line 2 shows every successful login, whether by password or key.
- Line 3 shows everything the suspicious IP address (Internet Protocol address, the network address of the other computer) did.
On RHEL style servers, swap /var/log/auth.log for /var/log/secure. Older entries may sit in rotated files such as auth.log.1, so check those too if the time you need is missing.
Count attempts per IP address
This one line answers "who is attacking us the most?" It looks long, but each part does one small job, joined with the pipe symbol |, which passes the output of one command into the next.
sudo grep "Failed password" /var/log/auth.log | grep -oE "from [0-9.]+" | sort | uniq -c | sort -rn | head
grep "Failed password"keeps only the failed attempts.grep -oE "from [0-9.]+"keeps only the "from" and the IP address.-omeans "only the match" and-Eallows the pattern.sortputs identical addresses next to each other.uniq -ccounts each address.sort -rnputs the biggest count first.headshows the top ten.
Read the journal with journalctl
On servers without auth.log, or when you want an easy time filter, use the journal.
sudo journalctl -u ssh --since "1 hour ago"
sudo journalctl -u sshd --since "1 hour ago"
sudo journalctl -u ssh --since "1 hour ago" | grep "Accepted"
- Line 1 is for Ubuntu and Debian, where the service is named
ssh.-umeans "this unit", which is systemd's word for a service. - Line 2 is for RHEL and Fedora, where it is usually named
sshd. - Line 3 combines the journal with grep to show only successful logins.
You can also give exact times, such as --since "2026-11-09 08:00" --until "2026-11-09 09:00", which is handy when you match an alert window. Add -f to follow new lines live, a quick way to check whether an attack is still happening.
The same search in Microsoft Sentinel
If your Linux servers send syslog to Microsoft Sentinel, the lines land in the Syslog table. This short KQL (Kusto Query Language) search counts failed passwords per server.
Syslog
| where TimeGenerated > ago(1h)
| where ProcessName in ("sshd", "sshd-session")
| where SyslogMessage has "Failed password"
| summarize Failures = count() by HostName
Line by line: pick the Syslog table, keep the last hour, keep SSH messages under either process name, keep failed passwords, then count them for each host.
Which patterns should you escalate?
Internet facing SSH servers see failed logins all day from automated scanners. What matters is the pattern, and above all whether anything succeeded.
Failures, then success
HighMany Failed password lines from one IP address, then Accepted password from the same address.
Escalate straight away. The password may have been guessed. This is T1110.001 Password Guessing.
Unexpected root login
HighAccepted for root, especially from an external address.
Most teams block direct root login. Escalate and check what the session did.
Login from a new place
MedA valid user logs in from an IP address they have never used, or at an odd hour.
Confirm with the user or system owner. Stolen credentials look like normal logins (T1078 Valid Accounts).
Internal SSH hopping
MedOne internal server logging in to many others over SSH in a short time.
Could be lateral movement (T1021.004 Remote Services: SSH). Ask whether it is a known admin or automation job.
Watch out: Lots of invalid user lines with no success is usually internet background noise. Note it and check the server is patched and uses keys, but do not panic. The single Accepted line hidden among thousands of failures is the one that matters.
One more thing to know: OpenSSH 9.8 and later turn on a feature called PerSourcePenalties by default. It temporarily blocks addresses that keep failing to log in. If an attack seems to stop suddenly on a new server, this may be why, and the attacker may come back once the penalty expires.
Write it up and keep learning
When you hand over or close the alert, include the facts your lead will ask for.
- Server name, time window and log source you checked.
- Source IP addresses and the number of failed attempts.
- Whether any login succeeded, for which account and by password or key.
- The exact commands or queries you ran, so someone can repeat them.
- Your recommendation: close as noise, block the address, or escalate.
Key takeaways
- SSH logs live in
/var/log/auth.logon Ubuntu,/var/log/secureon RHEL, and the journal everywhere systemd runs. Failed passwordmeans wrong password,invalid usermeans the name does not exist andAcceptedmeans a login worked.- Use
grepto find lines andsort | uniq -cto count them. - Use
journalctl -u sshor-u sshdwith--sincefor time based searches. - Always check for a success after many failures, because that is the pattern to escalate.
Save the commands from this page somewhere you can reach on shift, then try them on your own practice machine this week. Once you can read SSH logs without looking anything up, Linux alerts will feel far less mysterious.
Written by Ben, Cybersecurity Student