Unable to connect to a server using 2024.2.0: Key exchange negotiation failed
Unable to connect to a server when using SSH.NET 2024.2.0 and base64-encoded ed25519 private key. Version 2024.1.0 works fine.
This is the exception I'm getting:
Renci.SshNet.Common.SshConnectionException: Key exchange negotiation failed.
at Renci.SshNet.Security.KeyExchange.Finish()
at Renci.SshNet.Security.KeyExchangeECCurve25519.Finish()
at Renci.SshNet.Security.KeyExchangeECCurve25519.Session_KeyExchangeEcdhReplyMessageReceived(Object sender, MessageEventArgs`1 e)
at Renci.SshNet.Session.OnKeyExchangeEcdhReplyMessageReceived(KeyExchangeEcdhReplyMessage message)
at Renci.SshNet.Messages.Transport.KeyExchangeEcdhReplyMessage.Process(Session session)
at Renci.SshNet.Session.MessageListener()
--- End of stack trace from previous location ---
at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle)
at Renci.SshNet.Session.Connect()
at Renci.SshNet.BaseClient.CreateAndConnectSession()
at Renci.SshNet.BaseClient.Connect()
at FSI_0002.main(String host, String user, String dir) in /home/vmadmin/temp/print-sftp-files.fsx:line 22
at <StartupCode$FSI_0002>.$FSI_0002.main@() in /home/vmadmin/temp/print-sftp-files.fsx:line 30
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Stopped due to error
Here's my code:
#r "nuget: SSH.NET, 2024.2.0"
open Renci.SshNet
open System
open System.IO
let getAuthMethod (user : string) : AuthenticationMethod =
let key = Environment.GetEnvironmentVariable "SSH_KEY"
let pwd = Environment.GetEnvironmentVariable "SSH_PWD"
if not (String.IsNullOrEmpty key) then
new PrivateKeyAuthenticationMethod(user, new PrivateKeyFile(new MemoryStream(Convert.FromBase64String key)))
else if not (String.IsNullOrEmpty pwd) then
new PasswordAuthenticationMethod(user, pwd)
else
failwith "Environment variable SSH_PWD or SSH_KEY must be defined"
let main host user (dir: string) =
let auth = getAuthMethod user
use client = new SftpClient(new ConnectionInfo(host, user, auth))
client.Connect()
let res = client.ListDirectory dir
for item in res do
printfn "%s" item.FullName
match fsi.CommandLineArgs |> List.ofArray with
| [ _; host; user; dir ] -> main host user dir
| _ -> printfn "Usage: dotnet fsi %s <host> <user> <dir>" fsi.CommandLineArgs.[0]
The error is happening at the initial handshake i.e. before authentication. There were some changes in 2024.2.0 related to Curve25519 key exchange. Can you get a packet capture, or is this server publicly accessible?
Can you get a packet capture
I don't know how to do that :(
or is this server publicly accessible?
It is, kind of, but I don't want to advertise it publicly. Can I send you a private message somehow?
The server version is OpenSSH_9.9p2, OpenSSL 3.3.3 11 Feb 2025
You can drop me a mail at the address in this commit message: https://github.com/sshnet/SSH.NET/commit/7a599e21c467c3366ba50f4d5f167b868d7123bf
The problem was the server sending a host certificate (since 2024.2.0 added certificate support) which had an expired validity period, which we then rejected. It seems that ssh does not check the validity period as that worked fine, so perhaps we should do the same
It seems that ssh does not check the validity period
ssh won't accept an expired certificate. It tries other host key algorithms. If the connection gets accepted by ssh I assume that is because the (non-certificate) host key is in known_hosts.
I have also encountered this error since upgrading to 2024.2.0. We connect to 100s of vendor sites though and only 1 has the issue.
It's more than likely an expired host key on the vendors SFTP server then? Are there any other possibilities with this error?
If it's always an expired host key isn't the error message a little vague?