func prepareHostControlPath(host, gateway *config.Host) error { controlPathDir := path.Dir(os.ExpandEnv(strings.Replace(host.ControlPath, "~", "$HOME", -1))) gatewayControlPath := path.Join(controlPathDir, gateway.Name()) if config.BoolVal(host.ControlMasterMkdir) { return os.MkdirAll(gatewayControlPath, 0700) } return nil }
func proxyGo(host *config.Host) error { if host.Host == "" { host.Host = host.Name } if len(host.ResolveNameservers) > 0 { logrus.Debugf("Resolving host: '%s' using nameservers %s", host.Host, host.ResolveNameservers) // FIXME: resolve using custom dns server results, err := net.LookupAddr(host.Host) if err != nil { return err } if len(results) > 0 { host.Host = results[0] } logrus.Debugf("Resolved host is: %s", host.Host) } if host.ResolveCommand != "" { command := commandApplyHost(host.ResolveCommand, host) logrus.Debugf("Resolving host: '%s' using command: '%s'", host.Host, command) args, err := shlex.Split(command) if err != nil { return err } out, err := exec.Command(args[0], args[1:]...).Output() if err != nil { return err } host.Host = strings.TrimSpace(fmt.Sprintf("%s", out)) logrus.Debugf("Resolved host is: %s", host.Host) } logrus.Debugf("Connecting to %s:%d", host.Host, host.Port) conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host.Host, host.Port)) if err != nil { return err } defer conn.Close() logrus.Debugf("Connected to %s:%d", host.Host, host.Port) // Create Stdio pipes c1 := readAndWrite(conn, os.Stdout) c2 := readAndWrite(os.Stdin, conn) select { case err = <-c1: case err = <-c2: } if err != nil { return err } return nil }
func proxyCommand(host *config.Host, command string) error { command = host.ExpandString(command) args, err := shlex.Split(command) Logger.Debugf("ProxyCommand: %s", command) if err != nil { return err } spawn := exec.Command(args[0], args[1:]...) spawn.Stdout = os.Stdout spawn.Stdin = os.Stdin spawn.Stderr = os.Stderr return spawn.Run() }
func proxy(host *config.Host, conf *config.Config, dryRun bool) error { if len(host.Gateways) > 0 { Logger.Debugf("Trying gateways: %s", host.Gateways) for _, gateway := range host.Gateways { if gateway == "direct" { err := proxyDirect(host, dryRun) if err != nil { Logger.Errorf("Failed to use 'direct' connection: %v", err) } } else { hostCopy := host.Clone() gatewayHost := conf.GetGatewaySafe(gateway) err := prepareHostControlPath(hostCopy, gatewayHost) if err != nil { return err } // FIXME: dynamically add "-v" flags var command string // FIXME: detect ssh client version and use netcat if too old // for now, the workaround is to configure the ProxyCommand of the host to "nc %h %p" if err = hostPrepare(hostCopy); err != nil { return err } if hostCopy.ProxyCommand != "" { command = "ssh %name -- " + hostCopy.ExpandString(hostCopy.ProxyCommand) } else { command = hostCopy.ExpandString("ssh -W %h:%p ") + "%name" } Logger.Debugf("Using gateway '%s': %s", gateway, command) err = proxyCommand(gatewayHost, command, dryRun) if err == nil { return nil } Logger.Errorf("Cannot use gateway '%s': %v", gateway, err) } } return fmt.Errorf("No such available gateway") } Logger.Debugf("Connecting without gateway") return proxyDirect(host, dryRun) }
func proxyCommand(host *config.Host, command string, dryRun bool) error { command = host.ExpandString(command) Logger.Debugf("ProxyCommand: %s", command) args, err := shlex.Split(command) if err != nil { return err } if dryRun { return fmt.Errorf("dry-run: Execute %s", args) } spawn := exec.Command(args[0], args[1:]...) spawn.Stdout = os.Stdout spawn.Stdin = os.Stdin spawn.Stderr = os.Stderr return spawn.Run() }
func proxy(host *config.Host, conf *config.Config, dryRun bool) error { if len(host.Gateways) > 0 { Logger.Debugf("Trying gateways: %s", host.Gateways) for _, gateway := range host.Gateways { if gateway == "direct" { err := proxyDirect(host, dryRun) if err != nil { Logger.Errorf("Failed to use 'direct' connection: %v", err) } } else { hostCopy := host.Clone() gatewayHost := conf.GetGatewaySafe(gateway) err := prepareHostControlPath(hostCopy, gatewayHost) if err != nil { return err } if hostCopy.ProxyCommand == "" { hostCopy.ProxyCommand = "nc %h %p" } // FIXME: dynamically add "-v" flags if err = hostPrepare(hostCopy); err != nil { return err } command := "ssh %name -- " + hostCopy.ExpandString(hostCopy.ProxyCommand) Logger.Debugf("Using gateway '%s': %s", gateway, command) err = proxyCommand(gatewayHost, command, dryRun) if err == nil { return nil } Logger.Errorf("Cannot use gateway '%s': %v", gateway, err) } } return fmt.Errorf("No such available gateway") } Logger.Debugf("Connecting without gateway") return proxyDirect(host, dryRun) }
func hostPrepare(host *config.Host) error { if host.HostName == "" { host.HostName = host.Name() } if len(host.ResolveNameservers) > 0 { Logger.Debugf("Resolving host: '%s' using nameservers %s", host.HostName, host.ResolveNameservers) // FIXME: resolve using custom dns server results, err := net.LookupAddr(host.HostName) if err != nil { return err } if len(results) > 0 { host.HostName = results[0] } Logger.Debugf("Resolved host is: %s", host.HostName) } if host.ResolveCommand != "" { command := host.ExpandString(host.ResolveCommand) Logger.Debugf("Resolving host: %q using command: %q", host.HostName, command) args, err := shlex.Split(command) if err != nil { return err } cmd := exec.Command(args[0], args[1:]...) var stdout bytes.Buffer var stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { Logger.Errorf("ResolveCommand failed: %s", stderr.String()) return err } host.HostName = strings.TrimSpace(fmt.Sprintf("%s", stdout.String())) Logger.Debugf("Resolved host is: %s", host.HostName) } return nil }
func proxy(host *config.Host, conf *config.Config) error { if len(host.Gateways) > 0 { logrus.Debugf("Trying gateways: %s", host.Gateways) for _, gateway := range host.Gateways { if gateway == "direct" { err := proxyDirect(host) if err != nil { logrus.Errorf("Failed to use 'direct' connection") } } else { gatewayHost := conf.GetGatewaySafe(gateway) err := prepareHostControlPath(host, gatewayHost) if err != nil { return err } if host.ProxyCommand == "" { host.ProxyCommand = "nc %h %p" } command := "ssh %name -- " + commandApplyHost(host.ProxyCommand, host) logrus.Debugf("Using gateway '%s': %s", gateway, command) err = proxyCommand(gatewayHost, command) if err == nil { return nil } logrus.Errorf("Cannot use gateway '%s': %v", gateway, err) } } return fmt.Errorf("No such available gateway") } logrus.Debugf("Connecting without gateway") return proxyDirect(host) }
func hostPrepare(host *config.Host) error { if host.HostName == "" { host.HostName = host.Name() } if len(host.ResolveNameservers) > 0 { Logger.Debugf("Resolving host: '%s' using nameservers %s", host.HostName, host.ResolveNameservers) // FIXME: resolve using custom dns server results, err := net.LookupAddr(host.HostName) if err != nil { return err } if len(results) > 0 { host.HostName = results[0] } Logger.Debugf("Resolved host is: %s", host.HostName) } if host.ResolveCommand != "" { command := host.ExpandString(host.ResolveCommand) Logger.Debugf("Resolving host: %q using command: %q", host.HostName, command) args, err := shlex.Split(command) if err != nil { return err } out, err := exec.Command(args[0], args[1:]...).Output() if err != nil { return err } host.HostName = strings.TrimSpace(fmt.Sprintf("%s", out)) Logger.Debugf("Resolved host is: %s", host.HostName) } return nil }
func commandApplyHost(command string, host *config.Host) string { command = strings.Replace(command, "%name", host.Name(), -1) command = strings.Replace(command, "%h", host.HostName, -1) command = strings.Replace(command, "%p", fmt.Sprintf("%d", host.Port), -1) return command }