Sample code for 30+ languages & platforms
PureBasic Requires Chilkat v11.0.0+

TCP Socket through SSH Tunnel (Port Forwarding)

See more Socket/SSL/TLS Examples

Demonstrates using Chilkat Socket to communicate to a TCP service through an SSH tunnel. This example will connect to an NIST time server and (using the old Time Protocol (RFC 868)), will read the current GMT time.

Note: This is not necessarily a recommended means for getting the current date/time. The most commonly used time protocol is the Network Time Protocol (RFC-1305). The intent of this example is to show how TCP communications can occur through an SSH tunnel.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkDateTime.pb"
IncludeFile "CkSocket.pb"

Procedure ChilkatExample()

    success.i = 0

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

    tunnel.i = CkSocket::ckCreate()
    If tunnel.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    sshHostname.s = "sftp.example.com"
    sshPort.i = 22

    ;  Connect to an SSH server and establish the SSH tunnel:
    success = CkSocket::ckSshOpenTunnel(tunnel,sshHostname,sshPort)
    If success = 0
        Debug CkSocket::ckLastErrorText(tunnel)
        CkSocket::ckDispose(tunnel)
        ProcedureReturn
    EndIf

    ;  Authenticate with the SSH server via a login/password
    ;  or with a public key.
    ;  This example demonstrates SSH password authentication.
    success = CkSocket::ckSshAuthenticatePw(tunnel,"mySshLogin","mySshPassword")
    If success = 0
        Debug CkSocket::ckLastErrorText(tunnel)
        CkSocket::ckDispose(tunnel)
        ProcedureReturn
    EndIf

    ;  OK, the SSH tunnel is setup.  Now open a channel within the tunnel.
    ;  Once the channel is obtained, the Socket API may
    ;  be used exactly the same as usual, except all communications
    ;  are sent through the channel in the SSH tunnel.
    ;  Any number of channels may be created from the same SSH tunnel.
    ;  Multiple channels may coexist at the same time.

    ;  Connect to an NIST time server and read the current date/time
    maxWaitMs.i = 4000
    useTls.i = 0
    channel.i = CkSocket::ckCreate()
    If channel.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkSocket::ckSshNewChannel(tunnel,"time-c.nist.gov",37,useTls,maxWaitMs,channel)
    If success = 0
        Debug CkSocket::ckLastErrorText(tunnel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        ProcedureReturn
    EndIf

    ;  The time server will send a big-endian 32-bit integer representing
    ;  the number of seconds since since 00:00 (midnight) 1 January 1900 GMT.
    ;  The ReceiveInt32 method will receive a 4-byte integer, but returns
    ;  1 or 0 to indicate success.  If successful, the integer
    ;  is obtained via the ReceivedInt property.
    bigEndian.i = 1
    success = CkSocket::ckReceiveInt32(channel,bigEndian)
    If success = 0
        Debug CkSocket::ckLastErrorText(channel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        ProcedureReturn
    EndIf

    dt.i = CkDateTime::ckCreate()
    If dt.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkDateTime::ckSetFromNtpTime(dt,CkSocket::ckReceivedInt(channel))

    ;  Show the current local date/time
    bLocalTime.i = 1
    Debug "Current local date/time: " + CkDateTime::ckGetAsRfc822(dt,bLocalTime)

    ;  Close the SSH channel.
    success = CkSocket::ckClose(channel,maxWaitMs)
    If success <> 1
        Debug CkSocket::ckLastErrorText(channel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        CkDateTime::ckDispose(dt)
        ProcedureReturn
    EndIf

    ;  It is possible to create a new channel from the existing SSH tunnel for the next connection:
    ;  Any number of channels may be created from the same SSH tunnel.
    ;  Multiple channels may coexist at the same time.
    success = CkSocket::ckSshNewChannel(tunnel,"time-a.nist.gov",37,useTls,maxWaitMs,channel)
    If success = 0
        Debug CkSocket::ckLastErrorText(tunnel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        CkDateTime::ckDispose(dt)
        ProcedureReturn
    EndIf

    ;  Review the LastErrorText to see that the connection was made via the SSH tunnel:
    Debug CkSocket::ckLastErrorText(tunnel)

    ;  Close the connection to time-a.nist.gov.  This is actually closing our channel
    ;  within the SSH tunnel, but keeps the tunnel open for the next port-forwarded connection.
    success = CkSocket::ckClose(channel,maxWaitMs)
    If success <> 1
        Debug CkSocket::ckLastErrorText(channel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        CkDateTime::ckDispose(dt)
        ProcedureReturn
    EndIf

    ;  Finally, close the SSH tunnel.
    success = CkSocket::ckSshCloseTunnel(tunnel)
    If success = 0
        Debug CkSocket::ckLastErrorText(tunnel)
        CkSocket::ckDispose(tunnel)
        CkSocket::ckDispose(channel)
        CkDateTime::ckDispose(dt)
        ProcedureReturn
    EndIf

    Debug "TCP SSH tunneling example completed."


    CkSocket::ckDispose(tunnel)
    CkSocket::ckDispose(channel)
    CkDateTime::ckDispose(dt)


    ProcedureReturn
EndProcedure