Sample code for 30+ languages & platforms
Unicode 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 Unicode C Downloads

Unicode C
#include <C_CkSshW.h>
#include <C_CkSocketW.h>

void ChilkatSample(void)
    {
    BOOL success;
    HCkSshW ssh1;
    HCkSshW ssh2;
    HCkSocketW socket;
    BOOL useTls;
    int maxWaitMillisec;
    const wchar_t *responseStatusLine;
    const wchar_t *responseHeaderLine;
    const wchar_t *remainderOfHeader;

    success = FALSE;

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

    ssh1 = CkSshW_Create();

    // Connect directly to the 1st SSH server.
    success = CkSshW_Connect(ssh1,L"serverssh1.com",22);
    if (success != TRUE) {
        wprintf(L"%s\n",CkSshW_lastErrorText(ssh1));
        CkSshW_Dispose(ssh1);
        return;
    }

    // Authenticate using login/password:
    success = CkSshW_AuthenticatePw(ssh1,L"ssh1Login",L"ssh1Password");
    if (success != TRUE) {
        wprintf(L"%s\n",CkSshW_lastErrorText(ssh1));
        CkSshW_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 = CkSshW_Create();
    success = CkSshW_ConnectThroughSsh(ssh2,ssh1,L"serverssh2.com",22);
    if (success != TRUE) {
        wprintf(L"%s\n",CkSshW_lastErrorText(ssh2));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        return;
    }

    // Authenticate with ssh2...
    success = CkSshW_AuthenticatePw(ssh2,L"ssh2Login",L"ssh2Password");
    if (success != TRUE) {
        wprintf(L"%s\n",CkSshW_lastErrorText(ssh2));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        return;
    }

    socket = CkSocketW_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 = CkSocketW_UseSsh(socket,ssh2);
    if (success != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_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 = CkSocketW_Connect(socket,L"www.chilkatsoft.com",443,useTls,maxWaitMillisec);
    if (success != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_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.
    CkSocketW_putStringCharset(socket,L"utf-8");

    // Send an HTTP HEAD request:
    success = CkSocketW_SendString(socket,L"HEAD / HTTP/1.1\r\nHost: www.chilkatsoft.com\r\n\r\n");
    if (success != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_Dispose(socket);
        return;
    }

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

    // Get the 1st response line, which should be "HTTP/1.1 200 OK"
    responseStatusLine = CkSocketW_receiveToCRLF(socket);
    if (CkSocketW_getLastMethodSuccess(socket) != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_Dispose(socket);
        return;
    }

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

    // Now get the 1st line of the response header:
    responseHeaderLine = CkSocketW_receiveToCRLF(socket);
    if (CkSocketW_getLastMethodSuccess(socket) != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_Dispose(socket);
        return;
    }

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

    // Now read the remainder of the response header by reading until a double CRLF is seen:
    remainderOfHeader = CkSocketW_receiveUntilMatch(socket,L"\r\n\r\n");
    if (CkSocketW_getLastMethodSuccess(socket) != TRUE) {
        wprintf(L"%s\n",CkSocketW_lastErrorText(socket));
        CkSshW_Dispose(ssh1);
        CkSshW_Dispose(ssh2);
        CkSocketW_Dispose(socket);
        return;
    }

    wprintf(L"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 = CkSocketW_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.
    CkSshW_Disconnect(ssh2);

    CkSshW_Disconnect(ssh1);


    CkSshW_Dispose(ssh1);
    CkSshW_Dispose(ssh2);
    CkSocketW_Dispose(socket);

    }