
SwiftNIO SSH is a programmatic implementation of SSH using SwiftNIO
This project contains SSH support using SwiftNIO.
SwiftNIO SSH is a programmatic implementation of SSH: that is, it is a collection of APIs that allow programmers to implement SSH-speaking endpoints. Critically, this means it is more like libssh2 than openssh. SwiftNIO SSH does not ship production-ready SSH clients and servers, but instead provides the building blocks for building this kind of client and server.
There are a number of reasons to provide a programmatic SSH implementation. One is that SSH has a unique relationship to user interactivity. Technical users are highly accustomed to interacting with SSH interactively, either to run commands on remote machines or to run interactive shells. Having the ability to programmatically respond to these requests enables interesting alternative modes of interaction. As prior examples, we can point to Twisted's Manhole, which uses a programmatic SSH implementation called conch to provide an interactive Python interpreter within a running Python server, or ssh-chat, a SSH server that provides a chat room instead of regular SSH shell functionality. Innovative uses can also be imagined for TCP forwarding.
Another good reason to provide programmatic SSH is that it is not uncommon for services to need to interact with other services in a way that involves running commands. While Process solves this for the local use-case, sometimes the commands that need to be invoked are remote. While Process could launch an ssh client as a sub-process in order to run this invocation, it can be substantially more straightforward to simply invoke SSH directly. This is libssh2's target use-case. SwiftNIO SSH provides the equivalent of the networking and cryptographic layer of libssh2, allowing motivated users to drive SSH sessions directly from within Swift services.
The most recent versions of SwiftNIO SSH support Swift 5.9 and newer. The minimum Swift version supported by SwiftNIO SSH releases are detailed below:
| SwiftNIO SSH | Minimum Swift Version |
|---|---|
0.0.0 ..< 0.3.0 | 5.1 |
0.3.0 ..< 0.4.0 | 5.2 |
0.4.0 ..< 0.5.0 | 5.4 |
0.5.0 ..< 0.6.2 | 5.5.2 |
0.6.2 ..< 0.9.0 | 5.6 |
0.9.0 ..< 0.9.2 | 5.8 |
0.9.2 ..< 0.10.0 | 5.9 |
0.10.0 ... 0.12.0 | 5.10 |
0.12.0 ..< 0.13.0 | 6.0 |
0.13.0 ..< | 6.1 |
SwiftNIO SSH supports SSHv2 with the following feature set:
SwiftNIO SSH provides a SwiftNIO ChannelHandler, NIOSSHHandler. This handler implements the bulk of the SSH protocol directly. Users are not expected to generate SSH messages directly: instead, they interact with the NIOSSHHandler through child channels and delegates.
SSH is a multiplexed protocol: each SSH connection is subdivided into multiple bidirectional communication channels called, appropriately enough, channels. SwiftNIO SSH reflects this construction by using a "child channel" abstraction. When a peer creates a new SSH channel, SwiftNIO SSH will create a new NIO Channel that is used to represent all traffic on that SSH channel. Within this child Channel all events are strictly ordered with respect to one another: however, events in different Channels may be interleaved freely by the implementation.
An active SSH connection therefore looks like this:
┌ ─ NIO Channel ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
│ ┌────────────────────────────────┐ │
│ │
│ │ │ │
│ │
│ │ │ │
│ NIOSSHHandler │───────────────────────┐
│ │ │ │ │
│ │ │
│ │ │ │ │
│ │ │
│ └────────────────────────────────┘ │ │
│
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │
│
│
│
│
▼
┌── SSH Child Channel ─────────────────────────────────────────────────────────────┐
│ │
│ ┌────────────────────────────────┐ ┌────────────────────────────────┐ ├───┐
│ │ │ │ │ │ │
│ │ │ │ │ │ ├───┐
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ User Handler │ │ User Handler │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ └────────────────────────────────┘ └────────────────────────────────┘ │ │ │
│ │ │ │
└───┬──────────────────────────────────────────────────────────────────────────────┘ │ │
│ │ │
└───┬──────────────────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────┘
An SSH channel is invoked with a channel type. NIOSSH supports three: session, directTCPIP, and forwardedTCPIP. The most common channel type is session: session is used to represent the invocation of a program, whether a specific named program or a shell. The other two channel types are related to TCP port forwarding, and will be discussed later.