Troubleshooting
Start with a Debug log (Logging and diagnostics): it shows the key exchange, the host key,
and each authentication attempt, much as ssh -vvv does. Then find the symptom below.
Connecting
ConnectFailed
The TCP connection (or a proxy, ProxyJump hop or ProxyCommand) failed before SSH started.
- Check the host name, port and firewall: does
ssh -p <port> <host>connect from the same machine? - Through a proxy: the message says what the proxy answered (a 407 means proxy credentials are needed).
- With
BindAddressorLocalEndPoint: an IPv4 bind address reaches only IPv4 destinations, and the reverse. RefuseConnection yesinssh_configrefuses on purpose.
Timeout while connecting
ConnectTimeout passed. A server that accepts TCP but does not answer the SSH version exchange (a busy sshd hitting
MaxStartups, a port that is not SSH) looks like this. Check that the port speaks SSH (nc host 22 shows SSH-2.0-...).
No common algorithms
KeyExchangeFailed: the server offers only algorithms SshSharp does not implement (CBC ciphers, SHA-1 MACs, ssh-rsa, DH group 1
or group exchange). Typical for old network equipment and very old servers. The fix is on the server: enable a modern algorithm
(any OpenSSH since 6.5 has curve25519-sha256, aes*-ctr and hmac-sha2-*). With FipsMode, a server that has only an Ed25519
host key fails the same way. See Algorithms.
The connection drops after a while
- Idle connections through NAT or firewalls get dropped: set
KeepAliveInterval(ServerAliveInterval). - Against OpenSSH for Windows, keep-alives often go unanswered and the connection ends after
KeepAliveCountMaxintervals: leave keep-alive off, or use a long interval with a generous count. ChannelTimeoutscloses idle channels by design; check the configuration'sChannelTimeout.
Host keys
HostKeyRejected: not in known_hosts
With StrictHostKeyChecking.Yes, an unknown host is refused. Add its key (compare the fingerprint first):
ssh-keyscan host >> ~/.ssh/known_hosts, or ScanHostKeysAsync, or use
AcceptNew for first contact.
HostKeyRejected: the key changed
The server presented a different key than known_hosts has. It may be a reinstalled server, or an interception. Find out which
before removing the old line (ssh-keygen -R host). UpdateHostKeys avoids this for planned rotations.
Over a stream: "There is no host name to look up in known_hosts"
A connection over your own Stream has no host name. Set SshClientOptions.HostKeyAlias.
Authentication
AuthenticationFailed
SshAuthenticationException.AllowedMethods lists what the server would accept. Compare it with what you gave:
AllowedMethods has |
But you gave | Then |
|---|---|---|
publickey only |
a password | The server takes keys only: pass PrivateKeys or use the agent. |
publickey |
keys | None of them is in the server's authorized_keys for this user, or the server's MaxAuthTries was reached first: put the right key first, or use IdentitiesOnly. |
keyboard-interactive |
a password | Normal for PAM servers; Password answers a single hidden prompt. Multiple prompts (a one-time code) need a KeyboardInteractive handler. |
publickey,keyboard-interactive after a partial success |
The server requires both (multi-factor): give both. | |
gssapi-with-mic |
Needs SshClientOptions.Gssapi and .NET 10. |
Also check the user name, and the server's log (journalctl -u ssh / /var/log/auth.log), which says why it refused.
An encrypted key file is skipped
When connecting by alias, encrypted IdentityFiles need SshConfigConnectOptions.PassphraseProvider (and are skipped in
BatchMode). The Information log names skipped identity files and why.
The agent is not used
SshAgent.FromEnvironment()returns null:SSH_AUTH_SOCKis not set, and on Windows neither the OpenSSH agent service nor Pageant is running.- On Windows, an agent pipe owned by another user is ignored on purpose.
- With
ssh_config,IdentityAgent noneorUseAgent = falseturns it off;IdentitiesOnly yeslimits it to matching keys.
Commands and sessions
A command hangs
- Its output is not being read: read both
StandardOutputandStandardError(flow control). - It waits for input: call
CloseInputAsyncto send end-of-file. - It waits for a password (
sudo): configureNOPASSWD, or use a terminal and SshExpect.
InvalidOperationException: output exceeded the limit
RunCommandAsync collects at most MaxCommandOutputBytes (128 MiB). Stream large output with StartCommandAsync.
ChannelClosed when starting a command or opening SFTP
The server refused the session: too many open sessions on this connection (MaxSessions), sessions not permitted for this user
or key, or no Subsystem sftp configured. The connection itself is still usable.
Environment variables are not set
The server accepts only the variables its AcceptEnv lists. Pass values on the command line instead (FOO=bar command).
Files
NotSupportedException from SFTP
The server lacks an OpenSSH extension the operation needs: an overwriting rename (posix-rename@openssh.com), hard links, server-side
copy. sftp.Extensions lists what it has. Or a synchronous Read/Write on an SFTP stream: use the async methods.
SCP fails on a Windows server
Remote paths are single-quoted for a POSIX shell. A Windows OpenSSH server whose default shell is cmd.exe or PowerShell reads
them differently: use SFTP, which OpenSSH for Windows provides by default.
Forwarding
Forwarded connections are refused
The server does not allow forwarding (AllowTcpForwarding no, PermitOpen, AllowStreamLocalForwarding no). For remote
forwarding to an address other than loopback, the server needs GatewayPorts.
"Address already in use"
Another process (or an earlier run) holds the local port. Use port 0 and read LocalEndPoint.Port.
Still stuck?
Open an issue on GitHub with the SshSharp version, the .NET version and OS, the
server software (client.ServerIdentification, or ssh -v output), and a Debug log. Logs contain no passwords, keys, user
names or host names, but check them before posting. Report security problems privately, as the
security policy describes.