Sample code for 30+ languages & platforms
PureBasic

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