sshd "Timeout before authentication for …": What It Means
Published
A connection was accepted but did not finish authenticating inside the login grace period, so sshd terminated the pre-authentication process and the listener logged the client and that process's pid.
What it looks like
Oct 18 03:51:11 web1 sshd[924]: Timeout before authentication for 203.0.113.7 port 54321, pid = 48211
- 1Time — When it was logged; this format has no year or time zone
- 2Host — The server’s host name
- 3Program — sshd and its process ID
- 4Source address — The client’s IP address
- 5Source port — The client’s source port; with the address it identifies one connection
- 6Connection process — Process ID of the connection that timed out
Example lines as /var/log/auth.log shows them (/var/log/secure on RHEL and Fedora):
Oct 18 03:51:11 web1 sshd[924]: Timeout before authentication for 203.0.113.7 port 54321, pid = 48211 Oct 18 04:02:35 web1 sshd[924]: Timeout before authentication for 198.51.100.22 port 40118, pid = 48533 Oct 18 04:19:50 web1 sshd[924]: Timeout before authentication for invalid user admin 192.0.2.44 port 51902, pid = 48711
On our own server, the 30 days to 25 October 2026
Timeout before authentication for …, pid = …
2,566
lines · about 86 a day · 517 source addresses
Last seen 25 October 2026
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.
-
Timeout before authentication for %s, pid = %ld%smessage · sshd.c:387 (OpenSSH)
What it means
The listening sshd process forks a separate pre-authentication process for every connection it accepts and keeps track of it. When that child exits, the listener examines its exit status: a normal exit is only logged at debug level, a crash produces a different message, and the “login grace” exit status produces this line and marks the source for the grace-exceeded penalty.
So the message means one thing: the TCP connection was accepted, a per-connection process ran, and authentication had not completed when the login grace period expired, so the connection was cut. LoginGraceTime controls that window — “The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds.”
Three things are printed:
- The connection identifier — the client’s address and source port, the same identifier sshd’s other per-connection messages use, carrying a user preamble such as
invalid user adminwhen the client had already sent an authentication request naming an account. pid = <n>— the process id of the pre-authentication process that was terminated. This is your pivot: grepsshd-session[<n>]to pull up everything else that connection logged.- A trailing status detail that sshd appends to the message.
No credential was checked or rejected to produce this line. It is a clock running out, nothing more.
Is it an attack?
Usually it is background noise on any internet-facing port 22. The surrounding shape is what matters.
| Pattern | Reading |
|---|---|
| One line, one source, no user named | A scanner or port checker that opened TCP, did nothing, and was timed out |
| Many sources, each one or two lines, spread through the day | Internet-wide scanning — the usual baseline |
| One source holding many connections open to the limit, repeatedly | Resource pressure: each unauthenticated connection occupies a startup slot until it authenticates or the grace period expires |
invalid user <name> or authenticating user <name> in the identifier | The client began guessing and then stalled — read it with the invalid-user and password-failure lines on the same pid |
| From a staff address during working hours | Benign: somebody left a host-key confirmation, passphrase or multi-factor prompt unanswered |
| From a monitoring host at a fixed interval | A health check that connects to port 22 and never authenticates |
Any Accepted line from the same source afterwards | Stop triaging the timeout and investigate the session |
How to investigate
Count sources first, then follow a single connection by its pid.
# Debian/Ubuntu: the unit is ssh. RHEL/Fedora: journalctl -u sshd
sudo journalctl -u ssh --since "24 hours ago" | grep "Timeout before authentication"
# Busiest sources (/var/log/auth.log; on RHEL/Fedora /var/log/secure)
sudo grep -oP 'Timeout before authentication for (?:(?:invalid|authenticating) user \S+ )?\K[0-9a-fA-F:.]+' \
/var/log/auth.log | sort | uniq -c | sort -rn | head -20
# Account names the client had already asked for, where one was named
sudo grep -oP 'Timeout before authentication for (?:invalid|authenticating) user \K\S+' \
/var/log/auth.log | sort | uniq -c | sort -rn | head -20
# Everything one timed-out connection logged, using the pid from the line
sudo grep 'sshd-session\[48211\]' /var/log/auth.log
# Timeouts per minute — bursts point at a sweep or at startup slots being squeezed
sudo grep "Timeout before authentication" /var/log/auth.log \
| awk '{print $1, $2, substr($3,1,5)}' | uniq -c | sort -rn | head
# Did anything from those sources actually get in?
sudo grep -E "Accepted (publickey|password)" /var/log/auth.log | tail -50
If a source appears here and in invalid user or connection closed lines, treat it as one scripted client rather than three separate events. For an exported auth.log, the browser log analyzer groups lines by source address, and the SSH brute-force rule covers the guessing patterns these timeouts often sit next to.
How to stop it
You cannot stop remote clients from connecting and going quiet, so reduce how many reach the daemon and how long each one can hold a slot.
- Keep port 22 off the open internet where you can — a firewall allow-list, VPN or bastion removes most of this traffic outright.
- Tune
LoginGraceTime. The default is 120 seconds; a shorter grace period frees startup slots sooner, at the cost of users on slow links or slow prompts. - Understand
MaxStartups(default10:30:100): it “Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection.” That sentence is exactly why a pile of timing-out connections can affect real users. - Leave
PerSourcePenaltiesenabled. Penalties are on by default, and this exit path sets the grace-exceeded penalty: clients “that fail to authenticate after LoginGraceTime” are refused for 10 seconds by default, accumulating up to a maximum of 10 minutes, with a 15-second minimum before enforcement begins. - Remove password prompts from the picture with
PasswordAuthentication no(defaultyes) and, where PAM is enabled,KbdInteractiveAuthentication no(defaultyes). This will not stop clients that never authenticate, but it removes the prompts people sit in front of. - Limit who may log in at all with
AllowUsers; by default login is allowed for all users.
sudo sshd -t && sudo systemctl reload ssh
Test the configuration before reloading, and keep a working session open while you verify a new one.
Lines you will see next to it
- Connection closed by … The client at the other end of the SSH connection went away — closed it cleanly, or reset it — and sshd logged the address, port and (if the client had already named an account) the user it was trying before it quit.
- 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.
- 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.
- kex_exchange_identification(struct ssh *ssh, int timeout_ms, sshd never finished the opening banner exchange with the client — the other end went away (or sent something unreadable) before sending its identification string, so the connection ended before key exchange and before any authentication.
- …: activating … penalty of … seconds for … sshd has accumulated enough penalty against one client address range to start refusing its connections, and the line names the address, the number of seconds left on the block and what the client did to earn it.
Detect it
Frequently Asked Questions
- Does this line mean someone got in?
- No. It is written when a pre-authentication process is terminated for exceeding the login grace period, so the connection ended without a completed authentication. It also says nothing about credentials — the client may never have sent an authentication request at all. The line to look for afterwards is an "Accepted publickey" or "Accepted password" entry from the same source address.
- Why does the line come from sshd and not sshd-session?
- The listening sshd process forks a separate pre-authentication process for each connection and inspects its exit status when it ends. This message is written by that listener when the child exited because the login grace period ran out, which is why the child's process id is printed in the line rather than being the process id in the syslog tag.
- We turned off password authentication — why are these lines still appearing?
- The grace timer applies to any connection that has not successfully logged in yet, including clients that connect and never attempt authentication at all. Scanners, port checkers and stalled TCP sessions still consume the full LoginGraceTime window, so the message keeps appearing on key-only servers.
- Should I lower LoginGraceTime?
- It is a trade-off. The default is 120 seconds, and a shorter value means an unauthenticated connection occupies a startup slot for less time, which limits how long a scanner or a slow-loris style client can hold resources. Set it too low and you cut off users on slow links, multi-factor prompts or host-key confirmation prompts, so change it in small steps and watch for complaints.
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.