-
-
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.