SSH – Fix kex_exchange_identification Error with Windows 10 OpenSSH Server

sshwindows 10

I installed OpenSSH-server on my Windows 10 PC (probably a "home" version, not a Windows server) using the Microsoft guide. I did not change the C:/Windows/System32/OpenSSH/sshd_config_default file (although I don't think that's relevant here anyway). I can log to the machine from a terminal on that same machine:

localhost SSH

I have another machine running on the same LAN (both wired to the same SoHo router). From it, trying to connect to Windows 10 fails wtih:

kex_exchange_identification: Connection closed by remote host
Connection closed by 10.0.3.130 port 22

According to this answer to another similar thread, this error happens when the server closes the TCP connection during the cryptographic exchange, or something like that. So I've looked at Windows' firewall, but there is an enabled inbound rule for TCP port 22 (and, besides, if it had beed a missing rule issue, the SSH client would just timeout, not have an error in kex_exchange_identification):

firewall

So I've tried running Wireshark on the server (10.0.3.130). It appears the server accepts the TCP handshake, then the other machine (10.0.3.10) sends some protocol SSH packet, and then the server just closes the connection:

Wireshark OpenSSH started

To see what would happen, I went to Windows' Services app and stopped the OpenSSH SSH Server service, then tried the same thing, but the result with Wireshark is the same:

Wireshark OpenSSH stopped

The one thing I've noticed, and that I don't quite understand, is that running netstat -ab in an administrator PowerShell shows that port 22 has an active listener on it, even when OpenSSH is stopped (just Windows things I guess…):

netstat command

So, yeah… I'm stomped at this point. Any ideas?

Best Answer

TL;DR: After a little more searching, and trying to reboot like others suggested, I've found a simple workaround:

  1. Make Windows start the OpenSSH server on a port that netstat -ab does not show as taken by adding the line Port portNumber into %programdata%\ssh\sshd_config [*] (replacing portNumber by the chosen port of course). I personally chose port 222, since it's easy to remember.
  2. Add the inbound rule for TCP port portNumber in the Windows Defender Firewall with Advanced Security.

What I think was wrong is what I showed last: that last image seems to show that, in my case, port 22 (which OpenSSH-server is usually on) was already occupied by another, unrelated, server (for... whatever reason). So the SSH client was doing the TCP handshake, which that unrelated server was accepting, and then the client sent an OpenSSH protocol packet (which the unrelated server doesn't understand), which caused this unrelated server to simply close the TCP connection.

Now, it is true that I was able to connect to the ssh server on port 22 from the server itself. I think this is because connecting to localhost sends the packets to the loopback interface, which that unrelated server probably wasn't listening on.

So the logical workaround is to simply move the OpenSSH server to another port that isn't used, and then adding the inbound rule to that new port in the Windows firewall. However, a true solution would be to find what that unrelated server listening on port 22 in, and then either killing it or moving it to a different port.

[*]: Unlike what I thought, the OpenSSH configuration file is not C:/Windows/System32/OpenSSH/sshd_config_default ; it's actually %programdata%\ssh\sshd_config according to this guide from Microsoft. So C:/Windows/System32/OpenSSH/sshd_config_default seems, like its name indicates, to be there only to show what the OpenSSH server configuration is when we don't change any configuration in %programdata%\ssh\sshd_config, or when that file doesn't exist.

Related Topic