sshd "Failed password for … from … port … ssh2": What It Means
Published
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".
What it looks like
Oct 18 03:51:11 web1 sshd-session[48211]: Failed password for root from 203.0.113.7 port 54321 ssh2
- 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
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]: Failed password for root from 203.0.113.7 port 54321 ssh2 Oct 18 03:51:13 web1 sshd-session[48211]: Failed password for root from 203.0.113.7 port 54321 ssh2 Oct 18 03:52:40 web1 sshd-session[48230]: Failed password for invalid user admin from 198.51.100.22 port 40118 ssh2 Oct 18 04:07:02 web1 sshd-session[48502]: Failed password for deploy from 192.0.2.44 port 51902 ssh2
On our own server, the 30 days to 25 October 2026
… for … from … port … ssh2…
79,653
lines · about 2,655 a day · 693 source addresses
Last seen 6 October 2026
None since the server went key-only on 6 October 2026 — turning off password authentication removed this line entirely.
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.
-
%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
sshd writes this line from its authentication logging after an attempt finishes without authenticating the user. The result word comes straight from authmsg = authenticated ? "Accepted" : "Failed";, so a successful login uses the same sentence with Accepted in front — grep for the shape and you get both outcomes side by side. Two other words can appear in that slot: Partial, when one method of a multi-method requirement succeeded, and Postponed, when the method hands off to another stage.
The rest of the line is positional: the authentication method (password here, with a /submethod suffix when one applies, as in keyboard-interactive/pam), then an optional invalid user marker, the user name the client asked for, the client’s IP address, the client’s source port, and ssh2. The format has two trailing fields for extra method detail — a public-key failure appends key information there — which is why password failures end cleanly at ssh2.
The invalid user marker is the part worth understanding. On the first authentication request of a connection sshd looks the name up; if the lookup returns nothing usable it clears the “valid” flag and substitutes a fake password record so that timing does not reveal which names exist. That flag stays set for the whole connection, and it drives this marker. It is not only missing accounts: a real account can be refused by the same lookup — AllowUsers not matching, a locked account, a shell that does not exist or is not executable — and sshd logs a separate User … not allowed because … line for those cases while subsequent failures still read invalid user. A separate Invalid user line is the reliable evidence that the name itself is unknown.
Is it an attack?
Unsolicited, almost always. Any host with port 22 reachable from the internet gets a continuous stream of these from scanners and botnets. Read the surrounding pattern rather than individual lines.
| Pattern | Reading |
|---|---|
| One source, many different names, minutes apart | Dictionary brute force / name guessing |
Many sources, the same short list (root, admin, test, ubuntu) | Untargeted botnet sweep |
Names matching your stack or staff (deploy, postgres, solana) | The host was fingerprinted; the list is tailored |
Repeated failures for one real account (no invalid user) | Targeted guessing — treat as higher priority |
| An internal address, one account, on a schedule | A job, backup agent or CI runner with a stale password |
Failures then an Accepted line from the same address | Investigate immediately |
How to investigate
Count sources, names and attempts per connection before judging anything.
# Last 24 hours from the journal (Debian/Ubuntu unit is ssh; RHEL/Fedora use -u sshd)
sudo journalctl -u ssh --since "24 hours ago" | grep "Failed password for"
# Busiest source addresses (/var/log/auth.log; on RHEL/Fedora /var/log/secure)
sudo grep -oP 'Failed password for (?:invalid user )?\S+ from \K\S+' /var/log/auth.log \
| sort | uniq -c | sort -rn | head -20
# Which names are being tried
sudo grep -oP 'Failed password for (?:invalid user )?\K\S+' /var/log/auth.log \
| sort | uniq -c | sort -rn | head -20
# Failures against accounts that really exist here — the ones that matter
sudo grep "Failed password for" /var/log/auth.log | grep -v "invalid user"
# Did anything from those addresses get in?
sudo grep -E "Accepted (password|publickey)" /var/log/auth.log | tail -50
Check every name from the second command against /etc/passwd. If a source is internal, the account in the line is usually the one a script was configured with — find the job and fix its credential rather than blocking the host. For an exported auth.log, the free browser log analyzer groups these lines by source and account, and the SSH brute-force rule encodes the one-source-many-names pattern as a detection.
How to stop it
- Remove passwords from the equation.
PasswordAuthenticationdefaults toyes, so set it tonoexplicitly and use keys. If PAM is in play, also setKbdInteractiveAuthentication no— the manual notes that PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, andUsePAMenables PAM using both. - Keep
PermitRootLoginat or below its default ofprohibit-password, which disables password and keyboard-interactive authentication for root. - Limit who may log in at all with
AllowUsers; by default login is allowed for all users, and patterns may take theUSER@HOSTform with CIDR host criteria. - Leave
PerSourcePenaltiesenabled — penalties are on by default, and a client that disconnects after one or more unsuccessful authentication attempts is refused for 5 seconds by default, accumulating up to a maximum of 10 minutes. - Keep
MaxAuthTries(default 6) andLoginGraceTime(default 120 seconds) tight so each connection yields few guesses. - Best of all, do not expose port 22 to the whole internet: restrict it at the firewall or put it behind a VPN or bastion.
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
- 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.
- … for … from … port … ssh2… 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.
Detect it
Frequently Asked Questions
- Does the line mean the account exists on my server?
- Only when the words "invalid user" are absent. sshd adds that marker when the account lookup for the requested name returned nothing usable, which covers names that do not exist and accounts the server refuses for other reasons. A failure without the marker names an account sshd was willing to authenticate, so it is the more interesting of the two.
- Why do I see the same user name and the same source port several times in a row?
- The port is the client's source port for one TCP connection, so repeated lines with the same port and the same PID are repeated attempts inside a single session. MaxAuthTries limits how many attempts a connection gets; the manual gives its default as 6.
- Password authentication is disabled here — do these lines still matter?
- They still tell you who is probing you and which names they expect to find, which is worth tracking even when no password could let anyone in. What matters most is correlation — check that no Accepted line for publickey or password exists from the same addresses, and watch for failures against real staff or service accounts.
- How many failures should raise an alert?
- Counting raw lines on an internet-facing host produces alerts all day. Alert on shape instead: a single source trying many distinct names in minutes, repeated failures for an account that actually exists, the same name tried from many addresses, or any successful authentication from an address that had been failing.
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.