How to fix Server unexpectedly closed network connection in SSH
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- Determine whether the drop is at setup or after idle
- Check whether your IP is banned (fail2ban / sshguard)
- Check MaxStartups (drops under load / many sessions)
- Check TCP wrappers and access rules
ssh -vvv user@hostServer 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
- 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
- No common algorithm: client and server share no key-exchange, cipher, MAC, or host-key type, so sshd closes the socket during negotiation
- Firewall or NAT device closes an established but idle TCP connection after 5-30 minutes (idle-timeout variant)
- Missing keepalive settings let an idle session lapse before either side notices (idle-timeout variant)
- Server resource exhaustion: sshd runs out of memory or file descriptors and terminates connections
- Network instability: intermittent packet loss or routing changes drop the connection
- Account restrictions: invalid shell, expired password, or disabled account causing the server to close the session
How to fix "Server unexpectedly closed network connection"
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):
ssh -vvv user@hostKey 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:
sudo tail -f /var/log/auth.log | grep sshd # Debian/Ubuntu
sudo journalctl -u ssh -f # systemd journalRepeated failed logins are the most common reason a server drops you at setup. On the server:
# 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):
sudo nft list set inet sshguard attackers 2>/dev/nullAlso confirm you are not blocked at the firewall:
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).
If the failure correlates with many simultaneous connections, sshd may be shedding unauthenticated sessions. On the server:
sudo grep -i maxstartups /etc/ssh/sshd_configThe 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:
# in /etc/ssh/sshd_config
MaxStartups 100:30:500Validate and reload:
sudo sshd -t && sudo systemctl reload sshdReducing repeated reconnect storms from clients (e.g. broken automation retry loops) also helps.
The server may be refusing your IP or user by policy, which looks like an unexpected close. On the server, inspect access controls:
# 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_configIf a hosts.deny rule like sshd: ALL or a DenyUsers/AllowUsers line excludes you, adjust it to permit your source address or account, then:
sudo sshd -t && sudo systemctl reload sshdPrefer narrowing an AllowUsers/hosts.allow entry to your specific address over opening access broadly.
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:
ssh -vvv user@host 2>&1 | grep -i 'no matching'List what each side offers:
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:
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-rsaRemove these overrides once the server is updated. Avoid globally lowering your client's algorithms with Host *.
If Step 1 showed an established session dropping after idle time, keepalives usually fix it. Add to ~/.ssh/config:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3Or per-connection:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@hostThis 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.
If you administer the server and idle sessions are being dropped, set client-alive options in /etc/ssh/sshd_config:
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yesClientAliveInterval makes sshd probe an idle client every 60s; ClientAliveCountMax allows 3 missed replies before disconnecting. Validate and reload:
sudo sshd -t && sudo systemctl reload sshdIf 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.