SSH logs: find authentication events and alert on suspicious access

Locate SSH authentication logs, configure sshd logging safely, analyze failed logins, and build Guance alerts for repeated failures and unexpected successful access.

Best practices
Structured log records moving through a collection pipeline

SSH server logs record authentication attempts and selected connection or session events. They help you investigate failed logins, unexpected successful access, and repeated attempts against particular accounts. They are not a full recording of every command or every remote action; that requires a separate audit design.

Start by confirming where your distribution sends OpenSSH logs. Then retain successful authentications as well as failures, parse their fields consistently, and alert on events that matter for your access policy.

Find the logs

Environment Common location or command
Debian or Ubuntu with syslog file routing /var/log/auth.log
RHEL-family systems or Fedora with syslog file routing /var/log/secure
A systemd journal journalctl -u ssh.service or journalctl -u sshd.service, depending on the installed unit

These paths depend on the syslog configuration and installed packages. A minimal system may retain authentication events only in the journal. Journal persistence and file rotation determine how far back you can investigate.

A quick search of /etc/ssh/sshd_config is only a starting point: included files and defaults can change the effective configuration. On a host you administer, inspect it with:

sudo sshd -T | grep -E '^(loglevel|syslogfacility) '

Locate the daemon's absolute path if it is not in your administrative PATH. Use sshd -T -C ... when inspecting connection-dependent Match settings, and inspect the syslog/journal configuration to determine the destination. The sshd manual documents test modes.

Read authentication events

Successful password and public-key authentication commonly look like this:

Jul 17 15:45:23 web sshd[5678]: Accepted password for devuser from 10.0.2.15 port 49812 ssh2
Jul 17 15:49:45 web sshd[5680]: Accepted publickey for jenkins from 10.0.2.20 port 52413 ssh2: RSA SHA256:LmNo...

An unsuccessful password attempt against a nonexistent account may look like this:

Jul 17 15:47:10 web sshd[5679]: Failed password for invalid user admin from 192.0.2.82 port 38654 ssh2

invalid user indicates that the supplied username was not a valid local account for this attempt. It is a useful scanning signal, although a mistaken username can produce it too. The source address above is a documentation example, not a live threat indicator.

A disconnect event can follow:

Jul 17 16:02:33 web sshd[5678]: Disconnected from user devuser 10.0.2.15 port 49812

In these file examples, the prefix supplies a timestamp, hostname, and process/PID; the message provides event-specific fields such as the user, source address, port, or authentication method. Not every SSH message includes every field. Older syslog timestamps also omit the year and timezone, so the collector must interpret them in context. OpenSSH versions may use different message formats and process names.

Choose a logging level and apply it safely

A configuration to evaluate for authentication auditing is:

LogLevel VERBOSE
SyslogFacility AUTHPRIV

OpenSSH defaults to INFO. VERBOSE adds authentication detail that can be useful when investigating keys and access attempts, but confirm the actual records your installed version emits. Do not assume key fingerprints appear only at this level or that the extra output is free. DEBUG and DEBUG1 are equivalent; DEBUG2 and DEBUG3 add detail and can expose private session information. Reserve them for controlled troubleshooting. See LogLevel.

AUTHPRIV selects a syslog facility. File ownership, permissions, and syslog routing enforce access restrictions; the facility name alone does not make the logs private.

Keep the current administrative session open, validate configuration, and reload the correct service unit:

sudo sshd -t
# Run only after the configuration test succeeds.
sudo systemctl reload sshd.service

Use ssh.service if that is your distribution's unit. Confirm that reload is supported and test a second login before closing the existing session. A blind restart can turn a configuration mistake into an access outage.

Analyze a single host

For a Debian-style authentication file:

# Password authentication failures in the current file.
sudo grep 'Failed password' /var/log/auth.log

# Extract the address after "from" and count these failure records.
sudo awk '/Failed password/ {
  for (i = 1; i < NF; i++) {
    if ($i == "from") { print $(i + 1); break }
  }
}' /var/log/auth.log | sort | uniq -c | sort -nr | head

