Sample code for 30+ languages & platforms
C

TCP or TLS over Multiple Hop SSH to Remote Server

See more Socket/SSL/TLS Examples

Demonstrates how to use the Chilkat Socket API to connect to a remote server (using TCP or TLS) tunneled through mulitple-hop SSH. The scheme looks like this:
Application => ServerSSH1 => ServerSSH2 => DestinationServer

The ConnectThroughSsh and UseSsh methods are added in Chilkat version 9.5.0.55 to accomplish this task.

Chilkat C Downloads

C
#include <C_CkSsh.h>
#include <C_CkSocket.h>

void ChilkatSample(void)
    {
    BOOL success;
    HCkSsh ssh1;
    HCkSsh ssh2;
    HCkSocket socket;
    BOOL useTls;
    int maxWaitMillisec;
    const char *responseStatusLine;
    const char *responseHeaderLine;
    const char *remainderOfHeader;

    success = FALSE;

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    ssh1 = CkSsh_Create();

    // Connect directly to the 1st SSH server.
    success = CkSsh_Connect(ssh1,"serverssh1.com",22);
    if (success != TRUE) {
        printf("%s\n",CkSsh_lastErrorText(ssh1));
        CkSsh_Dispose(ssh1);
        return;
    }

    // Authenticate using login/password:
    success = CkSsh_AuthenticatePw(ssh1,"ssh1Login","ssh1Password");
    if (success != TRUE) {
        printf("%s\n",CkSsh_lastErrorText(ssh1));
        CkSsh_Dispose(ssh1);
        return;
    }

    // Connect through the 1st SSH connection to reach a 2nd SSH server.
    // Note: Any number of SSH connections may be simultaneously tunneled through a single
    // existing SSH connection.
    ssh2 = CkSsh_Create();
    success = CkSsh_ConnectThroughSsh(ssh2,ssh1,"serverssh2.com",22);
    if (success != TRUE) {
        printf("%s\n",CkSsh_lastErrorText(ssh2));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        return;
    }

    // Authenticate with ssh2...
    success = CkSsh_AuthenticatePw(ssh2,"ssh2Login","ssh2Password");
    if (success != TRUE) {
        printf("%s\n",CkSsh_lastErrorText(ssh2));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        return;
    }

    socket = CkSocket_Create();

    // Tell the socket object to connect to our destination server though the ssh2 tunnel (which itself is routed through ssh1).
    // The connection looks like this:  ApplicationSocket(TLS) => ServerSSH1 => ServerSSH2 => DestinationServer
    success = CkSocket_UseSsh(socket,ssh2);
    if (success != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    // Connect using TLS to www.chilkatsoft.com
    // We could also tunnel a bare TCP connection by specifying port 80 with useTls = FALSE.
    useTls = TRUE;
    maxWaitMillisec = 20000;
    success = CkSocket_Connect(socket,"www.chilkatsoft.com",443,useTls,maxWaitMillisec);
    if (success != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    // Once the multiple hop SSH tunneled connection is setup,  the socket programming
    // is identical to the normal case where we have a direct connection.

    // Tell the socket object that all text is to be sent in the utf-8 encoding,
    // and the text received is assumed to be utf-8.
    CkSocket_putStringCharset(socket,"utf-8");

    // Send an HTTP HEAD request:
    success = CkSocket_SendString(socket,"HEAD / HTTP/1.1\r\nHost: www.chilkatsoft.com\r\n\r\n");
    if (success != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    // Wait a maximum of 4 seconds while no data is forthcoming:
    CkSocket_putMaxReadIdleMs(socket,4000);

    // Get the 1st response line, which should be "HTTP/1.1 200 OK"
    responseStatusLine = CkSocket_receiveToCRLF(socket);
    if (CkSocket_getLastMethodSuccess(socket) != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    printf("StatusLine: %s\n",responseStatusLine);

    // Now get the 1st line of the response header:
    responseHeaderLine = CkSocket_receiveToCRLF(socket);
    if (CkSocket_getLastMethodSuccess(socket) != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    printf("HeaderLine: %s\n",responseHeaderLine);

    // Now read the remainder of the response header by reading until a double CRLF is seen:
    remainderOfHeader = CkSocket_receiveUntilMatch(socket,"\r\n\r\n");
    if (CkSocket_getLastMethodSuccess(socket) != TRUE) {
        printf("%s\n",CkSocket_lastErrorText(socket));
        CkSsh_Dispose(ssh1);
        CkSsh_Dispose(ssh2);
        CkSocket_Dispose(socket);
        return;
    }

    printf("Remainder: %s\n",remainderOfHeader);

    // Close the connection with the server.  This closes the tunnel through ssh2.
    // Wait a max of 20 seconds (20000 millsec)
    success = CkSocket_Close(socket,20000);

    // Close the connection with ssh2.  (This closes the the tunnel through ssh1.)
    // The connection with ssh1 is still alive, and may be used for more connections.
    CkSsh_Disconnect(ssh2);

    CkSsh_Disconnect(ssh1);


    CkSsh_Dispose(ssh1);
    CkSsh_Dispose(ssh2);
    CkSocket_Dispose(socket);

    }