func (l *sshListener) handle(c net.Conn) error { conf := ssh.ServerConfig{ PublicKeyCallback: l.checkLogin, } conf.AddHostKey(l.id) _, chans, reqs, err := ssh.NewServerConn(c, &conf) if err != nil { return err } go ssh.DiscardRequests(reqs) for newCh := range chans { id := newCh.ChannelType() if len(id) != len(RPC_CHANNEL) { newCh.Reject(ssh.Prohibited, "wrong ID length") } ch, reqs, err := newCh.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) l.pending.add(id, ch) } return nil }
func main() { conf := serverConfig() // start the server addr := fmt.Sprintf("0.0.0.0:%s", os.Args[1]) listener, err := net.Listen("tcp", addr) if err != nil { log.Fatalf("[FATAL] failed to listen to %q, err %q", addr, err) } log.Printf("[INFO] listening to %q", addr) for { conn, err := listener.Accept() if err != nil { log.Fatalf("[FATAL] failed to accept tcp conn %q", err) } _, chs, reqs, err := ssh.NewServerConn(conn, conf) if err != nil { log.Printf("[ERROR] failed to open new ssh server conn %q", err) continue } // discard all requests sent outside of normal data go ssh.DiscardRequests(reqs) for ch := range chs { handleChannel(ch) } } }
func (d *sshDialer) Dial(addr string) (connMuxer, error) { conf := ssh.ClientConfig{ User: "******", Auth: []ssh.AuthMethod{ssh.PublicKeys(d.identity)}, HostKeyCallback: d.checkHost, } c, err := net.Dial("tcp", addr) if err != nil { return nil, err } defer func() { if c != nil { c.Close() } }() conn, chans, reqs, err := ssh.NewClientConn(c, addr, &conf) if err != nil { return nil, err } go ssh.DiscardRequests(reqs) go func() { for c := range chans { go c.Reject(ssh.Prohibited, "") } }() c = nil return &sshMuxer{conn}, nil }
func (srv *Server) ServeConn(conn net.Conn) error { _, chans, reqs, err := ssh.NewServerConn(conn, srv.sshCfg) if err != nil { return fmt.Errorf("handshake: %v", err) } go ssh.DiscardRequests(reqs) for nch := range chans { var ( chType = nch.ChannelType() chArg = string(nch.ExtraData()) ) if !srv.h.AcceptSSHRaw(chType, chArg) { nch.Reject(ssh.UnknownChannelType, "unknown channel type") continue } ch, reqs, err := nch.Accept() if err != nil { return fmt.Errorf("accept: %v", err) } // FIXME: use context.Context to cleanly synchronize with handlers, block on them // but still be able to terminate them gracefully. go func(ch ssh.Channel, reqs <-chan *ssh.Request) { srv.h.HandleSSHRaw(chType, chArg, ch, reqs) ch.Close() }(ch, reqs) } return nil }
func (m *sshMuxer) Open(id string) (io.ReadWriteCloser, error) { channel, reqs, err := m.conn.OpenChannel(id, nil) if err != nil { return nil, err } go ssh.DiscardRequests(reqs) return channel, nil }
func TestSetupForwardAgent(t *testing.T) { a, b, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer a.Close() defer b.Close() _, socket, cleanup := startAgent(t) defer cleanup() serverConf := ssh.ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["rsa"]) incoming := make(chan *ssh.ServerConn, 1) go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { t.Fatalf("Server: %v", err) } incoming <- conn }() conf := ssh.ClientConfig{} conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) if err != nil { t.Fatalf("NewClientConn: %v", err) } client := ssh.NewClient(conn, chans, reqs) if err := ForwardToRemote(client, socket); err != nil { t.Fatalf("SetupForwardAgent: %v", err) } server := <-incoming ch, reqs, err := server.OpenChannel(channelType, nil) if err != nil { t.Fatalf("OpenChannel(%q): %v", channelType, err) } go ssh.DiscardRequests(reqs) agentClient := NewClient(ch) testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil) conn.Close() }
func NewServer() (err error) { // An SSH server is represented by a ServerConfig, which holds // certificate details and handles authentication of ServerConns. config := new(ssh.ServerConfig) config.PublicKeyCallback = HandlePublicKeyCallback config.AuthLogCallback = HandleAuthLogCallback key, err := osext.ReadHostKeys(HostKeysDir) if err != nil { return } for _, v := range key { signer, err := ssh.ParsePrivateKey(v) if err != nil { return err } config.AddHostKey(signer) } // Once a ServerConfig has been configured, connections can be // accepted. conn, err := net.Listen("tcp", ":22") if err != nil { log.Fatal("Failed to listen for connection: ", err) } for { sConn, err := conn.Accept() if err != nil { log.Printf("conn.Accept: %s", err) continue } sshconn, chans, reqs, err := ssh.NewServerConn(sConn, config) if err != nil { log.Printf("ssh.NewServerConn: Failed to handshake: %s", err) continue } // The incoming Request channel must be serviced. go ssh.DiscardRequests(reqs) // Handle the incomming request go HandleServerConn(sshconn, chans) } }
func handleConn(conn net.Conn, conf *ssh.ServerConfig) { defer conn.Close() sshConn, chans, reqs, err := ssh.NewServerConn(conn, conf) if err != nil { log.Println("Failed to handshake:", err) return } go ssh.DiscardRequests(reqs) for ch := range chans { if ch.ChannelType() != "session" { ch.Reject(ssh.UnknownChannelType, "unknown channel type") continue } go handleChannel(sshConn, ch) } }
func (ri *ReviewInfo) Serve(srvConn *ssh.ServerConn, srvChans <-chan ssh.NewChannel, srvReqs <-chan *ssh.Request) (err error) { go ssh.DiscardRequests(srvReqs) log.Info("review connect begin.") for newChan := range srvChans { if newChan.ChannelType() != "session" { newChan.Reject(ssh.ResourceShortage, "not session") continue } ch, reqs, err := newChan.Accept() if err != nil { log.Error("%s", err.Error()) continue } go ri.serveChan(ch, reqs) } log.Info("review connect closed.") return }
// ForwardToAgent routes authentication requests to the given keyring. func ForwardToAgent(client *ssh.Client, keyring Agent) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go func() { ServeAgent(keyring, channel) channel.Close() }() } }() return nil }
// ForwardToRemote routes authentication requests to the ssh-agent // process serving on the given unix socket. func ForwardToRemote(client *ssh.Client, addr string) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } conn, err := net.Dial("unix", addr) if err != nil { return err } conn.Close() go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go forwardUnixSocket(channel, addr) } }() return nil }
func listen(config *ssh.ServerConfig, port string) { listener, err := net.Listen("tcp", "0.0.0.0:"+port) if err != nil { panic(err) } for { // Once a ServerConfig has been configured, connections can be accepted. conn, err := listener.Accept() if err != nil { log.Error(3, "Fail to accept incoming connection: %v", err) continue } // Before use, a handshake must be performed on the incoming net.Conn. sConn, chans, reqs, err := ssh.NewServerConn(conn, config) if err != nil { log.Error(3, "Fail to handshake: %v", err) continue } // The incoming Request channel must be serviced. go ssh.DiscardRequests(reqs) go handleServerConn(sConn.Permissions.Extensions["key-id"], chans) } }
func processRequests(conn *ssh.ServerConn, reqs <-chan *ssh.Request) { for req := range reqs { if req.Type != "tcpip-forward" { // accept only tcpip-forward requests if req.WantReply { req.Reply(false, nil) } continue } type channelForwardMsg struct { Laddr string Lport uint32 } m := &channelForwardMsg{} ssh.Unmarshal(req.Payload, m) privateBytes, err := ioutil.ReadFile(appConfig.RemotePrivateKeyPath) if err != nil { log.Fatal(err.Error()) } signer, err := ssh.ParsePrivateKey(privateBytes) if err != nil { log.Fatal(err.Error()) } config := &ssh.ClientConfig{ User: appConfig.RemoteSSHUser, Auth: []ssh.AuthMethod{ ssh.PublicKeys(signer), }, } sshClientConn, err := ssh.Dial("tcp", appConfig.RemoteSSHAddr, config) if err != nil { log.Fatal(err.Error()) } type channelOpenForwardMsg struct { raddr string rport uint32 laddr string lport uint32 } fm := &channelOpenForwardMsg{ raddr: "localhost", rport: m.Lport, laddr: "localhost", lport: m.Lport, } channel, reqs, err := conn.Conn.OpenChannel("forwarded-tcpip", ssh.Marshal(fm)) if err != nil { log.Fatal(err.Error()) } go ssh.DiscardRequests(reqs) portListener, err := sshClientConn.Listen("tcp", appConfig.RemoteForwardAddress) if err != nil { log.Fatal(err.Error()) } go func() { for { sshConn, err := portListener.Accept() if err != nil { log.Fatal(err.Error()) } // Copy localConn.Reader to sshConn.Writer go func(sshConn net.Conn) { _, err := io.Copy(sshConn, channel) if err != nil { log.Println("io.Copy failed: %v", err) sshConn.Close() return } }(sshConn) // Copy sshConn.Reader to localConn.Writer go func(sshConn net.Conn) { _, err := io.Copy(channel, sshConn) if err != nil { log.Println("io.Copy failed: %v", err) sshConn.Close() return } }(sshConn) } }() req.Reply(true, nil) } }