How to fix Server unexpectedly closed network connection in SSH

SSHINTERMEDIATEMEDIUMUpdated Sep 4, 2026· 885 views

PuTTY's "Server unexpectedly closed network connection" most often means sshd dropped you at connection setup (fail2ban ban, MaxStartups, TCP wrappers, cipher/kex mismatch); idle timeouts are a less common cause.

Quick fix

Fixes Server unexpectedly closed network connection

ssh -vvv user@host
  1. Determine whether the drop is at setup or after idle
  2. Check whether your IP is banned (fail2ban / sshguard)
  3. Check MaxStartups (drops under load / many sessions)
  4. Check TCP wrappers and access rules
ssh — error
ssh -vvv user@host
Server unexpectedly closed network connection

What this error means

This message comes from PuTTY (and PuTTY-derived clients like WinSCP) and means the TCP connection to the SSH server was closed by the remote end without a clean SSH protocol disconnect. Despite the word "unexpectedly," the most common trigger is the server deliberately dropping the connection during setup — before or during the key exchange and authentication handshake. Intrusion-prevention tools such as fail2ban or sshguard ban your IP, the daemon's MaxStartups limit sheds unauthenticated connections under load, TCP wrappers (hosts.deny/hosts.allow) refuse you, or the client and server share no common key-exchange, cipher, or host-key algorithm and sshd closes the socket. A separate, less common scenario produces the same words: an already-established session is torn down after a period of inactivity. Here a firewall/NAT device times out the idle TCP flow, or the server's idle/keepalive settings expire the session while no traffic flows. Because the same message covers both a handshake-time rejection and an idle-time drop, the first job is to determine which one you are seeing — a fix for one (for example keepalives) does nothing for the other.

Typical symptoms

  • Connection fails immediately on connect, before or right after entering credentials (handshake-time variant)
  • PuTTY/WinSCP shows the dialog 'Server unexpectedly closed network connection'
  • Connecting works from one network or IP but is refused from another (suggests an IP ban or TCP-wrapper rule)
  • Fails only under load or when many sessions start at once (MaxStartups shedding)
  • Server auth.log shows 'Connection closed by ... [preauth]', 'Unable to negotiate', or fail2ban ban entries
  • A separate pattern: session works initially but drops after 5-30 minutes idle (idle/firewall timeout variant)
  • More frequent on public or corporate networks behind aggressive NAT/firewalls (idle variant)

Common causes

  1. IP banned by fail2ban/sshguard after repeated failed logins, so the daemon drops the connection at setup
  2. MaxStartups limit reached: sshd sheds new unauthenticated connections under load or many simultaneous logins
  3. TCP wrappers / host-based rules (hosts.deny, hosts.allow, AllowUsers/DenyUsers, Match blocks) refusing the source IP or user
  4. No common algorithm: client and server share no key-exchange, cipher, MAC, or host-key type, so sshd closes the socket during negotiation
  5. Firewall or NAT device closes an established but idle TCP connection after 5-30 minutes (idle-timeout variant)
  6. Missing keepalive settings let an idle session lapse before either side notices (idle-timeout variant)
  7. Server resource exhaustion: sshd runs out of memory or file descriptors and terminates connections
  8. Network instability: intermittent packet loss or routing changes drop the connection
  9. Account restrictions: invalid shell, expired password, or disabled account causing the server to close the session

How to fix "Server unexpectedly closed network connection"

1Determine whether the drop is at setup or after idle

This message has two very different causes, and fixing the wrong one wastes time. First classify the failure.

- Does it fail immediately on connect (before or just after the password/key prompt)? That is a handshake-time drop — go to Steps 2-5.
- Does an established session drop only after sitting idle (minutes)? That is an idle-timeout drop — go to Steps 6-7.

Reproduce with a verbose OpenSSH client (even on Windows; PuTTY itself shows little detail):

bash
ssh -vvv user@host

Key signals:
- Connection closed by <ip> port 22 very early, or right after expecting SSH2_MSG_KEX... = setup-time rejection (ban, MaxStartups, TCP wrappers).
- Unable to negotiate with <ip>: no matching key exchange method (or cipher/host key) = algorithm mismatch.
- A session that stays up under -vvv until you stop typing, then drops = idle timeout.

If you control the server, watch its log live while you connect:

bash
sudo tail -f /var/log/auth.log | grep sshd   # Debian/Ubuntu
sudo journalctl -u ssh -f                     # systemd journal
2Check whether your IP is banned (fail2ban / sshguard)

Repeated failed logins are the most common reason a server drops you at setup. On the server:

bash
# fail2ban: list jails, then list banned IPs for the sshd jail
sudo fail2ban-client status
sudo fail2ban-client status sshd

# Unban your address if listed
sudo fail2ban-client set sshd unbanip <your_ip>

If sshguard is used instead, banned addresses live in its backend (often nftables/ipset):

bash
sudo nft list set inet sshguard attackers 2>/dev/null

Also confirm you are not blocked at the firewall:

bash
sudo iptables -L -n | grep <your_ip>

To stop getting banned, fix the underlying auth failures (wrong key, wrong username) rather than disabling the protection. If you must connect during a ban, do so from a different IP or whitelist your address in jail.local (ignoreip).

3Check MaxStartups (drops under load / many sessions)

If the failure correlates with many simultaneous connections, sshd may be shedding unauthenticated sessions. On the server:

bash
sudo grep -i maxstartups /etc/ssh/sshd_config

The value is start:rate:full. The OpenSSH default 10:30:100 means: begin randomly dropping new unauthenticated connections at 10 in-flight (30% chance, rising linearly) and reject all once 100 are pending. For high-concurrency hosts (CI, bastions), raise it:

