Skip to main content
DevOps Insightsguides & answers

OpenSSH · troubleshooting

kex_exchange_identification: Connection closed by remote host

The TCP connection opened, but the server closed or reset it before the two sides even exchanged SSH greetings. Usually sshd is refusing new connections for a while (too many waiting logins, or a penalty on your address), a firewall cut it, or the port is not running SSH at all.

Reproduced on OpenSSH 10.3p1, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 9 sections

Before you start

  • The full ssh -v output, and if you can, the server's sshd log.

Run this first

step 1 of 1
ssh -v HOST 2>&1 | grep -E 'banner line|kex_exchange_identification|Connection (closed|reset)'

Look for Not allowed at this time (sshd refusing), non-SSH banner lines (wrong service), or nothing (cut in between)

The lines just before the error say who hung up and, often, why.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

What does ssh -v print just before the error?

Cause space

4 of 4 still possible

  • Too many connections are waiting to log inCommon
  • sshd is penalising your address (OpenSSH 9.8 and later)Occasional
  • The port is not running SSHOccasional
  • A firewall, intrusion-prevention system or tool such as fail2ban cut the connectionOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    ssh -v HOST 2>&1 | grep -E 'banner line|kex_exchange_identification|Connection (closed|reset)'

    The lines just before the error say who hung up and, often, why.

    Look for Not allowed at this time (sshd refusing), non-SSH banner lines (wrong service), or nothing (cut in between)

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Too many connections are waiting to log in

Common

sshd limits unauthenticated connections. The default, 10:30:100, starts refusing 30% of new ones once 10 are waiting, and all of them at 100. Bots trying passwords fill these slots quickly on a server open to the internet, and so can a burst of CI jobs.

Confirm

sudo journalctl -t sshd --since '-1h' | grep -i maxstartups

drop connection ... past MaxStartups lines (Debian and Ubuntu also log to /var/log/auth.log)

Fix

  • Reduce who can reach port 22: a firewall rule or security group allowing only your addresses removes the bot traffic that fills the slots.
  • If the load is genuinely yours (many CI jobs at once), reuse connections or space them out before raising MaxStartups.

sshd is penalising your address (OpenSSH 9.8 and later)

Occasional

PerSourcePenalties refuses an address for a period after behaviour that looks like an attack, such as repeated failed logins. Your own scripts or a misconfigured client can trigger it.

Confirm

sudo journalctl -t sshd --since '-1h' | grep -i penalt

Lines about a penalty for your address

Fix

  • Stop whatever is failing repeatedly (a wrong key in a loop, a monitoring check), then wait for the penalty to expire.
  • On a trusted network you can exempt addresses with PerSourcePenaltyExemptList in sshd_config.

The port is not running SSH

Occasional

A web server, a load balancer or another service on that port answers in its own protocol and hangs up.

Confirm

ssh -v -p PORT HOST 2>&1 | grep 'banner line'

Banner lines that are not SSH, such as HTTP/1.1 400 Bad Request

Fix

  • Use the port SSH really listens on (ssh -p PORT), or point the load balancer at sshd.

A firewall, intrusion-prevention system or tool such as fail2ban cut the connection

Occasional

Something between you and sshd resets or closes connections from your address. The sshd log then shows nothing for your attempt, because the connection never reached it.

Confirm

sudo journalctl -t sshd --since '-10min'

No line at all for your connection attempt

Fix

  • Check the firewall or fail2ban for a block on your address and remove it; then fix whatever triggered it.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Every SSH session starts with both sides sending a short greeting line. This error means the server hung up before that, so no key or password was ever checked. Something on the server side, or in between, decided not to talk to you yet. Run ssh -v: the lines it prints just before the error usually say which.

Words used on this page

Identification exchange
The first step of SSH: each side sends a version line such as SSH-2.0-OpenSSH_9.6. kex is short for key exchange, which follows it.
MaxStartups
An sshd setting that limits how many connections may wait for login at once; extra ones are dropped.
PerSourcePenalties
From OpenSSH 9.8, sshd temporarily refuses an address that behaved like an attack, for example many failed logins.
What is actually happening

Reproduced on OpenSSH 10.3p1 with a test server limited to one waiting login (MaxStartups 1). With that slot taken, ssh printed only "Connection closed by 127.0.0.1 port 22997". ssh -v showed the reason: "banner line 0: Not allowed at this time", then "kex_exchange_identification: Connection closed by remote host". The server's log said "drop connection #1 from [127.0.0.1]:N on [127.0.0.1]:22997 Maxstartups". Once the slot freed, ssh got through to authentication.

A listener that resets connections gave "kex_exchange_identification: read: Connection reset by peer". A port answering HTTP instead of SSH showed, under -v, "banner line 0: HTTP/1.1 400 Bad Request": proof that something other than sshd answered.

Newer clients print less without -v: OpenSSH 9.6p1 on Ubuntu 24.04, pointed at a web server on port 80, printed only "Connection closed by 127.0.0.1 port 80".

How to tell this is your problem
WhereWhat you see
sshkex_exchange_identification: Connection closed by remote host, or just Connection closed by IP port 22
sshkex_exchange_identification: read: Connection reset by peer
ssh -vbanner line 0: Not allowed at this time (sshd is refusing new connections)
Server's sshd logdrop connection #N from [IP]:PORT on [IP]:22 past MaxStartups

How to know it is actually fixed

  • ssh reaches the authentication step (a password prompt, key acceptance or Permission denied) instead of closing.

Stopping it happening again

  • Do not leave port 22 open to the whole internet; allow known addresses or use a bastion or VPN.
  • Reuse SSH connections in automation (ControlMaster) instead of opening many at once.

Security considerations

  • Repeated drops from many addresses can mean the server is being scanned or attacked. Raising MaxStartups or disabling penalties to make the error go away also helps an attacker.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it