SSH fails during the key-exchange identification handshake because the server closes the TCP connection before negotiation finishes. It's a connectivity or server-side issue (fail2ban, MaxStartups, firewall), not authentication.
An SSH connection happens in phases. The very first phase is the protocol/version identification and key exchange (KEX) banner exchange, where the client and server announce themselves and begin negotiating encryption. The `kex_exchange_identification: Connection closed by remote host` error means the server (or something in front of it) dropped the TCP connection before it ever sent its identification string. Because this happens before any algorithm negotiation, key verification, or authentication, it is almost always a connectivity or server-side gatekeeping problem rather than a credential problem. The most common culprits are intrusion-prevention tools that banned your IP (fail2ban, DenyHosts), the SSH daemon refusing new connections because it hit its `MaxStartups` limit, TCP wrappers (`/etc/hosts.deny`), or a firewall/middlebox resetting the connection.
On the server, the most common cause is that an intrusion-prevention tool banned your IP. Check for it:
# Check fail2ban status for the sshd jail (lists currently banned IPs)
sudo fail2ban-client status sshd
# Check TCP wrappers
sudo cat /etc/hosts.deny
sudo cat /etc/hosts.allow
# Check iptables/nftables for drop rules on the SSH port
sudo iptables -L -n | grep -E 'ssh|:22'
sudo nft list ruleset 2>/dev/null | grep -E 'ssh|22'If your IP is banned by fail2ban, unban it (replace <your-ip> with your actual address):
sudo fail2ban-client set sshd unbanip <your-ip>On your client machine, use maximum verbosity to confirm the failure happens at identification, before any banner is received:
ssh -vvv user@hostnameLook for the last successful step. With this error you will typically see the TCP connection established, then it closes before a line like debug1: Remote protocol version ... appears. That confirms the server closed the connection before sending its SSH banner, pointing to a server-side gate (ban, MaxStartups, wrapper) rather than authentication.
On the server, inspect the SSH daemon logs to see why it closed the connection:
# systemd-based systems
sudo journalctl -u ssh -u sshd -n 50 --no-pager
# syslog-based systems (Debian/Ubuntu vs RHEL/CentOS)
sudo tail -n 50 /var/log/auth.log
sudo tail -n 50 /var/log/secureLook for messages such as:
- error: beginning MaxStartups throttling / drop connection #N
- refused connect from (TCP wrappers)
- Unable to load host key
- fatal: ... too many connections
These point directly at the cause.
On the server, make sure the daemon is actually running and that no broken config is causing it to reject or crash on connections:
# Check if sshd is running
sudo systemctl status ssh sshd
# Validate the configuration WITHOUT restarting
sudo sshd -t
# If config is valid and a restart is warranted, reload/restart
sudo systemctl restart ssh sshdThe -t flag tests the configuration and prints any syntax errors. Fix reported errors before restarting, otherwise sshd may fail to come back up.
If the logs show MaxStartups throttling, the daemon is dropping new unauthenticated connections because too many are pending. On the server, review the setting:
sudo grep -i maxstartups /etc/ssh/sshd_configThe default is 10:30:100 (start randomly dropping at 10 pending connections, 30% drop rate, hard cap at 100). If you have legitimate high concurrency, raise it:
# Example: start throttling at 50, hard cap at 200
MaxStartups 50:30:200Then validate and restart:
sudo sshd -t
sudo systemctl restart ssh sshdNote: raising MaxStartups increases exposure during a brute-force attack, so prefer fixing the underlying load or ban source where possible.
If the logs show Unable to load host key, sshd may close connections because it cannot present a host key. On the server:
# Inspect host keys
sudo ls -la /etc/ssh/ssh_host_*
# Expected permissions:
# Private keys: 600 (-rw-------)
# Public keys: 644 (-rw-r--r--)
# Fix permissions if needed
sudo chmod 600 /etc/ssh/ssh_host_*_key
sudo chmod 644 /etc/ssh/ssh_host_*_key.pubIf host keys are missing or corrupted, regenerate them and restart:
sudo ssh-keygen -A
sudo systemctl restart ssh sshdIf the server side looks healthy, confirm the connection isn't being reset or fragmented in transit. From the client:
# Confirm the TCP port is reachable at all
nc -vz hostname 22
# Trace the path and watch for fragmentation / black holes (MTU issues)
sudo tracepath -m 100 hostname
# Try forcing a smaller MTU on the client interface as a test (replace eth0 / value)
# A successful connection after lowering MTU points to a path-MTU problem.
sudo ip link set dev eth0 mtu 1400If nc cannot reach port 22, a firewall or network device is blocking or resetting the connection. If lowering the MTU lets the handshake complete, the path has an MTU/fragmentation issue that should be fixed on the network (enable Path MTU Discovery or correct the offending device). Revert any temporary MTU change once diagnosed.
Many of the server-side causes (fail2ban bans, brute-force throttling) are temporary. If you cannot immediately access the server to unban your IP:
# Wait for the ban window to expire, then retry
ssh user@hostname
# If you have out-of-band access, whitelist your IP in fail2ban so it is never banned
sudo fail2ban-client set sshd addignoreip <your-ip>
# Or persist it in /etc/fail2ban/jail.local under [DEFAULT]:
# ignoreip = 127.0.0.1/8 <your-ip>Whitelisting your own management IP avoids future lockouts without weakening protection against other sources.
The kex_exchange_identification error occurs at the very start of the SSH protocol handshake, before any algorithm negotiation or authentication. This is what distinguishes it from Unable to negotiate ... no matching key exchange method (a true KEX algorithm mismatch, which happens *after* both sides exchange banners) and from authentication failures like Permission denied (publickey). If you only ever see this error before the server's version banner, the problem is connectivity or server-side gatekeeping, not crypto algorithms or credentials.
Server-side library updates: After glibc or OpenSSL upgrades, sshd may keep running against old, partially-unmapped libraries until it is restarted, which can cause it to close connections. Restart sshd after system library updates (sudo systemctl restart ssh sshd).
Brute-force defense interplay: Under a brute-force attack, both MaxStartups throttling and fail2ban bans can reject legitimate connections. Inspect logs for attack patterns, whitelist your management IP, and consider rate-limiting at the firewall (e.g. iptables/nftables connection-rate rules) rather than just raising MaxStartups.
MTU/black-hole connections: On VPNs or tunnels, ICMP being filtered breaks Path MTU Discovery, so large handshake packets are silently dropped. Lowering the client MTU or enabling MSS clamping on the gateway resolves these cases.
sign_and_send_pubkey: no mutual signature supported
How to fix "sign_and_send_pubkey: no mutual signature supported" in SSH
sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation
How to fix "sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation" in SSH
Bad owner or permissions on /home/user/.ssh/config
How to fix "Bad owner or permissions on .ssh/config" in SSH
No more authentication methods to try.
How to fix "No more authentication methods to try." in SSH
Error connecting to agent: Connection refused
How to fix "Error connecting to agent: Connection refused" in SSH