# Replace ssh.service with the unit used on this host.
sudo journalctl -u ssh.service --since '1 hour ago'
sudo journalctl -u ssh.service -p err
sudo journalctl -u ssh.service -f

The address extraction works for the illustrated valid- and invalid-user password failure formats, including IPv6 addresses. It is not a general parser for every OpenSSH or PAM message. Review rotation archives separately when investigating an older period.

-p err shows error-priority messages and higher priorities; many authentication events use another priority. Do not use that filter alone to find all failed logins. Likewise, Failed password excludes public-key failures and other authentication paths.

For troubleshooting, inspect a time-bounded set of events before narrowing it further. PAM messages containing authentication failure may explain a rejected login. bad ownership or modes can indicate ownership or permission problems. Check the account's home directory, .ssh directory, and authorized-keys file; 700 and 600 are common restrictive settings, not a complete diagnosis. A key-reading error may contain key_read on some versions, but that string is not a universal signature for rejected keys. Also inspect accepted algorithms, authorized-key configuration, and account restrictions.

Centralize the records and alerts

For multiple hosts, build a collection path that makes missing data visible as well as suspicious events:

  1. Collect and parse. Configure the DataKit log collector for the actual authentication files and their permissions/rotation behavior. If the source is journal-only, establish a supported journal ingestion or forwarding path first; a file collector cannot read a nonexistent auth.log. Use Pipeline rules to extract fields such as username, src_ip, auth_method, and an explicit outcome. Test success, failure, invalid-user, IPv6, and unmatched samples.
  2. Inspect trends. In the Log Explorer, group normalized authentication failures by source address and account. Clustering can reduce repeated message noise, but it does not independently identify a new attack or establish who operates an address. Preserve the raw message for investigation.
  3. Define alerts. A log detection monitor can evaluate counts and filters. For example, detect at least one successful root authentication when direct root access is forbidden, or more than 20 failed authentications from the same src_ip within five minutes. These are starting thresholds; tune them for bastions, shared NAT addresses, legitimate mistakes, and distributed attempts.
  4. Route and investigate. Include the host, account, source, method, and time window in the event. Configure the notification destinations your team uses, such as DingTalk, WeCom, or Feishu where supported, and confirm receipt with a controlled test. Alert timing includes collection, evaluation, and notification delays.

Map a parsed failure outcome to a chosen log severity such as status="error", and success to status="info" if that matches your schema. Avoid tagging every message containing the word Failed without checking its event type. Add alerts for successful password authentication where only keys should be used, and for successful access outside approved account or source policies.

Complement monitoring with access controls: restrict direct root login and password authentication where appropriate, use MFA, and consider rate controls such as Fail2Ban. Changing the listening port may reduce routine scanning noise, but it is not an authentication control. Validate access changes with a recovery path before enforcing them.

Common questions

Do repeated failures mean the host was compromised?

No. A failure establishes that the logged attempt failed, not that the attacker gained access. Investigate suspicious successful authentications, concentrated attempts against real accounts, and unusual failures from trusted networks. Also consider log gaps and activity outside SSH.

Can I leave DEBUG enabled?

Avoid it for routine operation. Debug output can be voluminous and privacy-sensitive. Limit its scope and duration, protect the resulting records, and restore the normal level after troubleshooting.

How can I distinguish my login from an attacker's?

Correlate the source address or bastion, account, authentication method, key fingerprint where available, and expected access window. None proves identity alone: trusted networks and keys can be compromised. Retaining successful logins gives you evidence to compare with approved access.

Can Guance show the addresses responsible for most failed attempts?

Yes, after collection and parsing: filter to SSH authentication failures and group counts by src_ip. Save the query or dashboard view for continued use. The result ranks observed source addresses; it does not identify the human behind them.

References and related reading

The text-processing example was checked against representative records. Service reloads, host access controls, and Guance alerts were not exercised on a live SSH deployment.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting