gliderlabs / ssh

Easy SSH servers in Golang
https://godoc.org/github.com/gliderlabs/ssh
BSD 3-Clause "New" or "Revised" License
3.67k stars 442 forks source link

Using ForwardAgentConnections for creating a "jump host" #207

Closed antonmedv closed 1 year ago

antonmedv commented 1 year ago

Hello!

Thanks for your awesome library! Really appreciate your work.

I have a question: is it possible to create a "jump host" using your library and crypto/ssh client?

[User machine]  --->  [gliderlabs/ssh]  --->   [Another OpenSSH server]

Thanks!

antonmedv commented 1 year ago

Looks like I figured it out:

package main

import (
    "io"
    "log"
    "net"
    "os"

    "github.com/gliderlabs/ssh"
    . "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/agent"
)

func main() {
    ssh.Handle(func(s ssh.Session) {
        if !ssh.AgentRequested(s) {
            s.Write([]byte("no agent forwarding\n"))
            return
        }
        l, err := ssh.NewAgentListener()
        if err != nil {
            log.Fatal(err)
        }
        defer l.Close()
        go ssh.ForwardAgentConnections(l, s)

        // Get a connection to the local SSH agent
        conn, err := net.Dial("unix", l.Addr().String())
        if err != nil {
            panic(err)
        }

        // Create an agent from the connection
        sshAgent := agent.NewClient(conn)

        // Define the client configuration
        config := &ClientConfig{
            User: "root", // Replace with your username
            Auth: []AuthMethod{
                // Use the agent for authentication
                PublicKeysCallback(sshAgent.Signers),
            },
            // This callback is used for server verification.
            // In a real application, you might want to use something stricter
            HostKeyCallback: InsecureIgnoreHostKey(),
        }

        // Connect to the remote server
        sshClient, err := Dial("tcp", "", config)
        if err != nil {
            panic(err)
        }

        // Create a session
        session, err := sshClient.NewSession()
        if err != nil {
            panic(err)
        }
        defer session.Close()

        // Set up the agent forwarding
        err = agent.RequestAgentForwarding(session)
        if err != nil {
            panic(err)
        }

        // You can now execute a command or do something with the session
        var b []byte
        b, err = session.CombinedOutput("ip route")
        if err != nil {
            panic(err)
        }
        io.WriteString(os.Stdout, string(b))
    })

    log.Println("starting ssh server on port 2222...")
    log.Fatal(ssh.ListenAndServe(":2222", nil))
}