Library / SDK
rust-lang/ssh2-rs avatar
rust-lang/ssh2-rs

ssh2-rs and the Rust binding for libssh2

Rust bindings for libssh2

569 stars166 forksRustApache-2.0

At a glance

What is it?
ssh2-rs, published on crates.io as ssh2, is a set of Rust bindings for libssh2 that give you SSH sessions, remote command execution and local port forwarding without writing the protocol yourself. The interesting engineering is the vendored-openssl feature, and the interesting constraint is that the crate still builds a native library underneath.
Who is it for?
ssh2-rs is a good fit for a Rust project that needs an SSH client library, because it exposes libssh2's full surface in idiomatic Rust, including remote command execution and local port forwarding, and it lets you drop the OpenSSL system dependency with the vendored-openssl feature.
Can I use it commercially?
Yes. Apache-2.0 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 17 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the crate actually wraps

The one-line description is Rust bindings to libssh2, an ssh client library, and the package metadata expands it: bindings to libssh2 for interacting with SSH servers and executing remote commands, forwarding local ports, and so on.

So this is not a from-scratch SSH implementation. The protocol work, the key exchange, the cipher negotiation and the transport layer all live in libssh2, which is a C library, and the Rust side is the FFI boundary and the safe wrapper around it. That distinction shapes everything else about the crate, including its build requirements and its version cadence.

The crate is published as ssh2, and the repository lives under rust-lang in the GitHub organisation while the README badges still point at the alexcrichton/ssh2-rs paths from before that move. The Cargo.toml lists three authors, Alex Crichton, Wez Furlong and Matteo Bigoi, and the current version is 0.9.6.

The audience is a Rust developer who needs to talk to an SSH server from an application or a tool, and who would rather not implement the protocol or shell out to the ssh binary. The functions named in the package description cover what people actually want: run a command on a remote host and open a tunnel.

The reason to reach for this rather than a pure-Rust implementation is the same reason people reach for libssh2 in C: it is a mature, widely deployed implementation of a protocol with a long history of awkward edge cases, and the cryptography underneath it comes from a library that has been through a great deal of scrutiny.

The dependency chain and the Cargo.toml

The manifest is small enough to read in one sitting, and every entry in it is load-bearing.

toml
[dependencies]
bitflags = "2"
libc = "0.2"
libssh2-sys = { path = "libssh2-sys", version = "0.3.2" }
parking_lot = "0.12"

The libssh2-sys entry is the interesting one, and it uses a path dependency with a version alongside. That means the C library is built from a vendored source tree in the repository rather than being found on the system, and the path form means the build uses the copy in this checkout while the version field still lets other crates depend on it from crates.io.

bitflags is how libssh2's many status and error constants are surfaced, which is the idiomatic Rust pattern for a C library's flag words. libc provides the platform types. parking_lot provides the lock primitives, and its presence tells you the crate is willing to use a spinlock-based mutex rather than the standard library's, which matters when the lock is held across a syscall.

There are two feature flags, and the whole configuration surface is in those two lines:

toml
[features]
vendored-openssl = ["libssh2-sys/vendored-openssl"]
openssl-on-win32 = ["libssh2-sys/openssl-on-win32"]

The first turns on a static OpenSSL build, and the second is a Windows-specific accommodation for finding OpenSSL there.

The repository layout backs up the two-level structure. There is a libssh2-sys/ directory holding the raw bindings and the vendored C source, a src/ directory for the safe Rust API, a tests/ directory, and a systest/ directory that is a separate workspace member, which is the conventional way to run the C library's own test suite against the bindings rather than reimplementing it in Rust.

The vendored-openssl decision, and the macOS pain

The README has a section headed Building on OSX 10.10+, and it is short enough to quote the shape of. The library depends on OpenSSL, and to get OpenSSL working on macOS you are pointed at the openssl crate's instructions.

That pointer is the whole story. libssh2 does not implement cryptography itself, it uses OpenSSL or a compatible backend, so the crate inherits OpenSSL as a build and link dependency, and on macOS that means dealing with the fact that the system OpenSSL is not the one you want to link against.

The escape hatch arrived with version 0.4 of ssh2. The vendored-openssl feature has libssh2 built against a statically built version of OpenSSL, as described in the openssl crate's own documentation. With that feature enabled, the build no longer depends on a system OpenSSL at all: the C library is compiled against a copy of OpenSSL that comes with the build, and the resulting binary carries it.

That is a genuine trade-off rather than a free win. In exchange for not managing a system OpenSSL, you accept a longer build, a larger binary, and your own copy of OpenSSL to patch. For a distributed CLI tool, that is often the right answer, because the alternative is asking every user to install an OpenSSL development package. For a server-side application where a system OpenSSL is already managed, the vendored path may be unnecessary weight.

The version detail is worth remembering: the feature has existed since 0.4 of the crate, and the current version is 0.9.6, so the option is well established rather than experimental.

Adding it to a project and making a first connection

Adding the crate is the two-line dependency the README gives:

toml
# Cargo.toml
[dependencies]
ssh2 = "0.9"

The version 0.9 matches the 0.9.6 release in the manifest, and the API documentation is published on docs.rs under the ssh2 crate, which is where you go after the dependency is in place.

A first connection follows the shape of the C library rather than the shape of a Rust API designed from scratch. You open a session that owns the connection state, authenticate with a user and either a password or a private key, and then open a channel for a command, a file transfer handle for file operations, or a direct TCP/IP channel for forwarding. The session object has to outlive everything else, because the underlying libssh2 session is what owns the socket and the negotiated keys, and borrowing rules in the Rust wrapper will reflect that.

