sshd "Accepted publickey" and "Accepted password": Successful SSH Login
Published
sshd authenticated the named account — the line records a completed SSH login with the method used, the user, the client address and source port, and for public keys the key type and fingerprint that was accepted.
What it looks like
Oct 18 03:51:11 web1 sshd-session[48211]: Accepted publickey for deploy from 203.0.113.7 port 54321 ssh2: ED25519 SHA256:0K3bVn2Q1sYgq7Wd9rHcLm4xPzT6uEa8ZfJiRvNtBoU
- 1Time — When it was logged; this format has no year or time zone
- 2Host — The server’s host name
- 3Program — sshd-session, one process per connection, and its process ID: a connection’s lines share it
- 4User — The account name
- 5Source address — The client’s IP address
- 6Source port — The client’s source port; with the address it identifies one connection
- 7Protocol — SSH protocol version 2
- 8Key type — The type of key that was accepted
- 9Key fingerprint — Its SHA256 fingerprint; ssh-keygen -lf ~/.ssh/authorized_keys prints the same form
Example lines as /var/log/auth.log shows them (/var/log/secure on RHEL and Fedora):
Oct 18 03:51:11 web1 sshd-session[48211]: Accepted publickey for deploy from 203.0.113.7 port 54321 ssh2: ED25519 SHA256:0K3bVn2Q1sYgq7Wd9rHcLm4xPzT6uEa8ZfJiRvNtBoU Oct 18 04:02:37 web1 sshd-session[48344]: Accepted publickey for backup from 198.51.100.22 port 40118 ssh2: RSA SHA256:9pQrLx2Dm7Yc4Vn1tKb6ZaWgEoJ3sHfUi0QvXdRy5Tk Oct 16 21:14:02 web1 sshd-session[41190]: Accepted password for alice from 192.0.2.44 port 51902 ssh2
On our own server, the 30 days to 25 October 2026
… for … from … port … ssh2…
19,863
lines · about 662 a day · 28 source addresses
Last seen 25 October 2026
… for … from … port … ssh2…
0
lines · about 0.00 a day
LogTriage's production API server (Hetzner, Germany): port 22 open to the internet, key-only since 6 October 2026 (password and keyboard-interactive authentication off); nginx in front of the API on ports 80 and 443. Counted weekly from the sshd journal; no address ever leaves the server. More in the monthly attack report; which free blocklists already list these attackers is measured in the IP blocklist report, and you can check the addresses in your own log.
Where the line comes from
Format strings as written in the source of OpenSSH 10.2p1 — the versions this server runs. Each links to the exact line.
… for … from … port … ssh2…
-
%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%smessage · auth.c:294 (OpenSSH) -
authmsg = authenticated ? "Accepted" : "Failed";result word · auth.c:287 (OpenSSH) -
authctxt->valid ? "" : "invalid user ",added for unknown users · auth.c:298 (OpenSSH)
… for … from … port … ssh2…
-
%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%smessage · auth.c:294 (OpenSSH) -
authmsg = authenticated ? "Accepted" : "Failed";result word · auth.c:287 (OpenSSH) -
authctxt->valid ? "" : "invalid user ",added for unknown users · auth.c:298 (OpenSSH)
What it means
Every authentication outcome sshd logs comes from one statement, do_log2() at auth.c:294, with the format %s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s. Reading an Accepted line is reading that format left to right:
- The result word. auth.c:287 is
authmsg = authenticated ? "Accepted" : "Failed";.Acceptedmeans this authentication attempt succeeded. The two branches above it producePostponedandPartialinstead. - The method, and a submethod joined by a slash when there is one (
submethod != NULL ? "/" : "") — hencepublickey,password, or forms such askeyboard-interactive/pam. invalid user, inserted at auth.c:298 when the authentication context is not valid. On Accepted lines it is absent, so the account named is one the host knows.- The user name, then the client’s address and the client’s source port for that TCP connection.
- The trailing text, built from
format_method_key()or fromauth_method_info. For public keys that is the key type and fingerprint of the key that was accepted; for a password there is nothing to describe, so the line ends atssh2.
So the line is the moment the credential check passed. It does not say what the session then did, and it does not say the person at the other end is the account’s owner — only that a key or password that the server accepts was presented from that address.
Is it an attack?
| Pattern | Reading |
|---|---|
| Public key, known account, host and key fingerprint you recognise | Routine login |
| Accepted from an address that produced a run of Failed password or Invalid user lines minutes earlier | Treat as a compromise until proven otherwise |
Accepted password on a host you believe is key-only | Configuration drift — PasswordAuthentication or KbdInteractiveAuthentication is still on somewhere |
| Public key whose fingerprint is not in your inventory | Someone may have appended a key to authorized_keys (ATT&CK T1098.004) |
| Accepted for a service or deploy account from an address that is not the CI runner or bastion | Stolen key material, or key reuse outside the intended path |
Accepted for root | Compare against PermitRootLogin; the manual’s default is prohibit-password, which disables password and keyboard-interactive authentication for root |
A single Accepted line is informational — healthy servers write them constantly. What changes its severity is what surrounds it: the failures before it, the account, the fingerprint and the source address.
How to investigate
# Every successful login in the last 24 hours
# (Debian/Ubuntu unit is ssh; on RHEL/Fedora use -u sshd)
sudo journalctl -u ssh --since "24 hours ago" \
| grep -E 'Accepted (publickey|password|keyboard-interactive)'
# Who got in, with what method, from where (/var/log/auth.log; RHEL/Fedora: /var/log/secure)
sudo grep ' Accepted ' /var/log/auth.log \
| awk '{for(i=1;i<=NF;i++) if($i=="Accepted") print $(i+1), $(i+3), $(i+5)}' \
| sort | uniq -c | sort -rn
# Any password logins at all on a host that should be key-only?
sudo grep 'Accepted password' /var/log/auth.log
# Which key let them in? Compare the fingerprint on the line with the account's keys
sudo ssh-keygen -lf /home/deploy/.ssh/authorized_keys
# Did that source fail repeatedly before it succeeded?
sudo grep '203.0.113.7' /var/log/auth.log
# Everything one connection logged, by PID
sudo grep 'sshd-session\[48211\]' /var/log/auth.log
If the fingerprint is unknown, check the modification time and owner of every authorized_keys file before deleting anything, and keep a copy. If the source failed first and succeeded after, that is the brute-force-to-access transition the SSH brute-force rule is built around; an exported auth.log can be grouped by source and account in the browser log analyzer.
How to stop it
You do not stop Accepted lines — you decide who is able to produce one.
- Turn off passwords.
PasswordAuthenticationandKbdInteractiveAuthenticationboth default toyes. Set both tonoandAccepted passwordlines become impossible. The manual notes that because PAM keyboard-interactive authentication “usually serves an equivalent role to password authentication”, you should disable one of the two whenUsePAMis enabled. - Keep keys as the only way in.
PubkeyAuthenticationdefaults toyes; the keys read come fromAuthorizedKeysFile, whose default is.ssh/authorized_keysplus.ssh/authorized_keys2. Monitor both paths for changes. - Narrow the account list with
AllowUsers; by default login is allowed for all users, and the manual’sUSER@HOSTform also restricts particular users to particular hosts, with CIDR address matching. - Require two methods for sensitive hosts with
AuthenticationMethods, for examplepublickey,keyboard-interactive— successful authentication then requires completing every method in one of the listed sets, and the first step appears as aPartialline. - Set
PermitRootLogindeliberately rather than relying on the default.
sudo sshd -t && sudo systemctl reload ssh
Validate before reloading and keep an existing session open until a new one works.
Lines you will see next to it
- … for … from … port … ssh2… sshd rejected a password authentication attempt — the line names the account that was tried, the client address and the client's source port, and marks names that are not usable accounts on this host with "invalid user".
- Invalid user … from … port … sshd rejected the login because the name the client asked for is not a valid account on this host, so no password or key was ever checked against a real user.
- authentication failure; logname=… uid=… euid=… tty=… ruser=… rhost=… PAM's pam_unix module rejected the credentials sshd asked it to check — the line names the client address in rhost= and, when it has one, the account in user=.
- maximum authentication attempts exceeded for … from … port … ssh2 One SSH connection used up every authentication attempt sshd allows it — the MaxAuthTries limit, 6 by default — so sshd logged the account name, source address and port and tore the connection down.
Detect it
Frequently Asked Questions
- Does the line tell me which key was used?
- For public key authentication, yes. The trailing text comes from `format_method_key()`, so the line ends with the key type and the key's SHA256 fingerprint. Run `ssh-keygen -lf` against the account's authorized_keys file and compare fingerprints to find out exactly which entry let the session in — and whether that entry is one you put there.
- Why do "Accepted password" lines have nothing after "ssh2"?
- The same format string ends with two optional strings that are filled from the key description or from `auth_method_info`. A password authentication has no key to describe, so both are empty and the line stops at `ssh2`. That difference is why the two messages need two different search patterns.
- Can an "Accepted" line ever say "invalid user"?
- The `invalid user ` text is inserted by the same statement whenever sshd's authentication context is not marked valid, which is why failures for unknown names read "Failed password for invalid user admin". In practice the accounts you see on Accepted lines are real accounts; treat an Accepted line as naming a user that exists on the host.
- What does "Partial publickey" mean next to these lines?
- It comes from the same log statement, two branches earlier — sshd writes "Partial" when a method succeeded but more are still required, and "Postponed" when the method is not finished. With AuthenticationMethods demanding two methods you see the first step logged as Partial and only the last one as Accepted.
Run your own auth.log through it
Paste or drop /var/log/auth.log (or journalctl -u ssh output) into the free browser analyzer: brute force, password spraying, a successful login after failures and invalid-user sweeps are flagged with the evidence lines. Nothing is uploaded.