Traversio

Direct TCP/IP Channels

Use a raw `direct-tcpip` channel when your Swift code itself should speak one forwarded TCP stream.

SSHConnection.openDirectTCPIPChannel(...) is the raw forwarding primitive in Traversio.

It is the right tool when:

  • your Swift code wants one tunnel to one target
  • you are comfortable speaking the target protocol yourself
  • you want a direct byte stream instead of a listener created for other tools

If another local application should connect to a local port that Traversio exposes, use Local Port Forwarding instead.

Mental Model

your Swift code
    -> one SSH direct-tcpip channel
        -> one remote TCP service

This API opens one channel directly from your code. Local, dynamic, and remote forwarding create listener-based workflows.

A Concrete Example

Suppose an HTTP service is only reachable from the SSH server side:

  • remote service: 127.0.0.1:8080
  • goal: from Swift, send one HTTP request and parse the raw bytes

This is a good fit for a direct channel:

import Traversio

@available(macOS 26.0, iOS 26.0, *)
func fetchRemoteHealth(configuration: SSHClientConfiguration) async throws -> String {
    let output = try await SSHClient.withConnection(configuration: configuration) { connection in
        let channel = try await connection.openDirectTCPIPChannel(
            targetHost: "127.0.0.1",
            targetPort: 8080,
            originatorAddress: "127.0.0.1",
            originatorPort: 0
        )

        try await channel.write(
            "GET /health HTTP/1.1\r\n" +
            "Host: 127.0.0.1\r\n" +
            "Connection: close\r\n\r\n"
        )
        try await channel.sendEOF()

        return try await channel.collectDataUntilClose()
    }

    return String(decoding: output.data, as: UTF8.self)
}

When This Is Better Than Local Port Forwarding

Choose openDirectTCPIPChannel(...) when:

  • the caller is your own Swift code
  • you only need one logical TCP conversation
  • you want direct access to the byte stream and EOF events

Choose local forwarding when:

  • another local client should connect to 127.0.0.1:<port>
  • you want URLSession, a browser, or a database tool to treat the tunnel like a normal local endpoint

Parameters

What the main parameters mean:

  • targetHost and targetPort identify the remote TCP service the SSH server should connect to
  • originatorAddress and originatorPort are origin metadata reported to the remote side

The defaults are usually enough when origin metadata is not important for the target service.

What You Get Back

SSHDirectTCPIPChannel exposes:

  • write(_:)
  • write(_ string: String)
  • sendEOF()
  • close()
  • readChunk()
  • nextEvent()
  • events
  • collectDataUntilClose()

Use readChunk() or events consistently on a given channel. One read style per stream keeps the control flow predictable.

Support Status

This raw path is one of the better-understood forwarding pieces in the current release.

Current state:

  • the direct channel data path is live-validated against a real local OpenSSH 9.6 target
  • it remains an expert API for raw byte streams
  • wrapper lifetime follows the owning SSHConnection

On this page