Skip to content

Commit

Permalink
much better ssh example
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonWaldherr committed Jun 16, 2024
1 parent 06497da commit 9cea92f
Showing 1 changed file with 82 additions and 51 deletions.
133 changes: 82 additions & 51 deletions non-std-lib/ssh-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,98 +4,129 @@ import (
"flag"
"fmt"
"io/ioutil"
"net"
"os"

"golang.org/x/crypto/ssh"
)

var user string
var host string
var port string
var keyfile string
var (
user string
host string
port string
keyfile string
)

func init() {
flag.StringVar(&user, "u", "root", "SSH user")
flag.StringVar(&host, "h", "example.tld", "Host")
flag.StringVar(&port, "p", "22", "SSH port")
flag.StringVar(&keyfile, "pk", "", "Public key file, e.g.: \"~/.ssh/id_rsa\"")
}

func main() {
flag.StringVar(&user, "u", "root", "ssh user")
flag.StringVar(&host, "h", "example.tld", "host")
flag.StringVar(&port, "p", "22", "ssh port")
flag.StringVar(&keyfile, "pk", "", "public key file, eg.: \"~/.ssh/id_rsa\"")
flag.Parse()

var client *ssh.Client
var session *ssh.Session
var err error

if host == "example.tld" {
fmt.Println("go run ssh-client.go -h example.tld -p 22 -pk /Users/johndoe/.ssh/id_rsa")
fmt.Println("Usage: go run ssh-client.go -h <host> -p <port> -pk <path_to_private_key>")
flag.PrintDefaults()
return
}

var client *ssh.Client
var err error

if keyfile != "" {
client, session, err = connectToHostWithPublickey(user, fmt.Sprintf("%v:%v", host, port), keyfile)
client, err = connectToHostWithPublicKey(user, fmt.Sprintf("%v:%v", host, port), keyfile)
} else {
client, session, err = connectToHost(user, fmt.Sprintf("%v:%v", host, port))
client, err = connectToHost(user, fmt.Sprintf("%v:%v", host, port))
}

if err != nil {
panic(err)
}
out, err := session.CombinedOutput("ls -al")
if err != nil {
panic(err)
fmt.Fprintf(os.Stderr, "Failed to connect: %v\n", err)
return
}
fmt.Println(string(out))
client.Close()
defer client.Close()

runRemoteCommands(client)
}

func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
var pass string
fmt.Print("SSH-Password: ")
fmt.Scanf("%s\n", &pass)
func connectToHost(user, host string) (*ssh.Client, error) {
var password string
fmt.Print("SSH Password: ")
fmt.Scanf("%s\n", &password)

sshConfig := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{ssh.Password(pass)},
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()

client, err := ssh.Dial("tcp", host, sshConfig)
if err != nil {
return nil, nil, err
return nil, err
}

session, err := client.NewSession()
if err != nil {
client.Close()
return nil, nil, err
}

return client, session, nil
return client, nil
}

func connectToHostWithPublickey(user, host, publickeyfile string) (*ssh.Client, *ssh.Session, error) {
key, err := ioutil.ReadFile(publickeyfile)
func connectToHostWithPublicKey(user, host, publicKeyFile string) (*ssh.Client, error) {
key, err := ioutil.ReadFile(publicKeyFile)
if err != nil {
return nil, nil, err
return nil, err
}

signer, err := ssh.ParsePrivateKey(key)
if err != nil {
return nil, nil, err
return nil, err
}
client, err := ssh.Dial("tcp", host, &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
HostKeyCallback: ssh.HostKeyCallback(func(string, net.Addr, ssh.PublicKey) error { return nil }),
})
if client == nil || err != nil {
return nil, nil, err

sshConfig := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}

client, err := ssh.Dial("tcp", host, sshConfig)
if err != nil {
return nil, err
}

return client, nil
}

func runRemoteCommands(client *ssh.Client) {
commands := []string{
"ls -al",
"df -h",
"uptime",
"whoami",
}

for _, cmd := range commands {
output, err := executeRemoteCommand(client, cmd)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to run command '%s': %v\n", cmd, err)
continue
}
fmt.Printf("Output of '%s':\n%s\n", cmd, output)
}
}

func executeRemoteCommand(client *ssh.Client, command string) (string, error) {
session, err := client.NewSession()
if err != nil {
client.Close()
return nil, nil, err
return "", err
}
defer session.Close()

output, err := session.CombinedOutput(command)
if err != nil {
return "", err
}

return client, session, nil
return string(output), nil
}

0 comments on commit 9cea92f

Please sign in to comment.