"kex_exchange_identification: read: Connection reset by peer"

The TCP connection opened, but something ended it before the SSH greeting, so this happens before any key or password is checked. The server is usually refusing you on purpose: sshd penalties after failed logins, too many unauthenticated connections (MaxStartups), or /etc/hosts.deny. A firewall or a broken tunnel in the middle can do the same. Run ssh -v, and read the server's log for the matching line.

Updated . The penalty, MaxStartups, hosts.deny and firewall reset cases were reproduced on Debian 13 with OpenSSH 10.0 on both sides.

The forms of this message

kex_exchange_identification: read: Connection reset by peer
Connection reset by 203.0.113.10 port 22
kex_exchange_identification: Connection closed by remote host
Connection closed by 203.0.113.10 port 22

Recent clients may print only the last line, Connection closed by 203.0.113.10 port 22, unless you add -v. Reset and closed differ only in how the connection ended. Treat them as the same problem, because the same cause can show either one depending on what sits in between.

Start here

ssh -v user@server true

This line in the output is a very useful clue:

debug1: kex_exchange_identification: banner line 0: Not allowed at this time

That text comes from sshd itself. It means the server is up and is dropping you on purpose, so go to cause 1 and cause 2. To read the reason, use a console or another connection on the server:

sudo journalctl -u ssh -u sshd --since "1 hour ago" | grep -iE 'maxstartups|penalty'

If you are locked out, also try from another network, such as a phone hotspot. If that works, the block is tied to your address.

Cause 1: sshd penalties

Since OpenSSH 9.8, sshd penalizes addresses that fail to log in, and this is on by default. While the penalty lasts, new connections from that address are dropped. The server log shows:

drop connection #0 from [203.0.113.10]:41056 on [203.0.113.20]:22 penalty: failed authentication

Waiting is enough: the default maximum is 10 minutes. It is more likely to hit you behind a shared office address, or with a script or monitoring job that keeps failing, so fix what is failing first. For a trusted address, add this to sshd_config:

PerSourcePenaltyExemptList 203.0.113.10

A client that offers many keys can fail several times in one login. See Too many authentication failures to limit it to the right key.

Cause 2: MaxStartups

MaxStartups limits connections that have not logged in yet. The default is 10:30:100: from 10 such connections on, sshd drops new ones at random with a 30% chance, rising until all are dropped at 100. Bots scanning a public server can fill this. The log shows:

drop connection #1 from [203.0.113.10]:37954 on [203.0.113.20]:22 Maxstartups

Older versions log exceeded MaxStartups. Check the setting and the current connections:

sudo sshd -T | grep -iE '^(maxstartups|persourcemaxstartups|logingracetime)'
ss -tn state established '( sport = :22 )'

The failure is often intermittent: a retry works. To make room, raise the limit, and shrink the bot traffic with a firewall allow list or a shorter LoginGraceTime:

MaxStartups 30:30:100

Validate and apply it. The service is ssh on Debian and Ubuntu and sshd on Red Hat style systems:

sudo sshd -t && sudo systemctl reload ssh

Cause 3: TCP wrappers

OpenSSH upstream dropped this feature long ago, but some distributions still build it in. Debian 13 does, and a sshd: ALL line in /etc/hosts.deny produced the reset message in our test. Since OpenSSH 9.8 the library is linked to sshd-session, not to sshd, so check both:

ldd /usr/sbin/sshd /usr/lib/openssh/sshd-session 2>/dev/null | grep libwrap
grep -v '^#' /etc/hosts.deny /etc/hosts.allow

Remove the rule, or allow your address in /etc/hosts.allow:

sshd: 203.0.113.10

Cause 4: a firewall or fail2ban

A firewall, a load balancer or an intrusion prevention device that sends a TCP reset after the connection opens gives this family of messages. We reproduced it with this rule, where SSH printed Connection reset by peer:

iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate ESTABLISHED -j REJECT --reject-with tcp-reset

fail2ban is a less likely cause of this message than people assume. Its default actions reject new connections, which the client reports as Connection refused, not as a reset. It is still worth a look if you failed several logins:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10

See fail2ban for SSH for more.

Cause 5: a tunnel with a dead end

If you connect through a tunnel or port forward, the first hop accepts your connection and then fails to reach the real target. The client sees the reset. With ssh -L, the terminal running the tunnel shows the true reason:

channel 3: open failed: connect failed: Connection refused

Look there, or at your proxy's log. Check that the target address and port are right, and that sshd is running on the target.

Cause 6: sshd itself has a problem

When the cases above do not fit, test the configuration and run a debug copy on a spare port. Your normal service keeps running:

sudo sshd -t
sudo /usr/sbin/sshd -d -p 2200

Then connect with ssh -p 2200 user@server and read what the debug copy prints. Allow that port in your firewall first, and close it afterwards.

Questions

What does kex_exchange_identification: Connection reset by peer mean?

The TCP connection opened but was cut before the SSH greeting. The server, or something in between, turned you away before any key or password was checked.

How long does an sshd penalty last?

Since OpenSSH 9.8 penalties grow with repeated failures, up to 10 minutes by default. Waiting clears it, and PerSourcePenaltyExemptList exempts trusted addresses.

Why does the reset happen only sometimes?

An intermittent reset often points to MaxStartups: when too many connections are still logging in, sshd drops new ones at random.

Sources

More in Error messages

All guides