sshd Linux auth.log / journal Triage: low

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

  1. 1Time — When it was logged; this format has no year or time zone
  2. 2Host — The server’s host name
  3. 3Program — sshd and its process ID
  4. 4Source address — The client’s IP address
  5. 5Source port — The client’s source port; with the address it identifies one connection
  6. 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%s message · 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 admin when 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: grep sshd-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.

PatternReading
One line, one source, no user namedA scanner or port checker that opened TCP, did nothing, and was timed out
Many sources, each one or two lines, spread through the dayInternet-wide scanning — the usual baseline
One source holding many connections open to the limit, repeatedlyResource 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 identifierThe 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 hoursBenign: somebody left a host-key confirmation, passphrase or multi-factor prompt unanswered
From a monitoring host at a fixed intervalA health check that connects to port 22 and never authenticates
Any Accepted line from the same source afterwardsStop 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 (default 10: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 PerSourcePenalties enabled. 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 (default yes) and, where PAM is enabled, KbdInteractiveAuthentication no (default yes). 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

MITRE ATT&CK: T1595.001T1021.004

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.