0 votes
by (140 points)

I have an SFTP server running in the wild and I keep getting random connections from other countries. This is absolutely expected, but I would like to be able to detect this issue and reject connections from these IPs. The problem is that I don't know where to catch this exception and record the IP. I have tried placing a try catch around code in my Authentication Event Handler, but the error isn't being thrown there.

Session 273: Error: Rebex.Net.Protocols.Ssh.ZSC: Error while processing packet V. Key exchange failed. ---> Rebex.Net.Protocols.Ssh.ZSC: Key exchange failed. ---> System.Security.Cryptography.CryptographicException: Key not valid for use in specified state.

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils._ExportKey(SafeKeyHandle hKey, Int32 blobType, Object cspObject)
   at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
   at Rebex.Security.Cryptography.CryptoHelper.WS(RSA T, Byte[] U, String D, Boolean C, RD M)
   at Rebex.Security.Cryptography.CryptoHelper.YS(RSA T, Byte[] U, String D, Boolean C, RD M)
   at Rebex.Security.Cryptography.AsymmetricKeyAlgorithm.SignHash(Byte[] hash, SignatureHashAlgorithm hashAlgorithm)
   at Rebex.Net.SshPrivateKey.N(Byte[] T, Boolean U, SignatureHashAlgorithm D)
   at Rebex.Net.SshPrivateKey.CreateSignature(Byte[] hash, SignatureHashAlgorithm algorithm)
   at Rebex.Net.Protocols.Ssh.ZHD.OS(ETC T, XPD U)
   at Rebex.Net.Protocols.Ssh.YHD.JS(ETC T, XPD U)
   --- End of inner exception stack trace ---
   at Rebex.Net.Protocols.Ssh.YHD.JS(ETC T, XPD U)
   at Rebex.Net.Protocols.Ssh.MSC.DC(Int32 T, Int32 U)
   --- End of inner exception stack trace ---
   at Rebex.Net.Protocols.Ssh.MSC.DC(Int32 T, Int32 U)
   at Rebex.Net.Protocols.Ssh.MSC.DC()
   at Rebex.Net.Protocols.Ssh.MSC.HD(Int32 T, Int32 U, Int32 D, Int32 C, SocketException M)

Can you explain what this error means, and perhaps tell me where I could catch it and have access to the client IP? I only have access to the exception and session id in the ErrorOccurred Handler.

1 Answer

0 votes
by (148k points)

You actually ask two different questions:

1) How to reject connections based on their IP address?

Fortunately, this is very simple - use FileServer.Connecting event:

server.Connecting += (sender, e) =>
{
    // only accept sessions from clients within 192.168.1.* network
    if (e.ClientAddress.ToString().StartsWith("192.168.1."))
        e.Accept = true;
    else
        e.Accept = false;
};

Setting Accept to false will reject clients before they even attempt SSH negotiation.


2) What does the error mean?

The "Key exchange failed" error occurred because it was not possible to use the server RSA key to sign a hash during SSH session negotiation.

The actual cause of this was the "Key not valid for use in specified state" error thrown by .NET's RSACryptoServiceProvider object. This error usually indicates that something is wrong with the RSA key or key storage - see Microsoft Forum for suggested solutions.

How often does this occur? This doesn't seem to be related to different clients - if the RSA key is unusable, I would expect this to fail for all clients attempting RSA-based host key negotiation. Are you actually able to connect to this server yourself?

However, what's definitely worth mentioning is that RSACryptoServiceProvider.ExportParameters method has been called by the AsymmetricKeyAlgorithm.SignHash method - this indicates that RSACryptoServiceProvider.SignHash was attempted first and it failed. As a workaround of the last resort, AsymmetricKeyAlgorithm.SignHash tried to export the key in order to retry the signing operation using RSAManaged class - but this truned out to be impossible because RSACryptoServiceProvider.ExportParameters method failed as well.

by (140 points)
edited by
Ok you're right. It isn't working for any connections. That's because I just updated the binaries to BetaBuild6037 from BetaBuild6010. Once I reverted, everything started working again. Is there a new BetaBuild that will work?
by (148k points)
Thanks for letting us know - this was actually caused by a bug (RSACryptoServiceProvider.SignHash was not called even when it should have been). I sent a link to the current beta build to your e-mail. Please download it and give it a try. Sorry for inconvenience!
by (148k points)
We have released Rebex File Server 2016 R2.1 that fixes this issue. See http://www.rebex.net/file-server/history.aspx#2016R2.1 for details.
...