Apache MINA SSHD Documentation

repository·master·Indexed 22 days ago

https://github.com/apache/mina-sshd

A pure Java library providing SSH client and server capabilities for Java applications. It supports multiple I/O back-ends including NIO2, Apache MINA, and Netty. The project is modularized into various artifacts such as sshd-core, sshd-sftp, sshd-scp, and sshd-ldap. Requires Java 8+ for runtime (version 2.3+) and Java 17+ for build time (version 2.14+).

Tokens
59K
Snippets
134
Records
278
Agent score
75%

What's inside Apache MINA SSHD

  1. Overview of Apache MINA SSHD

    master

    Apache MINA SSHD is a pure Java library providing SSH protocol support for both clients and servers. It is designed for integration into Java-based applications rather than replacing standalone Unix SSH clients/servers.

    It supports multiple I/O back-ends for network transport:

    • Default: Built-in transport using Java's AsynchronousSocketChannel (NIO2).
    • Apache MINA: High-performance asynchronous I/O library.
    • Netty: Asynchronous event-driven network framework.
  2. Overview of JMH Benchmarks

    master

    The sshd-benchmarks project provides JMH (Java Microbenchmark Harness) benchmarks for Apache MINA SSHD. Note that these benchmarks are not included in the standard Apache MINA SSHD binary distribution.

    For specific details regarding individual benchmark implementations, refer to their respective README files within the repository.

  3. Understand the Apache SSHD distribution structure

    master

    The distribution is organized into the following directories:

    • /bin: Contains Linux and Windows shell scripts for running the demonstration code with default settings.
    • /lib: Contains all JAR files required to run the SSH client and server, including NIO2 I/O factories, SCP, SFTP, SOCKS, and ed25519 support.
    • /extras: Contains additional SSH-related functionality such as JGit, Putty, LDAP, and Spring SFTP.
    • /dependencies: Contains 3rd party artifacts required by the components in /extras.
    • /licenses: Contains copies of all 3rd party licenses used in the project.
  4. Efficiently list SFTP directories and attributes

    master

    When using SftpFileSystem (NIO), calling Files.readAttributes() or Files.size() triggers a remote network call, which is expensive. Standard Java FileVisitor implementations are also slow because they call readAttributes() for every file.

    To list files and attributes efficiently, you have two options:

    1. Use SftpClient directly: Use client.readDir() to get DirEntry objects, which contain both the filename and the attributes in a single request.
    2. Cast to SftpPath: If using DirectoryStream<Path>, the returned Path objects are often SftpPath instances. You can cast them to SftpPath to access cached attributes without a new network call.

    Warning: Attributes are a snapshot from the time the directory was listed. They do not reflect subsequent changes to the files.

    // Efficient way using SftpPath cache
    try (DirectoryStream<Path> dir = Files.newDirectoryStream(directoryPath)) {
      for (Path path : dir) {
        if (path instanceof SftpPath) {
          SftpClient.Attributes attributes = ((SftpPath) path).getAttributes();
          process.accept(path, attributes);
        }
      }
    }
  5. Note on UINT32 packet encoding/decoding changes

    master

    Most encoded/decoded packets specified as UINT32 in the protocol now use long instead of int to prevent overflow issues.

    Exceptions (where int is still used):

    • SFTP packet id field.
    • Various flags and mask fields (as they do not represent cardinal 32-bit numbers).
    • Various status code fields.
    • Cases where the value is used to allocate data structures (like arrays or lists). In these cases, validation is applied to ensure the value does not exceed Integer.MAX_VALUE to prevent Out-of-Memory (OOM) attacks.
  6. Understand the SFTP benchmark components

    master

    The SFTP benchmark suite consists of three distinct methods to compare upload performance:

    1. CatUpload: Simulates an upload using the equivalent of ssh user@host 'cat > upload/testfile.bin' < localfile.bin. This serves as a baseline and is expected to be faster than SFTP because it lacks SFTP message header overhead and SFTP ACKs.
    2. JschBenchmark: Measures upload performance using the JSch library.
    3. SshBenchmark: Measures upload performance using various methods provided by Apache MINA sshd.

    Each benchmark run is executed twice to compare different cipher configurations:

    • JSch defaults: aes128-ctr cipher and hmac-sha2-256-etm@openssh.com MAC.
    • Apache MINA sshd defaults: chacha20-poly1305@openssh.com cipher.
  7. How the SftpFileSystem channel pool works

    master

    To avoid the high network cost of opening and closing an SSH channel for every single file operation, SftpFileSystem maintains a pool of SftpClient instances.

    • Lifecycle: When an operation is requested, the file system grabs an existing SftpClient from the pool. If the pool is empty, it creates and initializes a new one. After the operation completes, the client is returned to the pool instead of being closed.
    • Expiration: To prevent resource exhaustion on the client and server, idle clients are removed from the pool after a period defined by SftpModuleProperties.POOL_LIFE_TIME (default: 10 seconds).
    • Core Size: By default, the pool can shrink to zero idle clients. If you want to keep a minimum number of channels open even when idle, configure SftpModuleProperties.POOL_CORE_SIZE (must be less than POOL_SIZE).
  8. Understand Buffering and Throughput in SSH Tunnels

    master

    SSH tunnels use two handlers: a read handler (reading from the SSH channel and writing to the port) and a write handler (reading from the port and writing to the SSH channel).

    Performance and Memory Characteristics:

    • Constant Memory Usage: There is no internal buffering between handlers. Each handler reads a fixed-size buffer and writes it before initiating the next read. This prevents memory from piling up.
    • Automatic Throttling: Throughput is automatically throttled to the slowest part of the connection. If the producer is faster than the SSH channel can write, the system 'pushes back' on the producer by stopping reads, eventually filling transport buffers and causing the producer to wait.
    • Optimization Tip: For best performance, ensure the read buffer size is a multiple of the SSH packet payload size. If the buffer is larger than the SSH packet payload, a single buffer write will be split into multiple SSH packets, which may impact efficiency.
  9. Configure cascading proxy jumps

    master

    Apache MINA SSHD supports both chained and cascading proxy jumps.

    • Chained: Specifying multiple proxies in a single directive (e.g., ProxyJump jumphost2, jumphost1).
    • Cascading: Defining proxy jumps through individual host configurations where one host's ProxyJump points to another host that itself has a ProxyJump.

    To prevent infinite loops in misconfigured cascades, the library imposes a limit on the total number of proxy jumps. This limit is controlled by CoreModuleProperties.MAX_PROXY_JUMPS, which defaults to 10.

  10. Handle unknown or unimplemented global requests

    master

    When a recipient receives a global request it doesn't recognize, it may respond in two ways:

    1. SSH_MSG_REQUEST_FAILURE: The standard response for an unknown request name if the sender requested a reply (want-reply=true).
    2. SSH_MSG_UNIMPLEMENTED: A response indicating the recipient might not implement global requests at all.

    Apache MINA sshd handles SSH_MSG_UNIMPLEMENTED by tracking the SSH packet sequence number of each request. If an unimplemented message arrives, the library matches the sequence number to the correct request in its internal FIFO list and fails that specific request, even if it is not at the front of the queue.

  11. Understand Global Requests in SSH

    master

    Global requests are SSH messages sent between a client and a server that are independent of any specific SSH channel. They are used to provide information or instruct the peer to perform actions, such as starting or cancelling TCP/IP remote port forwarding or handling host key updates.

    There are two types of global requests based on the want-reply flag:

    • want-reply=false: Asynchronous, "fire-and-forget" one-way messages.
    • want-reply=true: RPC-style messages that expect a reply (SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE).

    Because the SSH protocol lacks unique request identifiers in replies, RFC 4254 requires that replies must be sent in the same order as the corresponding requests.