-
-
Save Skarlso/34321a230cf0245018288686c9e70b2d to your computer and use it in GitHub Desktop.
| package main | |
| import ( | |
| "bytes" | |
| "fmt" | |
| "io/ioutil" | |
| "log" | |
| "golang.org/x/crypto/ssh" | |
| kh "golang.org/x/crypto/ssh/knownhosts" | |
| ) | |
| func main() { | |
| user := "user" | |
| address := "192.168.0.17" | |
| command := "uptime" | |
| port := "9999" | |
| key, err := ioutil.ReadFile("/Users/user/.ssh/id_rsa") | |
| if err != nil { | |
| log.Fatalf("unable to read private key: %v", err) | |
| } | |
| // Create the Signer for this private key. | |
| signer, err := ssh.ParsePrivateKey(key) | |
| if err != nil { | |
| log.Fatalf("unable to parse private key: %v", err) | |
| } | |
| hostKeyCallback, err := kh.New("/Users/user/.ssh/known_hosts") | |
| if err != nil { | |
| log.Fatal("could not create hostkeycallback function: ", err) | |
| } | |
| config := &ssh.ClientConfig{ | |
| User: user, | |
| Auth: []ssh.AuthMethod{ | |
| // Add in password check here for moar security. | |
| ssh.PublicKeys(signer), | |
| }, | |
| HostKeyCallback: hostKeyCallback, | |
| } | |
| // Connect to the remote server and perform the SSH handshake. | |
| client, err := ssh.Dial("tcp", address+":"+port, config) | |
| if err != nil { | |
| log.Fatalf("unable to connect: %v", err) | |
| } | |
| defer client.Close() | |
| ss, err := client.NewSession() | |
| if err != nil { | |
| log.Fatal("unable to create SSH session: ", err) | |
| } | |
| defer ss.Close() | |
| // Creating the buffer which will hold the remotly executed command's output. | |
| var stdoutBuf bytes.Buffer | |
| ss.Stdout = &stdoutBuf | |
| ss.Run(command) | |
| // Let's print out the result of command. | |
| fmt.Println(stdoutBuf.String()) | |
| } |
@oktayaa Hey!
Right? I don't know why anyone would dismiss checking known_hosts especially since pretty much the defence against MITM attacks.
Of course this could be a lot better with variables, but I'll leave that to the user. :) The point was to demonstrate the check it self. :)
Glad you find it useful!
Does this only work if the hostkey is already added in known_hosts? How would it be possible to write new hosts into the known_hosts file?
Edit:
I used ssh-keyscan github.com > known_hosts and it works quite well. It also already adds all keys from the server which works quite well. Not sure if there would be also a solution to do this in my golang program.
@steffakasid Hey! That's a good call.
Yes, there are a couple solutions out there to do an ssh-keyscan, but basically, you can just do a call with TCP.
Here is a more convoluted example: https://github.com/szuecs/go-ssh-keyscan/blob/master/go-ssh-keyscan.go
And here is one that just does a TCP call and returns the output: http://play.golang.org/p/Lm1FNTnLws
This is the only implementation I could find that actually has known_hosts checks enabled AND can parse hashed hostname in known_hosts. Thanks!
Most github libraries/wrappers either seem to have disabled the check or are using an example from the docs that doesn't consider hashed hostnames/ips.
(I still had a lot of issues to get it going but those turned out to be some sort of duplicate host keys for the ip/host in question) Since ssh itself works fine in that setup, crypto/ssh/knownhosts probably should too.
Might be a tiny bit more useful if you use a variable for 'user' and get env(HOME) to reach known_hosts and id_rsa etc.