Chilkat.SshTunnel and Chilkat.Socket

Multi-Hop SSH Tunneling: Two Chilkat Arrangements

Reach a second SSH server through a first SSH server by using either ConnectThroughSsh directly or a local dynamic SOCKS forwarder as the transport for a second SSH session.

Both arrangements create two independent SSH sessions. SSH Server 1 terminates the first session and forwards an opaque connection carrying the second. SSH Server 2 terminates the second session and opens the final destination connection.

Diagram convention: Double-headed lines are established bidirectional data paths. The purple dashed path is SSH session 2. Where it crosses the first hop, it is carried inside SSH session 1 and does not terminate at SSH Server 1.

Arrangement A: ConnectThroughSsh

An Ssh object owns the first session. An SshTunnel object borrows it as transport for the second.

Arrangement B: Dynamic SOCKS + Socket

An outer SshTunnel exposes a local SOCKS listener. A Socket uses it to negotiate the second SSH session.

Arrangement A

Use SshTunnel.ConnectThroughSsh

The existing Ssh object is borrowed, not copied. It must remain alive, connected, and authenticated while the second tunnel is in use.

ConnectThroughSsh multi-hop arrangement The second SSH session follows the first SSH connection to Server 1, then continues to Server 2. All established data paths are bidirectional. LOCAL APPLICATION PROCESS Ssh objectSSH session 1to Server 1 SshTunnelSSH session 2to Server 2 borrows transport REMOTE SYSTEMS SSH Server 1Bastion / jump hostTerminates SSH session 1Forwards opaque SSH 2 bytesto Server 2 SSH Server 2Internal SSH serverTerminates SSH session 2Authenticates independentlyOpens destination channel Destinationdb.internal:5432 SSH connection 1 SSH connection 2 passes through Server 1, then continues to Server 2 destination connection

The second-session path visibly enters and exits SSH Server 1. Server 1 removes only the outer SSH protection and forwards the still-encrypted SSH 2 byte stream.

SSH session 1 SSH session 2 API/control

API sequence

Connect and authenticate an Ssh object to Server 1.
Call ConnectThroughSsh(ssh1, server2, 22).
Verify Server 2 using the SshTunnel.HostKeyFingerprint.
Authenticate the SshTunnel independently to Server 2.
Configure forwarding and call BeginAccepting.
Chilkat.Ssh ssh1 = new Chilkat.Ssh();
bool success = ssh1.Connect("bastion.example.com", 22);
// Verify ssh1.HostKeyFingerprint.
success = ssh1.AuthenticatePw("jump-user", "jump-password");

Chilkat.SshTunnel tunnel = new Chilkat.SshTunnel();
success = tunnel.ConnectThroughSsh(ssh1, "ssh2.internal", 22);
// Verify tunnel.HostKeyFingerprint for Server 2.
success = tunnel.AuthenticatePw("internal-user", "internal-password");

tunnel.DestHostname = "db.internal";
tunnel.DestPort = 5432;
success = tunnel.BeginAccepting(15432);
Shutdown order: Close the second-hop SshTunnel and its clients before disconnecting ssh1.
Arrangement B

Use dynamic SOCKS forwarding and a Socket SSH session

The outer SshTunnel connects to Server A and runs a local SOCKS server. Socket tunnelB connects to that SOCKS listener and negotiates an independent SSH session with Server B.

Dynamic SOCKS and Socket multi-hop arrangement A Socket uses a local SOCKS listener owned by SshTunnel. The second SSH session follows the SOCKS path through Server A and continues to Server B. LOCAL APPLICATION PROCESS Outer SshTunnelSSH session 1 to ADynamic forwarding Local SOCKSlocalhost:1080owned by SshTunnel Socket tunnelBSSH session 2 to BSshOpenTunnel Socket channelapplication byte streamSshNewChannel owns SOCKS5 over loopback REMOTE SYSTEMS SSH Server AFirst-hop serverTerminates SSH session 1Opens connection to B:22Does not terminate SSH 2 SSH Server BSecond-hop serverTerminates SSH session 2Authenticates tunnelBOpens destination channel Destinationtime-c.nist.gov:37 SSH connection 1 SSH connection 2 follows SOCKS → Server A → Server B destination connection

The inner Socket first connects to the local SOCKS listener. The listener forwards the request through Server A to Server B:22. SSH session 2 remains end-to-end between tunnelB and Server B.

SSH session 1 SSH session 2 route

API sequence

Connect and authenticate the outer SshTunnel to Server A.
Set DynamicPortForwarding = true and call BeginAccepting(1080).
Configure tunnelB.Socks* for localhost:1080.
Call SshOpenTunnel, verify Server B's host key, and authenticate independently.
Call SshNewChannel to obtain a destination channel as another Socket byte stream.
Chilkat.SshTunnel outer = new Chilkat.SshTunnel();
bool success = outer.Connect("www.ssh-serverA.com", 22);
// Verify outer.HostKeyFingerprint.
success = outer.AuthenticatePw("loginA", "passwordA");

outer.DynamicPortForwarding = true;
outer.InboundSocksUsername = "chilkat123";
outer.InboundSocksPassword = "password123";
success = outer.BeginAccepting(1080);

Chilkat.Socket tunnelB = new Chilkat.Socket();
tunnelB.SocksHostname = "localhost";
tunnelB.SocksPort = 1080;
tunnelB.SocksVersion = 5;
tunnelB.SocksUsername = "chilkat123";
tunnelB.SocksPassword = "password123";

success = tunnelB.SshOpenTunnel("www.ssh-serverB.com", 22);
// Verify Server B's host key, then authenticate.
success = tunnelB.SshAuthenticatePw("loginB", "passwordB");

Chilkat.Socket channel = new Chilkat.Socket();
success = tunnelB.SshNewChannel("time-c.nist.gov", 37, false, 4000, channel);
Route dependency: The inner SSH session depends on the local SOCKS listener and the outer SSH session. Close inner channels and the inner connection before stopping and closing the outer tunnel.

Comparison

ConceptArrangement AArrangement B
First SSH sessionSshOuter SshTunnel
Second-session transportDirectly borrowed by ConnectThroughSshLocal SOCKS5 connection forwarded through the outer tunnel
Second SSH sessionSshTunnelSocket tunnelB
Application-facing resultStatic or dynamic local forwarding listenerA Socket channel returned by SshNewChannel
SSH identitiesServer 1 and Server 2 have independent host keys and credentials.
At Server 1The outer session ends; the still-encrypted second SSH session is forwarded rather than terminated.
After Server 2The destination connection is ordinary unless the destination protocol adds TLS or another security layer.
Both are genuine multi-hop SSH: In each case the effective route is local application ⇄ SSH Server 1 ⇄ SSH Server 2 ⇄ destination. Only the local implementation mechanism differs.