SSH.NET: a .NET SSH-2 client library for commands, SFTP, SCP and port forwarding
SSH.NET is a Secure Shell (SSH) library for .NET, optimized for parallelism.
At a glance
- What is it?
- SSH.NET is an MIT-licensed C# library that speaks SSH-2 from inside a .NET process. It suits services that need SFTP or remote command execution without shelling out to an ssh binary, and it is a poor fit if you only need a one-off interactive session.
- Who is it for?
- Adopt SSH.NET when you need SSH-2 inside a .NET process: scheduled SFTP transfers, remote command execution, or forwarded ports from a service. Do not adopt it if you only need an interactive terminal, since the ssh binary already does that job.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 29 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What SSH.NET solves, and for whom
A .NET service that needs to move a file to a remote host or run a command there has two options: spawn an ssh process and parse its output, or speak the protocol in-process. SSH.NET takes the second route. It is a Secure Shell (SSH-2) library written in C#, and the README describes it as "optimized for parallelism", which points at the intended user: a server-side component handling several connections at once, not a desktop tool for one interactive session.
The feature list covers the operations that usually force a process spawn. Commands run through SshClient with both synchronous and asynchronous methods. Files move through SftpClient, also in both styles, and SCP is supported as well. Remote, dynamic and local port forwarding are available through ForwardedPort types, and there is an interactive shell implementation via ShellStream. Authentication covers public key, password and keyboard-interactive, including multi-factor, and the client can reach the server through a SOCKS4, SOCKS5 or HTTP proxy.
The audience is therefore narrow and specific. If you write a backup job, a deployment step, a log collector or a file-sync service in C# and it has to talk to an SFTP endpoint, this library removes the subprocess and the brittle parsing that comes with it. If you are a person who wants to log into a machine and type, the library is the wrong layer entirely.
Inside the connection: clients, commands and streams
The API is built around client objects that own a connection. SshClient and SftpClient are the two entry points named in the README, and both follow a connect, use, dispose pattern. The README's own example wraps the client in a using block, calls Connect(), then runs a command and reads the result. The result arrives as a string on SshCommand.Result, so the library is buffering command output for you rather than exposing a raw socket.
SFTP is modelled as a file system rather than a byte stream. SftpClient exposes UploadFile, which takes a Stream and a remote path, and ListDirectory, which returns ISftpFile objects carrying FullName and LastWriteTime. That shape matters: you can walk a remote directory tree and make decisions on timestamps without writing your own SFTP packet handling.
The remaining types fill in the gaps. PrivateKeyFile parses key material, ForwardedPort handles tunnelling, and ShellStream gives you the interactive terminal case. The README links each of these to an API page on sshnet.github.io, and it also links separate pages for further examples and for logging, which suggests logging is configured rather than automatic. The README does not document rollback behaviour, connection retry policy or how a dropped connection surfaces to a caller, so those are things to establish from the API pages or from reading src/ before you depend on them.
Installing SSH.NET and running a first command
The package is published on NuGet as SSH.NET, and the README's badge points at nuget.org/packages/SSH.NET. Add it to a project with the standard .NET CLI command:
dotnet add package SSH.NETAfter restore, the types live in the Renci.SshNet namespace. The README's first example connects with a private key and runs a command. Note the constructor takes the host, the user name and a PrivateKeyFile, and that the command object is disposed alongside the client:
using (var client = new SshClient("sftp.foo.com", "guest", new PrivateKeyFile("path/to/my/key")))
{
client.Connect();
using SshCommand cmd = client.RunCommand("echo 'Hello World!'");
Console.WriteLine(cmd.Result); // "Hello World!\n"
}Running that against a reachable host prints the command output, in this case the echoed line. If the connection fails, the exception surfaces from Connect() or from the command call, not from the constructor.
The SFTP path is the second example in the README. It opens a local file, uploads it, then lists the remote directory and prints each entry's full path and last write time:
using (var client = new SftpClient("sftp.foo.com", "guest", "pwd"))
{
client.Connect();
using (FileStream fs = File.OpenRead(@"C:\tmp\test-file.txt"))
{
client.UploadFile(fs, "/home/guest/test-file.txt");
}
foreach (ISftpFile file in client.ListDirectory("/home/guest/"))
{
Console.WriteLine($"{file.FullName} {file.LastWriteTime}");
}
}If you want to track a pre-release build rather than the released package, the README describes adding the GitHub NuGet Registry as a source. That requires a Personal Access Token with the read:packages permission:
dotnet nuget add source --name SSH.NET --username <username> --password <personalaccesstoken> https://nuget.pkg.github.com/sshnet/index.jsonThe README notes that on non-Windows platforms you may need to add --store-password-in-clear-text to that command. Pre-release packages are published from the develop branch, which is also the repository's default branch.
Where the compatibility surface bites
The framework targets are the first constraint. SSH.NET supports .NET Framework 4.6.2 and higher, .NET Standard 2.0, and .NET 8 and higher. A project on .NET 6 or .NET 7 sits outside that list, and .NET Framework 4.6.1 and below are out as well. That is not a defect, but it is a hard boundary you should check before planning an upgrade around this library.
The second constraint is the algorithm list, which is long but finite. Encryption covers aes128-ctr through 3des-cbc, including aes-gcm and chacha20-poly1305 variants. Key exchange spans mlkem768x25519-sha256, sntrup761x25519-sha512, curve25519-sha256, the ecdh-sha2-nistp family, and several diffie-hellman groups down to group1-sha1. Host key algorithms run from ssh-ed25519 through ssh-rsa, and OpenSSH certificate authentication is supported for all of them. MAC algorithms include hmac-sha2-256 and hmac-sha2-512 with and without the -etm variant, plus hmac-sha1.
A server hardened to a modern algorithm set will negotiate fine. A legacy appliance offering only something absent from those lists will not, and the failure appears at handshake time. Compression is limited to none, which is the default, and [email protected]. The README does not describe how to override the negotiation or pin a preferred algorithm, so if you face an unusual server, that is a gap to investigate in the API documentation before you commit.
The third thing to weigh is the interactive case. ShellStream exists, but the README's examples are all programmatic. If your requirement is a human typing commands with terminal emulation, local scrollback and resize handling, the ssh binary or a terminal application is the simpler answer. SSH.NET is the wrong tool when the session is not driven by code.
SSH.NET against WinSCP and the renci lineage
The most common comparison for file transfer work is WinSCP. The difference is architectural rather than a matter of features. WinSCP is an application with a scripting interface and a separate .NET assembly that wraps it; the transfer logic lives outside your process boundary in a Windows-oriented tool. SSH.NET is a managed library that runs inside your application, so there is no external executable to deploy, no script to generate, and no console output to parse. The cost is that you write the orchestration yourself: retries, progress reporting and concurrency are your code, not a script engine's.
The second comparison is the naming itself. The types are in the Renci.SshNet namespace and the project is now sshnet/SSH.NET, so searching for one name turns up the other. They are the same lineage: the namespace is the historical identifier, and the package on NuGet is SSH.NET. Anyone deciding between "ssh net" and "renci" is choosing between two labels for one library, not two libraries.
For teams that want a protocol-level alternative rather than a wrapper, the honest answer is that SSH.NET's own README does not name a competitor. What it does give you is the full algorithm and key-format matrix, which is the material you would use to compare against any other .NET SSH implementation: if the other option cannot read PuTTY-User-Key-File-3 keys, or lacks [email protected], that is a concrete difference you can evaluate. The key format support here is broad: RSA, ECDSA 256/384/521 and ED25519 across OpenSSL traditional PEM, PKCS#8 PEM, ssh.com, OpenSSH and PuTTY formats, with per-format cipher lists for encrypted keys.
Licence, maintenance and the upgrade path
The licence is MIT, which is permissive and places few obligations on how you redistribute the library inside a product. The repository also carries a THIRD-PARTY-NOTICES.TXT file, which indicates bundled dependencies with their own terms. That file is the one to read if you need to enumerate third-party licences for a compliance review; this article is not legal advice, and the notices file plus LICENSE are the authoritative sources.
Maintenance is visible in the release cadence. The most recent release is 2026.0.0, dated 2026-08-09, following 2025.1.0 on 2025-10-27 and 2025.0.0 on 2025-04-18. The repository is not archived, and the last push to the develop branch was on 2026-09-01. The versioning scheme is calendar-based, which means a 2026.0.0 to 2027.0.0 jump signals a major boundary rather than a patch.
Upgrading carries the usual cost of a library that touches crypto: algorithm defaults can shift between major versions, and a server that negotiated cleanly on an older release may need attention on a newer one. The repository keeps a SECURITY.md, which is where the project documents how vulnerabilities are reported. If your organisation tracks CVEs for dependencies, that file and the release notes are the two places to watch, since the README itself does not carry a changelog. Pre-release builds from develop are available through the GitHub registry, but pulling them means accepting unreleased behaviour in exchange for earlier access.
Editorial conclusion
Adopt SSH.NET when you need SSH-2 inside a .NET process: scheduled SFTP transfers, remote command execution, or forwarded ports from a service. Do not adopt it if you only need an interactive terminal, since the ssh binary already does that job. Before committing, verify that your target framework is one of .NET Framework 4.6.2, .NET Standard 2.0 or .NET 8 and higher, check that the host key algorithm your server offers appears in the supported list, and read SECURITY.md for how vulnerabilities are reported.
Frequently asked questions
How do I use SSH.NET in C#?
Add the SSH.NET package from NuGet, then create an SshClient or SftpClient with a host, user name and either a password or a PrivateKeyFile. Call Connect(), run the command or transfer the file, and dispose the client; the README's examples wrap everything in a using block.
What is renci SSH net?
Renci.SshNet is the namespace the types live in, and it is the same library published on NuGet as SSH.NET. The main types are SshClient, SftpClient, PrivateKeyFile, SshCommand, ForwardedPort and ShellStream.
How is SSH.NET different from WinSCP?
SSH.NET is a managed library that runs inside your .NET process, so there is no external executable or script to manage. WinSCP is an application with a scripting interface, which means the transfer logic sits outside your application boundary.
Is SSH.NET free?
Yes. The repository is licensed under MIT, which permits commercial and private use with few conditions, and it also ships a THIRD-PARTY-NOTICES.TXT file covering bundled dependencies.
What is SSH.NET?
It is a Secure Shell (SSH-2) library for .NET, written in C# and described in the README as optimized for parallelism. It covers command execution, SFTP, SCP, port forwarding and an interactive shell.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sshnet-ssh-net)