bash
# in /etc/ssh/sshd_config
MaxStartups 100:30:500

Validate and reload:

bash
sudo sshd -t && sudo systemctl reload sshd

Reducing repeated reconnect storms from clients (e.g. broken automation retry loops) also helps.

4Check TCP wrappers and access rules

The server may be refusing your IP or user by policy, which looks like an unexpected close. On the server, inspect access controls:

bash
# TCP wrappers (still honored if sshd is built with libwrap)
sudo cat /etc/hosts.deny
sudo cat /etc/hosts.allow

# sshd access directives
sudo grep -Ei 'AllowUsers|DenyUsers|AllowGroups|DenyGroups|^Match' /etc/ssh/sshd_config

If a hosts.deny rule like sshd: ALL or a DenyUsers/AllowUsers line excludes you, adjust it to permit your source address or account, then:

bash
sudo sshd -t && sudo systemctl reload sshd

Prefer narrowing an AllowUsers/hosts.allow entry to your specific address over opening access broadly.

5Resolve key-exchange, cipher, or host-key mismatches

Connecting from a modern client to a very old server (or vice versa) can leave no common algorithm, and sshd closes the socket. The OpenSSH client makes this explicit:

bash
ssh -vvv user@host 2>&1 | grep -i 'no matching'

List what each side offers:

bash
ssh -Q kex; ssh -Q cipher; ssh -Q key      # client capabilities
sudo sshd -T | grep -Ei 'kexalgorithms|ciphers|hostkeyalgorithms'   # server (run on server)

The correct long-term fix is to upgrade the older side so both support modern algorithms. If you must reach a legacy host temporarily, you can re-enable a specific legacy algorithm for that host only in ~/.ssh/config, understanding it weakens that connection's security:

sshconfig
Host legacy-box
    HostName host
    # Last resort: only for an old server you cannot upgrade yet.
    KexAlgorithms +diffie-hellman-group14-sha1
    HostKeyAlgorithms +ssh-rsa
    PubkeyAcceptedAlgorithms +ssh-rsa

Remove these overrides once the server is updated. Avoid globally lowering your client's algorithms with Host *.

6Enable client-side keepalive (idle-timeout variant)

If Step 1 showed an established session dropping after idle time, keepalives usually fix it. Add to ~/.ssh/config:

sshconfig
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

Or per-connection:

bash
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@host

This sends an encrypted keepalive every 60 seconds and tolerates 3 unanswered replies (~180s) before giving up. Behind an aggressive firewall/NAT, shorten the interval (e.g. 30) so it stays under the device's idle timeout. In PuTTY, the equivalent is Connection > 'Seconds between keepalives' (set to 30-60). Note: keepalives do nothing for the setup-time drops in Steps 2-5.

7Tune server-side idle/keepalive (idle-timeout variant)

If you administer the server and idle sessions are being dropped, set client-alive options in /etc/ssh/sshd_config:

sshconfig
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes

ClientAliveInterval makes sshd probe an idle client every 60s; ClientAliveCountMax allows 3 missed replies before disconnecting. Validate and reload:

bash
sudo sshd -t && sudo systemctl reload sshd

If the timeout is actually imposed by an intermediate firewall/NAT rather than sshd, server keepalive plus the client ServerAliveInterval from Step 6 keeps the flow active so the device does not reap it.

Advanced notes

Two keepalive layers: TCPKeepAlive operates at the OS socket level (probes can be spoofed/dropped by middleboxes), while ClientAliveInterval/ServerAliveInterval send encrypted SSH-protocol probes. For idle-timeout problems, prefer the application-level options; enable both for maximum compatibility.

Reading the log line: Connection closed by authenticating user ... [preauth] indicates the failure happened before authentication completed — consistent with the setup-time causes (ban, MaxStartups, TCP wrappers, mismatch) rather than an idle drop.

Legacy-algorithm caveat: Re-enabling diffie-hellman-group14-sha1 or ssh-rsa (SHA-1) is a temporary bridge for un-upgradable hosts only, and should be scoped to a single Host block, never Host *. SHA-1 host-key signatures and small DH groups are deprecated; upgrade the server and remove the override.

Cloud bastions and load balancers: AWS NLB/ELB, GCP, and Azure idle timeouts (often 5-20 minutes, and some are non-configurable) cause the idle-timeout variant on otherwise healthy connections; set ServerAliveInterval below the balancer's timeout.

Long-running commands: For jobs that produce no output for long stretches, run them inside tmux/screen so a dropped client connection does not kill the work, and reattach after reconnecting.

Frequently asked questions

What does "Server unexpectedly closed network connection" mean?
This message comes from PuTTY (and PuTTY-derived clients like WinSCP) and means the TCP connection to the SSH server was closed by the remote end without a clean SSH protocol disconnect. Despite the word "unexpectedly," the most common trigger is the server deliberately dropping the connection during setup — before or during the key exchange and authentication handshake. allow) refuse you, or the client and server share no common key-exchange, cipher, or host-key algorithm and sshd closes the socket.
How do I fix "Server unexpectedly closed network connection"?
PuTTY's "Server unexpectedly closed network connection" most often means sshd dropped you at connection setup (fail2ban ban, MaxStartups, TCP wrappers, cipher/kex mismatch); idle timeouts are a less common cause.
What causes "Server unexpectedly closed network connection"?
IP banned by fail2ban/sshguard after repeated failed logins, so the daemon drops the connection at setup MaxStartups limit reached: sshd sheds new unauthenticated connections under load or many simultaneous logins TCP wrappers / host-based rules (hosts.deny, hosts.allow, AllowUsers/DenyUsers, Match blocks) refusing the source IP or user
Is the "Server unexpectedly closed network connection" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading