Пример #1
0
// GetSSHEndpoint tries to determine how to connect to a particular host
// via SSH.  GetSSHEndpoint first attempts to discover the endpoint via
// DNS SRV records of the form "_ssh._tcp.<hostname>".  If found,
// GetSSHEndpoint will return the target host and port to connect to
// instead of the "bare" DNS hostname.  If no SRV record is found, it
// will simply return the hostname and default SSH port (22).
func GetSSHEndpoint(hostname string) (target string, port uint16, err error) {
	cname, srvAddrs, err := net.LookupSRV(serviceName, "tcp", hostname)
	if err != nil {
		if _, ok := err.(*net.DNSError); ok {
			// DNS-related error. This is okay for now;
			// we'll just fall back to trying the hostname
			// as-is instead.
			log.Verbosef("error: %v", err)
			err = nil
		} else {
			// Non-DNS error.  Probably want to stop now.
			log.Fatal(err)
		}
	}

	if len(srvAddrs) > 0 {
		log.Verbosef("Found %d SRV record(s) for %v", len(srvAddrs), cname)

		for i, r := range srvAddrs {
			log.Verbosef("Record %d:\t%d %d %d %s", i, r.Priority, r.Weight, r.Port, r.Target)
		}

		// "The returned records are sorted by priority and randomized
		// by weight within a priority", so return details for the first
		// one in the list.

		// The target DNS names are fully-specified with the root ("."),
		// so trim that off.
		target = strings.TrimRight(srvAddrs[0].Target, ".")
		port = srvAddrs[0].Port
	} else {
		log.Verbosef("No SRV record found for %v", hostname)
		target = hostname
		port = defaultPort
	}

	// TODO: Extend this to return the entire list in priority-order
	return
}
Пример #2
0
func main() {
	if len(os.Args) < 2 {
		usage()
		os.Exit(1)
	}

	sshPath, err := exec.LookPath("ssh")
	if err != nil {
		log.Fatal("Could not find ssh!")
	}

	sshArgs, host, sshCommand := parseArgs(os.Args[1:])

	targetHost, targetPort, err := GetSSHEndpoint(host)
	if err != nil {
		log.Fatal(err)
	}

	log.Verbosef("Target for %v is %v:%v", host, targetHost, targetPort)

	args := []string{}
	args = append(args, fmt.Sprintf("-p %d", targetPort))
	args = append(args, sshArgs...)
	args = append(args, targetHost)
	args = append(args, sshCommand...)
	log.Verbosef("command: %v %v", sshPath, strings.Join(args, " "))

	cmd := exec.Command(sshPath, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	log.Verbosef("Connecting to %v:%v", targetHost, targetPort)
	if err = cmd.Run(); err != nil {
		if err, ok := err.(*exec.ExitError); !ok {
			log.Fatal(err)
		}
	}
}