Example #1
0
func Hop(through *ssh.Client, toaddr string, c *ssh.ClientConfig) (*ssh.Client, error) {
	hopconn, err := through.Dial("tcp", toaddr)
	if err != nil {
		return nil, err
	}

	conn, chans, reqs, err := ssh.NewClientConn(hopconn, toaddr, c)
	if err != nil {
		return nil, err
	}

	return ssh.NewClient(conn, chans, reqs), nil
}
Example #2
0
// Start port forwarding for the given SSH client:
func loop(sshClient *ssh.Client, localToRemote, remoteToLocal []PortForward) {
	done := make(chan bool, 1)

	// Intercept termination signals:
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGQUIT)

	go func() {
		sig := <-sigc
		log.Printf("Caught signal: %s\n", sig)
		done <- true
	}()

	// Forward all the local-to-remote ports:
	for _, fwd := range localToRemote {
		// Set up forwarding addresses:
		localAddr := fwd.LocalAddr
		remoteAddr := fwd.RemoteAddr

		log.Printf("Forwarding connections from local %s to remote %s\n", localAddr, remoteAddr)

		go func() {
			localListener, err := net.Listen("tcp", localAddr)
			if err != nil {
				log.Printf("unable to listen: %s\n", err)
				done <- true
				return
			}
			defer localListener.Close()
			log.Printf("Listening...\n")

			// Begin accepting new connections from the SSH tunnel:
			for {
				// Accept a new local connection:
				local, err := localListener.Accept()
				if err != nil {
					log.Printf("Accept: %s\n", err)
					break
				}
				logContext := local.RemoteAddr().String()
				log.Printf("%s: Accepted local connection.\n", logContext)

				// Connect to the remote RDP service:
				remote, err := sshClient.Dial("tcp", remoteAddr)
				if err != nil {
					log.Printf("%s: Unable to connect via SSH: %s\n", logContext, err)
					local.Close()
					continue
				}
				defer remote.Close()

				// Start forwarding data back 'n forth:
				go forward(local, remote, logContext)
			}
		}()
	}

	// Forward all remote-to-local ports:
	for _, fwd := range remoteToLocal {
		// Set up forwarding addresses:
		localAddr := fwd.LocalAddr
		remoteAddr := fwd.RemoteAddr

		// Resolve local address:
		var err error
		localTCPAddr, err := net.ResolveTCPAddr("tcp", localAddr)
		if err != nil {
			log.Printf("unable to resolve local address: %s\n", err)
			done <- true
			return
		}

		log.Printf("Forwarding connections from remote %s to local %s\n", remoteAddr, localAddr)

		go func() {
			// Request the remote side to open a port for forwarding:
			l, err := sshClient.Listen("tcp", remoteAddr)
			if err != nil {
				log.Printf("unable to register tcp forward: %s\n", err)
				return
			}
			log.Printf("Listening...\n")
			defer l.Close()

			// Begin accepting new connections from the SSH tunnel:
			for {
				// Accept a new remote connection from SSH:
				remote, err := l.Accept()
				if err != nil {
					log.Printf("Accept: %s\n", err)
					done <- true
					break
				}
				logContext := remote.RemoteAddr().String()
				log.Printf("%s: Accepted new SSH tunnel connection.\n", logContext)

				// Connect to the local RDP service:
				local, err := net.DialTCP("tcp", nil, localTCPAddr)
				if err != nil {
					log.Printf("%s: Could not open local connection to: %s\n", logContext, localTCPAddr)
					remote.Close()
					continue
				}

				// Start forwarding data back 'n forth:
				go forward(local, remote, logContext)
			}
		}()
	}

	<-done
}