Sample code for 30+ languages & platforms
DataFlex

Multi-Hop SSH (SSH Through SSH)

See more SSH Examples

Demonstrates connecting to one SSH server through another: Application => ServerSSH1 => ServerSSH2. The ConnectThroughSsh method tunnels the second connection through the first. The technique chains further, so ServerSSH3 and beyond can be reached the same way.

Background: This is the "jump host" or bastion pattern: a gateway server is reachable from outside, and the machines you actually want are only reachable from inside. Each hop authenticates separately with its own credentials, and the result is an ordinary Ssh object for the far server that happens to be routed through the near one. Any number of connections may be tunneled through a single existing connection, and closing an inner connection leaves the outer one alive for reuse.

Chilkat DataFlex Downloads

DataFlex
Use ChilkatAx-win32.pkg

Procedure Test
    Boolean iSuccess
    Variant vSsh1
    Handle hoSsh1
    String sHostname
    Integer iPort
    String sPassword
    Handle hoSsh2
    String sPassword2
    Integer iChannelNum
    String sTemp1

    Move False To iSuccess

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

    //  Demonstrates connecting to one SSH server through another (SSH through SSH):
    //  
    //      Application => ServerSSH1 => ServerSSH2
    //  
    //  Any number of SSH connections may be tunneled through a single existing SSH connection, and
    //  the technique can be chained further to reach ServerSSH3, ServerSSH4, and so on.

    Get Create (RefClass(cComChilkatSsh)) To hoSsh1
    If (Not(IsComObjectCreated(hoSsh1))) Begin
        Send CreateComObject of hoSsh1
    End

    //  Connect directly to the 1st SSH server.
    Move "jump.example.com" To sHostname
    Move 22 To iPort
    Get ComConnect Of hoSsh1 sHostname iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh1 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  Normally you would not hard-code the password in source.  You should instead obtain it
    //  from an interactive prompt, environment variable, or a secrets vault.
    Move "mySshPassword" To sPassword

    Get ComAuthenticatePw Of hoSsh1 "mySshLogin" sPassword To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh1 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  Connect through the 1st SSH connection to reach the 2nd SSH server.
    Get Create (RefClass(cComChilkatSsh)) To hoSsh2
    If (Not(IsComObjectCreated(hoSsh2))) Begin
        Send CreateComObject of hoSsh2
    End
    Get pvComObject of hoSsh1 to vSsh1
    Get ComConnectThroughSsh Of hoSsh2 vSsh1 "target.example.com" iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  The 2nd server has its own credentials.
    Move "mySshPassword2" To sPassword2
    Get ComAuthenticatePw Of hoSsh2 "mySshLogin2" sPassword2 To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  ssh2 is now connected and authenticated, and can be used exactly as if it were connected
    //  directly.  For example, open a session channel to run commands.
    Get ComOpenSessionChannel Of hoSsh2 To iChannelNum
    If (iChannelNum < 0) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  ... run commands on ssh2 ...

    //  Closing ssh2 closes the tunnel through ssh1.  The ssh1 connection remains alive and may be
    //  reused for more connections.
    Send ComDisconnect To hoSsh2

    Send ComDisconnect To hoSsh1


End_Procedure