The port forwarding in the package description is the part that most often surprises people who came from a different SSH library, because in libssh2 the local side of a tunnel is opened by the remote host, not by you. The client asks the server to listen on a port on the server's side and connects to that port on the server's behalf. That is a different shape from the usual local forwarding model, and it is worth reading the API docs before assuming the semantics of ssh -L.

For development the repository offers a Travis configuration, a .gitmodules file and the systest workspace member, so the crate's own test coverage comes from running libssh2's system test suite rather than from a parallel Rust implementation.

What this crate will not do for you

Three boundaries are worth stating before you commit to it.

The first is that it is a binding, so a C library is in your build. The vendored-openssl feature removes the OpenSSL system dependency but not the need to compile C. If your build environment forbids a C toolchain, or if you are targeting a platform with no C compiler in the pipeline, this crate will not work as-is.

The second is the model of concurrency. The crate is organised around a Session that you authenticate and then call into, and the API is blocking. The presence of parking_lot tells you the internals use a lock, which is what you would expect from a wrapper around a C library that has its own global-ish state in libssh2. If you want an async SSH client, this is the wrong crate, and you would be looking at running it on a blocking thread pool or choosing a different library.

The third is scope. This is a client library. It does not implement a server, it does not manage keys for you, and it does not give you the agent or the config file handling that the OpenSSH command line provides. You still have to decide where the private key comes from and whether to pass a passphrase, and that decision is a security decision you are making in your own code rather than something the crate takes care of.

The version number deserves a note too. The crate is at 0.9.6, which under Cargo's semantic versioning rules means the 0.9 series is treated as a single compatibility range: 0.9.7 and 0.9.8 would be compatible, and 0.10 would be a breaking change. The repository has no GitHub releases, so the crates.io version history is the release record.

Licensing, maintenance and how this differs from the alternatives

The licence is the one thing about this project that is unusually accommodating, and it is worth quoting the mechanism rather than the label.

The project is licensed under either of the Apache License, Version 2.0, or the MIT licence, at your option. Contributions are dual licensed the same way: any contribution intentionally submitted for inclusion, as defined in the Apache-2.0 licence, shall be dual licensed as above, without any additional terms or conditions.

That last clause matters more than it looks. A dual-licensing scheme with no additional terms means an outside contributor cannot inject a CLA-style claim into a pull request, and you can pick whichever of the two terms suits your distribution model. Both LICENSE-APACHE and LICENSE-MIT are at the repository root.

The repository is not archived and the last push was on 2026-10-06, so the crate is receiving work. The CI badges show separate workflows for Linux, Windows and macOS, which is the right shape for a crate whose build depends on a native library and an OpenSSL backend, since the platform differences are exactly where the build breaks.

The real alternative is a pure-Rust SSH implementation, and the difference in approach is fundamental rather than incremental. A pure-Rust crate has no C library in the build, no OpenSSL to arrange, and can therefore target wasm, embedded and cross-compilation setups that this one cannot. What it gives up is the maturity of libssh2: the C library has years of production use behind it, and its protocol handling has been hardened against a decade of accumulated edge cases.

There is a third option worth naming, which is to not use a library at all and shell out to the ssh binary, or to the sftp binary. That gets you the system implementation, with the system's key handling and known configuration, at the cost of process management, parsing output and the loss of a programmatic API. For a script or a one-off tool this is often the pragmatic choice. For anything that needs multiple parallel channels or port forwarding under program control, a library is the better fit, and between the libraries the choice comes down to whether you can accept a C dependency in the build.

Editorial conclusion

ssh2-rs is a good fit for a Rust project that needs an SSH client library, because it exposes libssh2's full surface in idiomatic Rust, including remote command execution and local port forwarding, and it lets you drop the OpenSSL system dependency with the vendored-openssl feature. It is a poor fit if you need a pure-Rust implementation with no C library in the build, since libssh2-sys compiles a native dependency, and a poor fit if you need an async API, since the crate is built around a blocking session object. Before adopting, check whether your target platform has a usable OpenSSL, because the README's macOS guidance points at the openssl crate's instructions, and decide early whether the vendored build is acceptable, since it changes what your release artefacts look like.

Frequently asked questions

How do I add ssh2-rs to a Rust project?

Add `ssh2 = "0.9"` to the dependencies in your Cargo.toml. The crate is published on crates.io as ssh2, and the API documentation is on docs.rs.

Does ssh2-rs require OpenSSL to be installed?

The library depends on OpenSSL, and the README points at the openssl crate's instructions for macOS. Starting with version 0.4 of ssh2, the vendored-openssl feature builds libssh2 against a statically built OpenSSL instead of a system one.

What can I do with the ssh2 crate?

The crate description says it provides bindings to libssh2 for interacting with SSH servers and executing remote commands, forwarding local ports, and related operations, so sessions, remote commands and local port forwarding are all in scope.

What licence does ssh2-rs use?

Either the Apache License, Version 2.0, or the MIT licence, at your option, and contributions are dual licensed the same way without additional terms. Both LICENSE-APACHE and LICENSE-MIT are at the repository root.

Which platforms does ssh2-rs build on?

The README carries separate build status badges for Linux, Windows and macOS workflows, and the macOS section is dedicated to getting OpenSSL working there. The crate version is 0.9.6 and the repository was last pushed to on 2026-10-06.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. README
  5. rust-lang/ssh2-rs on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rust-lang-ssh2-rs.svg)](https://hysenlabs.com/projects/rust-lang-ssh2-rs)