Connection Configuration
How to choose endpoint, trust, transport, and routing settings for an SSH connection.
SSHClientConfiguration is the complete description of one SSH connection attempt. It answers four practical questions:
- where to connect
- how to authenticate
- how to trust the server
- how the transport should behave once the session is up
If you use jump hosts, SSHProxyJumpHost repeats the same per-hop transport knobs on each SSH hop. The root SSHClientConfiguration continues to describe the final target and any outer connectionProxy used before the first SSH handshake starts.
Defaults At A Glance
| Field | Default | What it controls |
|---|---|---|
host | required | Final target host name or address |
port | 22 | Final target port |
username | required | SSH username |
authentication | required | User authentication method |
hostKeyPolicy | required | Host trust policy |
compressionPreference | .disabled | Whether to advertise transport compression |
legacyAlgorithmOptions | .disabled | Optional legacy host-key and RSA auth compatibility controls |
automaticRekeyPolicy | .currentProfileDefault | Automatic client-initiated rekey thresholds |
keepalivePolicy | .disabled | Post-auth idle keepalive behavior |
timeoutPolicy | .disabled | Connection-setup and prompt-reply timeout behavior |
connectionProxy | nil | Optional outer SOCKS5 or HTTP CONNECT hop before SSH starts |
proxyJumpHosts | [] | Optional SSH jump-host chain before the final target |
The matching SSHProxyJumpHost fields are:
hostportusernameauthenticationhostKeyPolicycompressionPreferencelegacyAlgorithmOptionsautomaticRekeyPolicykeepalivePolicytimeoutPolicy
Endpoint, Auth, And Trust
These are the required inputs:
hostusernameauthenticationhostKeyPolicy
Typical choices:
- use a stable DNS name when you rely on
known_hostshostnames or certificate principals - keep
hostKeyPolicystrict in production;.acceptAnyVerifiedHostKeyis only appropriate for disposable test targets - choose the simplest auth method your deployment already manages well: password for controlled lab/testing, public-key auth for normal production automation
Transport Settings
compressionPreference
Default: .disabled
Supported values:
.disabled.zlib.delayedZlib
.zlib means RFC 4253 zlib: compression starts as soon as the encrypted transport is active after each key exchange.
.delayedZlib means OpenSSH [email protected]: compression stays off during handshake and user authentication, then turns on only after authentication succeeds.
Use it when:
- bandwidth is scarce
- you expect larger shell, exec, or SFTP payloads
- the target server is already known to support either RFC 4253
zlibor the OpenSSH delayed-zlib path
Leave it off when:
- connections are short-lived
- payloads are small
- CPU cost matters more than wire size
automaticRekeyPolicy
Default: .currentProfileDefault
currentProfileDefault currently means:
outboundPacketThreshold: 1_048_576inboundPacketThreshold: 1_048_576idleTimeInterval: nil
Use a custom policy when:
- you want tighter packet budgets on long-lived connections
- you need an idle timer which triggers a client rekey even when the connection is quiet
- you are reproducing or validating server behavior under more aggressive rekey conditions
Use .disabled only when you intentionally want to turn off client-initiated automatic rekey.
legacyAlgorithmOptions
Default: .disabled
Supported values:
.disabled.sshRSA
SSHLegacyAlgorithmOptions.sshRSA enables Traversio's explicit legacy RSA compatibility path for one connection or one jump-host hop.
When it is enabled:
- the connection appends
ssh-rsato the advertised server-host-key preference list - RSA public-key authentication still prefers
rsa-sha2-512andrsa-sha2-256 - if the server declines the SHA-2 attempt and still offers
publickey, Traversio retries withssh-rsa
Use it when:
- you target older SSH appliances, routers, NAS devices, or embedded systems
- the server only advertises
ssh-rsahost keys - the server accepts RSA keys only through the legacy SHA-1 signature path
Keep it disabled for current OpenSSH-family servers and other modern deployments.
keepalivePolicy
Default: .disabled
SSHKeepalivePolicy(interval: ...) sends a keepalive only after authentication succeeds and the connection has stayed idle for that interval.
Use it when:
- the connection stays open for a long time
- shells or forwarding sessions may sit idle between bursts
- NAT or firewall devices may silently drop an otherwise idle TCP flow
Leave it disabled when:
- the connection is short-lived
- you mostly run one command or one SFTP transfer and then disconnect
- extra background traffic is not desirable
Behavior:
- keepalive applies to idle authenticated connections
timeoutPolicyremains the dedicated timeout control- long-running shell and exec reads keep their own streaming behavior
If you also set timeoutPolicy.responseTimeInterval, keepalive reply waits use the tighter of that reply timeout and the keepalive interval itself.
timeoutPolicy
Default: .disabled
SSHTimeoutPolicy has two independent knobs:
connectionSetupTimeIntervalresponseTimeInterval
connectionSetupTimeInterval covers one connect attempt, including:
- transport connection setup
- identification exchange
- key exchange
- host-key trust evaluation
- user authentication
responseTimeInterval covers waits where the peer should answer promptly, including:
- channel-open replies
- channel-request replies such as
exec,pty-req,shell, andsubsystem - global-request replies such as
tcpip-forward - SFTP responses
responseTimeInterval covers prompt request or reply paths. Long-running streams continue independently, including:
- long-running command output collection
- interactive shell streams
- remote-forward accept loops
Routing: Proxy Versus Jump Host
connectionProxy and proxyJumpHosts solve different problems.
Use connectionProxy when Traversio itself must first reach the SSH server through:
- a SOCKS5 proxy
- an HTTP CONNECT proxy
Use proxyJumpHosts when you want SSH hop chaining through one or more bastion hosts.
Important boundary:
connectionProxyis only for the outermost TCP hop before the first SSH handshakeproxyJumpHostsis the SSH-native hop chain after that
If you set both, the external proxy is used only for the first TCP connection. Later hops travel inside SSH direct-tcpip channels.
Rules Of Thumb
- Start with the defaults and add only the knobs you actually need.
- Add
timeoutPolicyfirst for automation and background jobs. It usually gives more immediate value than keepalive. - Add
keepalivePolicyfor long-lived shells, tunnels, or idle monitoring connections. - Keep compression off unless you have a concrete bandwidth reason to turn it on.
- Treat
SSHProxyJumpHostas hop-specific transport policy. The final target still uses the rootSSHClientConfiguration.
Example
let configuration = SSHClientConfiguration(
host: "app.internal.example.com",
username: "deploy",
authentication: try .ed25519PrivateKey(
contentsOfOpenSSHPrivateKeyFile: "/Users/me/.ssh/id_ed25519"
),
hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts"),
legacyAlgorithmOptions: .disabled,
automaticRekeyPolicy: .currentProfileDefault,
keepalivePolicy: .init(interval: 30),
timeoutPolicy: .init(
connectionSetupTimeInterval: 20,
responseTimeInterval: 5
),
proxyJumpHosts: [
SSHProxyJumpHost(
host: "bastion.example.com",
username: "deploy",
authentication: try .ed25519PrivateKey(
contentsOfOpenSSHPrivateKeyFile: "/Users/me/.ssh/id_ed25519"
),
hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts"),
legacyAlgorithmOptions: .disabled,
keepalivePolicy: .init(interval: 30),
timeoutPolicy: .init(responseTimeInterval: 5)
)
]
)