Traversio

ProxyJump

Reach a final SSH server through one or more SSH jump hosts before you open shell, exec, SFTP, or forwarding work on the final connection.

ProxyJump defines the SSH hop chain used to reach a final server through one or more bastion hosts.

+-----------+      +----------------------+      +---------------------+
| Local app | ---> | Jump host            | ---> | Final SSH server    |
+-----------+      +----------------------+      +---------------------+
                     | 1. Authenticate here |
                     | 2. Open direct-tcpip |
                     |    to the next hop   |
                     +----------------------+

What actually happens:

1. SSH connection #1 is established to the jump host
2. A direct-tcpip channel is opened through that jump host
3. SSH connection #2 is established inside that channel
4. The returned SSHConnection is the final target connection

Example: Reach An Internal Host Through A Bastion

import Traversio

let configuration = SSHClientConfiguration(
    host: "db-admin.internal",
    username: "deploy",
    authentication: .password("final-target-password"),
    hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts"),
    compressionPreference: .delayedZlib,
    proxyJumpHosts: [
        SSHProxyJumpHost(
            host: "bastion.example.com",
            username: "deploy",
            authentication: .password("bastion-password"),
            hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts"),
            compressionPreference: .delayedZlib
        )
    ]
)

let result = try await SSHClient.withConnection(configuration: configuration) { connection in
    try await connection.execute("hostname")
}

Connection flow:

  1. Traversio opens an SSH connection to bastion.example.com
  2. Traversio authenticates and verifies that hop
  3. Traversio opens a direct-tcpip channel through that hop to db-admin.internal:22
  4. Traversio runs a second SSH handshake inside that channel
  5. the returned SSHConnection is the final target connection

Multi-Hop Example

proxyJumpHosts is an array because real networks often need more than one hop:

let configuration = SSHClientConfiguration(
    host: "final.internal",
    username: "deploy",
    authentication: .password("final-password"),
    hostKeyPolicy: .acceptAnyVerifiedHostKey,
    proxyJumpHosts: [
        SSHProxyJumpHost(
            host: "bastion-a.example.com",
            username: "jump-a",
            authentication: .password("jump-a-password"),
            hostKeyPolicy: .acceptAnyVerifiedHostKey
        ),
        SSHProxyJumpHost(
            host: "bastion-b.internal",
            username: "jump-b",
            authentication: .password("jump-b-password"),
            hostKeyPolicy: .acceptAnyVerifiedHostKey
        ),
    ]
)

Each hop has its own:

  • host
  • port
  • username
  • authentication
  • host key policy
  • compression preference
  • automatic rekey policy

The final target keeps its transport settings on the root SSHClientConfiguration. Bastion hosts often use different credentials, trust rules, or transport policy than the final server.

Connection Proxies And ProxyJump

These features cover different layers of the route:

  • ProxyJump: SSH to hop A first, then carry the next SSH hop inside A
  • HTTP/SOCKS connection proxy: send the outer TCP connection through a non-SSH proxy before SSH starts

Traversio supports ProxyJump and user-specified HTTP CONNECT or SOCKS5 outer connection proxies through SSHClientConfiguration.connectionProxy.

If you set both:

  • connectionProxy controls how Traversio reaches the first hop
  • proxyJumpHosts controls which SSH hop comes first after that tunnel exists

Validation

ProxyJump is validated through a real first-hop SSH connection plus a nested final-target SSH handshake through that hop.

The documented path also shares the broader Traversio connection validation story: host-key trust, authentication, compression, rekey, setup timeout, connection proxies, and structured diagnostics all run through the same public connection machinery.

Applications should still validate their own bastion topology, host-key policy, auth methods, and proxy environment before critical rollout.

On this page