Forwarding & tunnels
All four of these dedicate an entire SSHConnection to the operation; while one is active, the connection cannot host any other job.
Direct TCP channel
let channel = try await connection.openDirectTCPChannel(
host: "10.0.0.5",
port: 6379
)
try await channel.write(Data("PING\r\n".utf8))
let reply = try await channel.read(maximumLength: 64 * 1024)
try await channel.close()
Use this when you have a target host+port reachable from the SSH server and you want to drive the protocol yourself.
Local forward (-L)
The SSH server forwards traffic from a local listener to a remote target.
let forward = try await connection.startLocalForward(
localHost: "127.0.0.1",
localPort: 0, // 0 = let the kernel pick
remoteHost: "db.internal",
remotePort: 5432
)
print("listening on \(forward.boundHost):\(forward.boundPort)")
try await forward.close()
Remote forward (-R)
The SSH server listens on its side and forwards connections back to the local target.
let forward = try await connection.startRemoteForward(
remoteHost: "127.0.0.1",
remotePort: 0,
localHost: "127.0.0.1",
localPort: 8080
)
Dynamic SOCKS (-D)
SSHKit runs a SOCKS5 server on a local bind that routes new TCP connections through the SSH session.
let socks = try await connection.startDynamicForward(
localHost: "127.0.0.1",
localPort: 0,
username: nil,
password: nil
)
print("SOCKS5 endpoint: \(socks.boundHost):\(socks.boundPort)")
username and password are for SOCKS5 client authentication if you want the local SOCKS server to require them. All forward objects expose the actually-bound host and port via boundHost / boundPort — useful when you passed 0.