func sshOnConn(conn net.Conn, h conf.Host) (*ssh.ClientConn, error) { var auths []ssh.ClientAuth if h.Pass != "" { auths = append(auths, ssh.ClientAuthPassword(password(h.Pass))) auths = append(auths, ssh.ClientAuthKeyboardInteractive(challenge(h.Pass))) } if h.Key != "" { k := &keyring{} err := k.loadPEM([]byte(h.Key)) if err != nil { return nil, err } auths = append(auths, ssh.ClientAuthKeyring(k)) } config := &ssh.ClientConfig{ User: h.User, Auth: auths, } debugln("handshake & authenticate") client, err := ssh.Client(conn, config) if err != nil { return nil, err } return client, nil }
func TestSSHD(t *testing.T) { block, _ := pem.Decode([]byte(testClientPrivateKey)) rsakey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) pub, _ := ssh.NewPublicKey(&rsakey.PublicKey) cmd, c, err := startSSHD(ssh.MarshalAuthorizedKey(pub)) if err != nil { t.Fatal(err) } defer cmd.Wait() defer cmd.Process.Kill() u, err := user.Current() if err != nil { t.Fatal(err) } _ = u config := &ssh.ClientConfig{ User: u.Username, Auth: []ssh.ClientAuth{ssh.ClientAuthKeyring(&keyring{rsakey})}, } client, err := ssh.Client(c, config) if err != nil { t.Fatal(err) } sess, err := client.NewSession() if err != nil { t.Fatal(err) } out, err := sess.Output("echo hello") if err != nil { t.Fatal(err) } if string(out) != "hello\n" { t.Fatalf("out = %q want %q", string(out), "hello\n") } }
func remoteCmdOutput(username, hostname, privateKey, cmd string) []byte { block, _ := pem.Decode([]byte(privateKey)) rsakey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) clientKey := &keychain{rsakey} clientConfig := &ssh.ClientConfig{ User: username, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(clientKey), }, } client, err := ssh.Dial("tcp", hostname, clientConfig) if err != nil { log.Println("ERROR: Failed to dial: " + err.Error()) return []byte{} } session, err := client.NewSession() if err != nil { log.Println("ERROR: Failed to create session: " + err.Error()) return []byte{} } defer session.Close() output, err := session.Output(cmd) if err != nil { log.Printf("ERROR: Failed to run cmd on host %s: %s", hostname, err.Error()) return []byte{} } return output }
func getConn(host *host.Host) (*ssh.ClientConn, error) { hostkey := host.Id if con, ok := conns[hostkey]; ok { return con, nil } if host.User == "" { return nil, fmt.Errorf("user not set") } for _, keyfile := range host.Keyfiles { // TODO add key to global keyring, ok? if err := keys.loadPEM(keyfile); err != nil { return nil, fmt.Errorf("unable to load %s: %v", keyfile, err) } } config := &ssh.ClientConfig{ User: host.User, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keys), }, } conn, err := ssh.Dial("tcp", host.ConnStr(), config) if err != nil { return nil, fmt.Errorf("unable to connect to %s: %v", host, err) } conns[hostkey] = conn return conn, nil }
func (conn *Conn) Connect() error { var auth []ssh.ClientAuth // only load a private key if requested ~/.ssh/id_rsa is _not_ loaded automatically // ssh-agent should be the usual path if conn.Key != "" { kr := new(keyring) if err := kr.loadPEM(conn.Key); err != nil { log.Fatal("Couldn't load specified private key '", conn.Key, "': ", err) } auth = append(auth, ssh.ClientAuthKeyring(kr)) } agentSock := os.Getenv("SSH_AUTH_SOCK") // ssh-agent support, might need to reuse this in the future? // how bad are 100's or 1000's of connections to the agent? if agentSock != "" { sock, err := net.Dial("unix", agentSock) if err != nil { log.Fatal("Could not connect to SSH_AUTH_SOCK. Is ssh-agent running?") } agent := ssh.NewAgentClient(sock) auth = append(auth, ssh.ClientAuthAgent(agent)) } conn.config = &ssh.ClientConfig{ User: conn.User, Auth: auth, } return conn.connect() }
func TestSshCmd(t *testing.T) { kc := new(keychain) kc.load() config := &ssh.ClientConfig{ User: os.Getenv("USER"), Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(kc), }, } client, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { panic("Failed to dial: " + err.Error()) } // Each ClientConn can support multiple interactive sessions, // represented by a Session. session, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer session.Close() // Once a Session is created, you can execute a single command on // the remote side using the Run method. var b bytes.Buffer session.Stdout = &b if err := session.Run("/usr/bin/whoami"); err != nil { panic("Failed to run: " + err.Error()) } log.Printf("Result of running whoami via ssh: %s\n", b) //fmt.Println(b.String()) }
func ConnectAndForward(addresses Addresses) { // Load id_rsa file keychain := new(keyChain) err := keychain.loadPEM(addresses.PrivateKeyPathString) if err != nil { log.Fatalf("Cannot load key: %v", err) } // Setup SSH config (type *ssh.ClientConfig) config := &ssh.ClientConfig{ User: addresses.SSHUserString, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keychain), }, } // Setup localListener (type net.Listener) localListener, err := net.Listen("tcp", addresses.LocalAddrString) if err != nil { log.Fatalf("net.Listen failed: %v", err) } defer localListener.Close() for { // Setup localConn (type net.Conn) localConn, err := localListener.Accept() if err != nil { log.Fatalf("listen.Accept failed: %v", err) } defer localConn.Close() go forward(localConn, config, addresses.ServerAddrString, addresses.RemoteAddrString) } }
func main() { logger = log.New(os.Stdout, "wam: ", log.LstdFlags|log.Lshortfile) logger.Println("sandhog") configData, err := loadConfig() if err != nil { printUsage() logger.Fatalln(err) } keyring, err := LoadKeyring(configData.keyPath) if err != nil { logger.Fatalln(err) } logger.Printf("loaded keyring: %s", keyring) sshConfig := &ssh.ClientConfig{ User: "******", Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keyring), }, } logger.Printf("created SSH client config: %s", sshConfig) // Dial your ssh server. logger.Println("connecting") conn, err := ssh.Dial("tcp", "localhost:22", sshConfig) if err != nil { logger.Fatalf("unable to connect: %s\n", err) } defer conn.Close() logger.Println("connected!") // Request the remote side to open port 8080 on all interfaces. // When they remoteListenEndpoint := fmt.Sprintf("127.0.0.1:%d", configData.remotePort) logger.Printf("requesting remote host listen on: %s\n", remoteListenEndpoint) listener, err := conn.Listen("tcp", remoteListenEndpoint) if err != nil { log.Fatalf("unable to register tcp forward: %s", err) } defer listener.Close() logger.Printf("remote host listening on %s\n", remoteListenEndpoint) for { conn, err := listener.Accept() if err != nil { logger.Println(err) break } go handleConn(conn, *configData) } // Serve HTTP with your SSH server acting as a reverse proxy. http.Serve(listener, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { fmt.Fprintf(resp, "Hello world!\n") })) }
func (this *Handel) check() (err error) { if this.auth == nil { keys := new(keychain) if err = keys.LoadPEM(this.PrivateKey); err != nil { return } this.auth = &ssh.ClientConfig{ User: this.User, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keys), }, } } if this.Port == "" { this.Port = SSH_PORT } if this.client == nil { this.client, err = ssh.Dial("tcp", this.Host+":"+this.Port, this.auth) if err != nil { return } } if this.session == nil { this.session, err = this.client.NewSession() if err != nil { return } } //stdin if this.FileIn == "" { this.session.Stdin = os.Stdin } else if fd, err := os.Open(this.FileIn); err == nil { this.session.Stdin = fd } else { return errors.New("process config error : bad input file : " + err.Error()) } //stdout if this.FileOut == "" { this.session.Stdout = os.Stdout } else if fd, err := os.OpenFile(this.FileOut, os.O_WRONLY|os.O_CREATE, 0666); err == nil { this.session.Stdout = fd } else { return errors.New("process config error : bad output file : " + err.Error()) } //stderr if this.FileErr == "" { this.session.Stderr = os.Stderr } else if fd, err := os.OpenFile(this.FileErr, os.O_WRONLY|os.O_CREATE, 0666); err == nil { this.session.Stderr = fd } else { return errors.New("process config error : bad error file : " + err.Error()) } return }
func clientConfig() *ssh.ClientConfig { kc := new(keychain) kc.keys = append(kc.keys, rsakey) config := &ssh.ClientConfig{ User: username(), Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(kc), }, } return config }
func NewClient(user string, addr string, keys *Keychain) *Client { return &Client{ Addr: addr, Config: &ssh.ClientConfig{ User: user, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keys), }, }, } }
func clientConfig() *ssh.ClientConfig { keyChecker := storedHostKey{} keyChecker.Add("ssh-rsa", serializedHostKey) kc := new(keychain) kc.keys = append(kc.keys, rsakey) config := &ssh.ClientConfig{ User: username(), Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(kc), }, HostKeyChecker: &keyChecker, } return config }
func clientConfig() *ssh.ClientConfig { keyChecker := storedHostKey{} keyChecker.Add(hostKey.PublicKey()) kc := new(keychain) kc.keys = append(kc.keys, privateKey) config := &ssh.ClientConfig{ User: username(), Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(kc), }, HostKeyChecker: &keyChecker, } return config }
// sshConfig returns the ssh configuration. func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { config := state.Get("config").(*Config) privateKey := state.Get("ssh_private_key").(string) keyring := new(ssh.SimpleKeychain) if err := keyring.AddPEMKey(privateKey); err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } sshConfig := &gossh.ClientConfig{ User: config.SSHUsername, Auth: []gossh.ClientAuth{gossh.ClientAuthKeyring(keyring)}, } return sshConfig, nil }
func sshConfig(state map[string]interface{}) (*gossh.ClientConfig, error) { config := state["config"].(config) privateKey := state["privateKey"].(string) keyring := new(ssh.SimpleKeychain) if err := keyring.AddPEMKey(privateKey); err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } return &gossh.ClientConfig{ User: config.SSHUsername, Auth: []gossh.ClientAuth{ gossh.ClientAuthKeyring(keyring), }, }, nil }
func (ss *ScpStorage) Connect() error { var err error clientConfig := &ssh.ClientConfig{ User: ss.User, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(ss.Keychain), }, } ss.connexion, err = ssh.Dial("tcp", ss.Endpoint, clientConfig) if err != nil { return fmt.Errorf("Failed to dial: %s", err.Error()) } return nil }
// SSHConfig returns a function that can be used for the SSH communicator // config for connecting to the instance created over SSH using the generated // private key. func SSHConfig(username string) func(multistep.StateBag) (*gossh.ClientConfig, error) { return func(state multistep.StateBag) (*gossh.ClientConfig, error) { privateKey := state.Get("privateKey").(string) keyring := new(ssh.SimpleKeychain) if err := keyring.AddPEMKey(privateKey); err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } return &gossh.ClientConfig{ User: username, Auth: []gossh.ClientAuth{ gossh.ClientAuthKeyring(keyring), }, }, nil } }
// Dial a hostname, intelligently using your local ssh settings to do so func Dial(hostname string) (*ssh.ClientConn, error) { options := []configFileOption{} f, err := os.Open(filepath.Join(homeDir(), ".ssh", "config")) if err == nil { defer f.Close() cfg, err := parseConfigFile(f) if err == nil { options = cfg.getOptions(hostname) } else { log.Println("[ssh]", "[error]", err) } } else { log.Println("[ssh]", "[error]", err) } port := 22 username := getUserName(options) for _, kv := range options { switch strings.ToLower(kv.key) { case "hostname": hostname = kv.value case "port": port, _ = strconv.Atoi(kv.value) } } auths := []ssh.ClientAuth{} for _, kv := range options { switch strings.ToLower(kv.key) { case "identityfile": keychain, err := GetKeyChain(toAbsolute(hostname, username, kv.value)) if err == nil { auths = append(auths, ssh.ClientAuthKeyring(keychain)) } } } log.Println("[ssh]", "dialing", fmt.Sprint(username+"@"+hostname, port)) return ssh.Dial("tcp", fmt.Sprint(hostname, ":", port), &ssh.ClientConfig{ User: username, Auth: auths, }) }
func makeKeyring() { signers := []ssh.Signer{} keys := []string{os.Getenv("HOME") + "/.ssh/id_rsa", os.Getenv("HOME") + "/.ssh/id_dsa"} for _, keyname := range keys { signer, err := makeSigner(keyname) if err == nil { signers = append(signers, signer) } } if len(signers) == 0 { haveKeyring = false } else { haveKeyring = true keyring = ssh.ClientAuthKeyring(&SignerContainer{signers}) } }
// Reads an OpenSSH key and provides it as a ssh.ClientAuth. func OpenSshClientAuth(path string) (ssh.ClientAuth, error) { privateKey, err := ioutil.ReadFile(path) if err != nil { return nil, err } block, _ := pem.Decode(privateKey) if block == nil { return nil, fmt.Errorf(`No key data found in PEM file "%s"`, path) } rsakey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } clientKey := &keychain{rsakey} return ssh.ClientAuthKeyring(clientKey), nil }
func (c *SSHClient) connect() error { if !c.Connected { config := &ssh.ClientConfig{ User: c.User, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(c.ClientKeychain), }, } conn, err := ssh.Dial("tcp", c.Host, config) // defer conn.Close() if err != nil { return err } log.Println("[Info] connected to " + c.Host) c.Connection = conn c.Connected = true } return nil }
func ConnectToSsh(username string, keyfile string, server string) (*ssh.Session, error) { k := new(keychain) k.loadPEM(keyfile) config := &ssh.ClientConfig{ User: username, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(k), }, } client, err := ssh.Dial("tcp", server, config) if err != nil { panic("Failed to dial: " + err.Error()) } session, err := client.NewSession() if err != nil { return nil, err } return session, nil }
func GetSSHConn(server string, username string, pemFile string) *ssh.ClientConn { clientKeychain := new(keychain) err := clientKeychain.loadPEM(pemFile) if err != nil { panic("Cannot load PEM File: " + err.Error()) } config := &ssh.ClientConfig{ User: username, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(clientKeychain), }, } client, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", server), config) if err != nil { panic(err) } return client }
func main() { // Decode and parse our key block, _ := pem.Decode([]byte(clientPrivateKey)) privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) // Add it to the keychain clientKeychain := new(keychain) clientKeychain.keys = append(clientKeychain.keys, privateKey) // Create our client config with key-based auth config := &ssh.ClientConfig{ User: "******", Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(clientKeychain), }, } // Connect client, err := ssh.Dial("tcp", "127.0.0.1:22", config) if err != nil { panic("Failed to dial: " + err.Error()) } // Create a new session session, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer session.Close() // Execute command var b bytes.Buffer session.Stdout = &b if err := session.Run("/bin/whoami"); err != nil { panic("Failed to run: " + err.Error()) } fmt.Print(b.String()) }
/* real */ func main() { k := new(keychain) err := k.loadPEM(*sshkey) if err != nil { fmt.Println(err) } config := &ssh.ClientConfig{ User: *sshuser, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(k), }, } go run_cmd(*sshhost+":22", "/usr/bin/w", config) go run_cmd(*sshhost+":22", "/usr/bin/whoami", config) output := <-outputs fmt.Println(output) output = <-outputs fmt.Println(output) }
func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { config := state.Get("config").(*config) auth := []gossh.ClientAuth{ gossh.ClientAuthPassword(ssh.Password(config.SSHPassword)), gossh.ClientAuthKeyboardInteractive( ssh.PasswordKeyboardInteractive(config.SSHPassword)), } if config.SSHKeyPath != "" { keyring, err := sshKeyToKeyring(config.SSHKeyPath) if err != nil { return nil, err } auth = append(auth, gossh.ClientAuthKeyring(keyring)) } return &gossh.ClientConfig{ User: config.SSHUser, Auth: auth, }, nil }
func (s *server) Dial() *ssh.ClientConn { s.cmd = exec.Command("sshd", "-f", s.configfile, "-i") stdin, err := s.cmd.StdinPipe() if err != nil { s.t.Fatal(err) } stdout, err := s.cmd.StdoutPipe() if err != nil { s.t.Fatal(err) } s.cmd.Stderr = os.Stderr err = s.cmd.Start() if err != nil { s.Shutdown() s.t.Fatal(err) } user, err := user.Current() if err != nil { s.Shutdown() s.t.Fatal(err) } kc := new(keychain) kc.keys = append(kc.keys, rsakey) config := &ssh.ClientConfig{ User: user.Username, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(kc), }, } conn, err := ssh.Client(&client{stdin, stdout}, config) if err != nil { s.Shutdown() s.t.Fatal(err) } return conn }
func (c *goCryptoCommand) ensureSession() (*ssh.Session, error) { if c.sess != nil { return c.sess, nil } if len(c.signers) == 0 { return nil, fmt.Errorf("no private keys available") } if c.user == "" { currentUser, err := user.Current() if err != nil { return nil, fmt.Errorf("getting current user: %v", err) } c.user = currentUser.Username } config := &ssh.ClientConfig{ User: c.user, Auth: []ssh.ClientAuth{ ssh.ClientAuthKeyring(keyring{c.signers}), }, } conn, err := sshDialWithProxy(c.addr, c.proxyCommand, config) if err != nil { return nil, err } sess, err := conn.NewSession() if err != nil { conn.Close() return nil, err } c.conn = conn c.sess = sess c.sess.Stdin = c.stdin c.sess.Stdout = c.stdout c.sess.Stderr = c.stderr return sess, nil }
func (s *stepConnectSSH) Run(state map[string]interface{}) multistep.StepAction { config := state["config"].(config) privateKey := state["privateKey"].(string) ui := state["ui"].(packer.Ui) ipAddress := state["droplet_ip"] // Build the keyring for authentication. This stores the private key // we'll use to authenticate. keyring := &ssh.SimpleKeychain{} err := keyring.AddPEMKey(privateKey) if err != nil { err := fmt.Errorf("Error setting up SSH config: %s", err) state["error"] = err ui.Error(err.Error()) return multistep.ActionHalt } connFunc := ssh.ConnectFunc( "tcp", fmt.Sprintf("%s:%d", ipAddress, config.SSHPort), 5*time.Minute) // Build the actual SSH client configuration sshConfig := &ssh.Config{ Connection: connFunc, SSHConfig: &gossh.ClientConfig{ User: config.SSHUsername, Auth: []gossh.ClientAuth{ gossh.ClientAuthKeyring(keyring), }, }, } // Start trying to connect to SSH connected := make(chan error, 1) connectQuit := make(chan bool, 1) defer func() { connectQuit <- true }() var comm packer.Communicator go func() { ui.Say("Connecting to the droplet via SSH...") attempts := 0 handshakeAttempts := 0 for { select { case <-connectQuit: return default: } // A brief sleep so we're not being overly zealous attempting // to connect to the instance. time.Sleep(500 * time.Millisecond) attempts += 1 nc, err := connFunc() if err != nil { continue } nc.Close() log.Println("TCP connection made. Attempting SSH handshake.") comm, err = ssh.New(sshConfig) if err == nil { log.Println("Connected to SSH!") break } handshakeAttempts += 1 log.Printf("SSH handshake error: %s", err) if handshakeAttempts > 5 { connected <- err return } } connected <- nil }() log.Printf("Waiting up to %s for SSH connection", config.sshTimeout) timeout := time.After(config.sshTimeout) ConnectWaitLoop: for { select { case err := <-connected: if err != nil { err := fmt.Errorf("Error connecting to SSH: %s", err) state["error"] = err ui.Error(err.Error()) return multistep.ActionHalt } // We connected. Just break the loop. break ConnectWaitLoop case <-timeout: err := errors.New("Timeout waiting for SSH to become available.") state["error"] = err ui.Error(err.Error()) return multistep.ActionHalt case <-time.After(1 * time.Second): if _, ok := state[multistep.StateCancelled]; ok { log.Println("Interrupt detected, quitting waiting for SSH.") return multistep.ActionHalt } } } // Set the communicator on the state bag so it can be used later s.comm = comm state["communicator"] = comm return multistep.ActionContinue }
// This blocks until SSH becomes available, and sends the communicator // on the given channel. func (s *stepConnectSSH) waitForSSH(state map[string]interface{}) (packer.Communicator, error) { config := state["config"].(config) instance := state["instance"].(*ec2.Instance) privateKey := state["privateKey"].(string) ui := state["ui"].(packer.Ui) // Build the keyring for authentication. This stores the private key // we'll use to authenticate. keyring := &ssh.SimpleKeychain{} err := keyring.AddPEMKey(privateKey) if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } // Create the function that will be used to create the connection connFunc := ssh.ConnectFunc( "tcp", fmt.Sprintf("%s:%d", instance.DNSName, config.SSHPort), 5*time.Minute) ui.Say("Waiting for SSH to become available...") var comm packer.Communicator for { time.Sleep(5 * time.Second) if s.cancel { log.Println("SSH wait cancelled. Exiting loop.") return nil, errors.New("SSH wait cancelled") } // First just attempt a normal TCP connection that we close right // away. We just test this in order to wait for the TCP port to be ready. nc, err := connFunc() if err != nil { log.Printf("TCP connection to SSH ip/port failed: %s", err) continue } nc.Close() // Build the configuration to connect to SSH config := &ssh.Config{ Connection: connFunc, SSHConfig: &gossh.ClientConfig{ User: config.SSHUsername, Auth: []gossh.ClientAuth{ gossh.ClientAuthKeyring(keyring), }, }, } sshConnectSuccess := make(chan bool, 1) go func() { comm, err = ssh.New(config) if err != nil { log.Printf("SSH connection fail: %s", err) sshConnectSuccess <- false return } sshConnectSuccess <- true }() select { case success := <-sshConnectSuccess: if !success { continue } case <-time.After(5 * time.Second): log.Printf("SSH handshake timeout. Trying again.") continue } ui.Say("Connected via SSH!") break } return comm, nil }