func handleLocalSshConn(lnConn net.Conn) { defer func() { if Config.Ssh_Reverse_Proxy.Exit_On_Panic { return } if r := recover(); r != nil { Log.Error("Recovered from panic in connection from "+ lnConn.RemoteAddr().String()+":", r) } }() Log.Info("Received connection from", lnConn.RemoteAddr()) var sClient *ssh.Client psConfig := getProxyServerSshConfig(&sClient) psConn, psChans, psReqs, err := ssh.NewServerConn(lnConn, psConfig) if err != nil { Log.Info("Could not establish connection with " + lnConn.RemoteAddr().String() + ": " + err.Error()) return } defer psConn.Close() defer sClient.Close() go ssh.DiscardRequests(psReqs) for newChannel := range psChans { handleChannel(newChannel, sClient) } Log.Info("Lost connection with", lnConn.RemoteAddr()) }
func listen(config *ssh.ServerConfig, port int) { listener, err := net.Listen("tcp", "0.0.0.0:"+com.ToStr(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, "Error accepting 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, "Error on handshaking: %v", err) continue } log.Trace("Connection from %s (%s)", sConn.RemoteAddr(), sConn.ClientVersion()) // The incoming Request channel must be serviced. go ssh.DiscardRequests(reqs) go handleServerConn(sConn.Permissions.Extensions["key-id"], chans) } }
func main() { mylogger = logger.NewLogger("", 0) configPath := flag.String("config", "", "fssh config file") flag.Parse() if _, err := toml.DecodeFile(*configPath, &config); err != nil { mylogger.Fatal(err) } sshConfig := ssh.ServerConfig{ PublicKeyCallback: keyHandler, PasswordCallback: passwdHandler, } sshConfig.AddHostKey(readSecretKey(config.Key)) s, err := net.Listen("tcp", config.Address+":"+strconv.Itoa(config.Port)) if err != nil { mylogger.Fatal(err) } defer s.Close() for { c, err := s.Accept() if err != nil { mylogger.Fatal(err) } ssh.NewServerConn(c, &sshConfig) } }
func (s *Server) serve(conn net.Conn) error { config := ssh.ServerConfig{ PublicKeyCallback: s.config.PublicKeyCallback.wrap(), PasswordCallback: s.config.PasswordCallback.wrap(), } for _, hostKey := range s.config.HostKeys { config.AddHostKey(hostKey) } serverConn, channelRequestCh, globalRequestCh, err := ssh.NewServerConn(conn, &config) if err != nil { return err } // connection succeeded at this point. create the ssh connection and start the go procs. newConn := sshConn{ handler: s.config.Handler, conn: serverConn, newChannel: channelRequestCh, requests: globalRequestCh, } go newConn.processChannelRequests() go newConn.processGlobalRequests() return nil }
func (s *server) start(port string) error { socket, err := net.Listen("tcp", fmt.Sprintf(":%s", port)) if err != nil { return err } log.Infof("Server listening on :%s :)", port) for { conn, err := socket.Accept() if err != nil { log.Errorf("unable to accept connection %v", err) continue } // From a standard TCP connection to an encrypted SSH connection sshConn, newChans, _, err := ssh.NewServerConn(conn, s.config) if err != nil { log.Errorf("ssh handshake failed, %v", err) continue } defer sshConn.Close() log.Infof("connection from %s", sshConn.RemoteAddr()) go func() { for chanReq := range newChans { go s.handleChanReq(chanReq, sshConn.Permissions.CriticalOptions) } }() } }
func (c *adapter) Handle(conn net.Conn, ui packer.Ui) error { log.Print("SSH proxy: accepted connection") _, chans, reqs, err := ssh.NewServerConn(conn, c.config) if err != nil { return errors.New("failed to handshake") } // discard all global requests go ssh.DiscardRequests(reqs) // Service the incoming NewChannels for newChannel := range chans { if newChannel.ChannelType() != "session" { newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") continue } go func(ch ssh.NewChannel) { if err := c.handleSession(ch); err != nil { c.ui.Error(err.Error()) } }(newChannel) } return nil }
func handleConn(conn net.Conn, handler Handler, config *ssh.ServerConfig) { sconn, channels, requests, err := ssh.NewServerConn(conn, config) if err != nil { conn.Close() // TODO: log fmt.Printf("Error accepting serverconn: %v\n", err) return } defer sconn.Close() go func() { for request := range requests { request.Reply(false, nil) } }() channel, requests, err := getSession(channels) if err != nil { fmt.Printf("Error getting session channel: %v\n", err) return } go ignoreChannels(channels) err = prepHandle(channel, requests, handler) if err != nil { fmt.Printf("Error in prephandle: %v\n", err) return } }
// Handle is the SSH client entrypoint, it takes a net.Conn // instance and handle all the ssh and ssh2docker stuff func (s *Server) Handle(netConn net.Conn) error { if err := s.Init(); err != nil { return err } log.Debugf("Server.Handle netConn=%v", netConn) // Initialize a Client object conn, chans, reqs, err := ssh.NewServerConn(netConn, s.SshConfig) if err != nil { log.Infof("Received disconnect from %s: 11: Bye Bye [preauth]", netConn.RemoteAddr().String()) return err } client := NewClient(conn, chans, reqs, s) // Handle requests if err = client.HandleRequests(); err != nil { return err } // Handle channels if err = client.HandleChannels(); err != nil { return err } return nil }
// handleConn handles an individual client connection. // // It manages the connection, but passes channels on to `answer()`. func (s *server) handleConn(conn net.Conn, conf *ssh.ServerConfig) { defer conn.Close() log.Info("Accepted connection.") sshConn, chans, reqs, err := ssh.NewServerConn(conn, conf) if err != nil { // Handshake failure. log.Err("Failed handshake: %s", err) return } // Discard global requests. We're only concerned with channels. go ssh.DiscardRequests(reqs) condata := sshConnection(conn) // Now we handle the channels. for incoming := range chans { log.Info("Channel type: %s\n", incoming.ChannelType()) if incoming.ChannelType() != "session" { incoming.Reject(ssh.UnknownChannelType, "Unknown channel type") } channel, req, err := incoming.Accept() if err != nil { // Should close request and move on. panic(err) } go s.answer(channel, req, condata, sshConn) } conn.Close() }
func newMockLineServer(t *testing.T) string { l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("Unable to listen for connection: %s", err) } go func() { defer l.Close() c, err := l.Accept() if err != nil { t.Errorf("Unable to accept incoming connection: %s", err) } defer c.Close() conn, chans, _, err := ssh.NewServerConn(c, serverConfig) if err != nil { t.Logf("Handshaking error: %v", err) } t.Log("Accepted SSH connection") for newChannel := range chans { channel, _, err := newChannel.Accept() if err != nil { t.Errorf("Unable to accept channel.") } t.Log("Accepted channel") go func(channelType string) { defer channel.Close() conn.OpenChannel(channelType, nil) }(newChannel.ChannelType()) } conn.Close() }() return l.Addr().String() }
func (server *Server) handleConnection(conn net.Conn) { showConnCount := func() { server.Logger.Debugf("Current Connections: (%d/%d)", atomic.LoadInt32(&server.ClientCount), server.Config.MaxClient) } defer func() { conn.Close() server.Logger.Debugf("The connection from %s is closed", conn.RemoteAddr().String()) atomic.AddInt32(&server.ClientCount, -1) showConnCount() }() atomic.AddInt32(&server.ClientCount, 1) showConnCount() if atomic.LoadInt32(&server.ClientCount) > server.Config.MaxClient { server.Logger.Errorf("Failed to accept incoming connection due to too many connections (%d/%d)", server.ClientCount, server.Config.MaxClient) return } sshConnection, chans, reqs, err := ssh.NewServerConn(conn, server.ServerConfig) if err != nil { if err != io.EOF { server.Logger.Errorf("Failed to start SSL connection with %s due to %s", conn.RemoteAddr().String(), err) } return } server.Logger.Debugf("Built SSL connection with %s, sessionId: %s, client version: %s, user: %s", conn.RemoteAddr().String(), hex.EncodeToString(sshConnection.SessionID()), sshConnection.ClientVersion(), sshConnection.User()) go ssh.DiscardRequests(reqs) server.handleChannels(chans, sshConnection) }
// StartSSHD starts the ssh server on address:port provided func StartSSHD(addr string) error { handler.Board = make(map[string]*handler.Handler, 0) listener, err := net.Listen("tcp", addr) if err != nil { return fmt.Errorf("Failed to listen on %v port. Reason: (%s)", addr, err.Error()) } fmt.Printf("GoSSHa is listening on %v port!\n", addr) for { tcpConn, err := listener.Accept() if err != nil { fmt.Printf("Failed to accept incoming connection (%s)\n", err) continue } h := handler.New() config := h.MakeSSHConfig() _, chans, reqs, err := ssh.NewServerConn(tcpConn, config) // sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config) if err != nil { fmt.Printf("Failed to handshake (%s)\n", err.Error()) continue } // fmt.Sprintf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) go ssh.DiscardRequests(reqs) go handleChannels(chans, &h) } }
func (p *Proxy) HandleConnection(netConn net.Conn) { logger := p.logger.Session("handle-connection") defer netConn.Close() serverConn, serverChannels, serverRequests, err := ssh.NewServerConn(netConn, p.serverConfig) if err != nil { return } defer serverConn.Close() clientConn, clientChannels, clientRequests, err := NewClientConn(logger, serverConn.Permissions) if err != nil { return } defer clientConn.Close() emitLogMessage(logger, serverConn.Permissions) go ProxyGlobalRequests(logger, clientConn, serverRequests) go ProxyGlobalRequests(logger, serverConn, clientRequests) go ProxyChannels(logger, clientConn, serverChannels) go ProxyChannels(logger, serverConn, clientChannels) Wait(logger, serverConn, clientConn) }
func main() { config := ssh.ServerConfig{ PublicKeyCallback: keyAuth, } config.AddHostKey(hostPrivateKeySigner) port := "2222" if os.Getenv("PORT") != "" { port = os.Getenv("PORT") } socket, err := net.Listen("tcp", ":"+port) if err != nil { panic(err) } for { conn, err := socket.Accept() if err != nil { panic(err) } // From a standard TCP connection to an encrypted SSH connection sshConn, _, _, err := ssh.NewServerConn(conn, &config) if err != nil { panic(err) } log.Println("Connection from", sshConn.RemoteAddr()) sshConn.Close() } }
func (self *ServerMode) handleSSHRequest(connection *net.Conn, config *ssh.ServerConfig) { // TODO: Check if we need to close anything. // Before use, a handshake must be performed on the incoming net.Conn. _, channels, requests, err := ssh.NewServerConn(*connection, config) if err != nil { panic("failed to handshake") } // The incoming Request channel must be serviced. go ssh.DiscardRequests(requests) // Service the incoming Channel channel. for newChannel := range channels { // Channels have a type, depending on the application level protocol intended. In the case of a shell, the type is // "session" and ServerShell may be used to present a simple terminal interface. if newChannel.ChannelType() != "session" { newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") continue } channel, requests, err := newChannel.Accept() if err != nil { panic("could not accept channel.") } // Sessions have out-of-band requests such as "shell", "pty-req" and "env". // Here we handle only the "shell" request. go func(in <-chan *ssh.Request) { for req := range in { ok := false switch req.Type { case "shell": ok = true if len(req.Payload) > 0 { // We don't accept any commands, only the default shell. ok = false } } req.Reply(ok, nil) } }(requests) term := terminal.NewTerminal(channel, "> ") go func() { defer channel.Close() for { line, err := term.ReadLine() if err != nil { break } // TODO: Likely we need to interpret the incoming commands in here. fmt.Println("INPUT-SSH:" + line) } }() } }
// handleSSH runs in a goroutine and handles an incoming SSH connection func (s *SSHServer) handleSSH(conn net.Conn, config ssh.ServerConfig) { _, _, _, err := ssh.NewServerConn(conn, &config) if err == nil { // this should never happen and if it does we need to shutdown the system log.Fatal("ssh server error: successful login. Shutting down system\n") } }
func (t *tcpHandler) Execute(c context.Context) { select { case <-c.Done(): t.conn.Close() return default: } // Create reaper g := grim.ReaperWithContext(c) defer g.Wait() // Convert to SSH connection sshConn, channels, requests, err := ssh.NewServerConn(t.conn, t.config) if err != nil { t.logger.Warn("SSH handshake failed:", "addr", t.conn.RemoteAddr().String(), "error", err) t.conn.Close() g.Kill() return } // Close connection on exit t.logger.Debug("Handshake successful") defer sshConn.Close() defer sshConn.Wait() // Discard all out-of-channel requests if t.requestHandler != nil { go t.requestHandler.Consume(requests) } else { go ssh.DiscardRequests(requests) } OUTER: for { select { case <-c.Done(): break OUTER case <-g.Dead(): break OUTER case ch := <-channels: // Check if chan was closed if ch == nil { break OUTER } // Handle the channel g.SpawnFunc(func(ctx context.Context) { t.dispatcher.Dispatch(ctx, sshConn, ch) return }) } } g.Kill() }
// handleSSH runs in a goroutine and handles an incoming SSH connection func handleSSH(conn net.Conn, config ssh.ServerConfig) { _, _, _, err := ssh.NewServerConn(conn, &config) if err == nil { log.Fatal("ssh server error: successful login. Shutting down system\n") } // goroutine ends conn.Close() }
func main() { config := &ssh.ServerConfig{ //Define a function to run when a client attempts a password login PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { // Should use constant-time compare (or better, salt+hash) in a production setting. if c.User() == "vagrant" && string(pass) == "vagrant" { return nil, nil } return nil, fmt.Errorf("password rejected for %q", c.User()) }, // NoClientAuth: true, } // You can generate a keypair with 'ssh-keygen -t rsa' privateBytes, err := ioutil.ReadFile("gossh_rsa") if err != nil { log.Fatal("Failed to load private key (./gossh_rsa)") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { log.Fatal("Failed to parse private key") } config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be accepted. socket, err := net.Listen("tcp", "0.0.0.0:2200") if err != nil { log.Fatalf("Failed to listen on 2200 (%s)", err) } for { conn, err := socket.Accept() if err != nil { panic(err) } // From a standard TCP connection to an encrypted SSH connection sshConn, newChans, _, err := ssh.NewServerConn(conn, config) if err != nil { panic(err) } defer sshConn.Close() log.Println("Connection from", sshConn.RemoteAddr()) go func() { for chanReq := range newChans { go handleChanReq(chanReq) } }() } }
// ListenAndServe starts a SCP server. func (s *Server) ListenAndServe() { if len(s.BindAddr) == 0 { panic("Must specify BindAddr") } if len(s.CertPath) == 0 { panic("Must specify CertPath") } privateBytes, err := ioutil.ReadFile(s.CertPath) if err != nil { panic("Failed to load private key") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { panic("Failed to parse private key") } config := &ssh.ServerConfig{ NoClientAuth: true, } config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be // accepted. listener, err := net.Listen("tcp", s.BindAddr) if err != nil { s.Fatal("Failed to bind to address", "addr", bindAddr) } s.Info("Listening for SCP connections", "addr", bindAddr) for { nConn, err := listener.Accept() if err != nil { s.Error("Failed to listen for SCP connections", "err", err) continue } // Before use, a handshake must be performed on the incoming // net.Conn. _, chans, reqs, err := ssh.NewServerConn(nConn, config) if err != nil { s.Error("Failed to create SCP connection", "err", err) continue } // Discard all global out-of-band Requests go ssh.DiscardRequests(reqs) // Accept all channels go s.handleChannels(chans) } }
func main() { config := &ssh.ServerConfig{ //Define a function to run when a client attempts a password login PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { // Should use constant-time compare (or better, salt+hash) in a production setting. if c.User() == "vagrant" && string(pass) == "vagrant" { return nil, nil } return nil, fmt.Errorf("password rejected for %q", c.User()) }, // NoClientAuth: true, } // You can generate a keypair with 'ssh-keygen -t rsa' privateBytes, err := ioutil.ReadFile("gossh_rsa") if err != nil { log.Fatal("Failed to load private key (./gossh_rsa)") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { log.Fatal("Failed to parse private key") } config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be accepted. listener, err := net.Listen("tcp", "0.0.0.0:2200") if err != nil { log.Fatalf("Failed to listen on 2200 (%s)", err) } // Accept all connections log.Print("Listening on 2200...") for { tcpConn, err := listener.Accept() if err != nil { log.Printf("Failed to accept incoming connection (%s)", err) continue } // Before use, a handshake must be performed on the incoming net.Conn. sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config) if err != nil { log.Printf("Failed to handshake (%s)", err) continue } log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) // Discard all global out-of-band Requests go ssh.DiscardRequests(reqs) // Accept all channels go handleChannels(chans) } }
func handleConnection(sshConfig *ssh.ServerConfig, tcpConn net.Conn) { defer tcpConn.Close() log.Debugf("new TCP connection from %s", tcpConn.RemoteAddr()) sshConn, _, _, err := ssh.NewServerConn(tcpConn, sshConfig) if err != nil { log.Debugf("failed to handshake (%s)", err) } else { sshConn.Close() } }
func sshServerFromConn(conn net.Conn, useSubsystem bool, config *ssh.ServerConfig) (*sshServer, error) { // From a standard TCP connection to an encrypted SSH connection sshConn, newChans, newReqs, err := ssh.NewServerConn(conn, config) if err != nil { return nil, err } svr := &sshServer{useSubsystem, conn, config, sshConn, newChans, newReqs} svr.listenChannels() return svr, nil }
func main() { // In the latest version of crypto/ssh (after Go 1.3), the SSH server type has been removed // in favour of an SSH connection type. A ssh.ServerConn is created by passing an existing // net.Conn and a ssh.ServerConfig to ssh.NewServerConn, in effect, upgrading the net.Conn // into an ssh.ServerConn config := &ssh.ServerConfig{ // You may also explicitly allow anonymous client authentication, though anon bash // sessions may not be a wise idea NoClientAuth: true, } // You can generate a keypair with 'ssh-keygen -t rsa' privateBytes, err := ioutil.ReadFile("id_rsa") if err != nil { log.Fatal("Failed to load private key (./id_rsa)") } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { log.Fatal("Failed to parse private key") } config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be accepted. listener, err := net.Listen("tcp", "0.0.0.0:2200") if err != nil { log.Fatalf("Failed to listen on 2200 (%s)", err) } // Accept all connections log.Print("Listening on 2200...") for { tcpConn, err := listener.Accept() if err != nil { log.Printf("Failed to accept incoming connection (%s)", err) continue } // Before use, a handshake must be performed on the incoming net.Conn. sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config) if err != nil { log.Printf("Failed to handshake (%s)", err) continue } log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) // Discard all global out-of-band Requests go ssh.DiscardRequests(reqs) // Accept all channels go handleChannels(chans) } }
// StartSSHExecServer runs an ssh server that accepts a single connection and handles only "exec" requests. // The handler callback is given the command string and stderr io.Writer. The handler return // value is propagated to the client via "exit-status". func StartSSHExecServer(port *int, sh SessionHandler) (*sync.WaitGroup, error) { config := &ssh.ServerConfig{ PublicKeyCallback: TestCertChecker.Authenticate, PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { if c.User() == TestUser && string(pass) == TestPassword { return nil, nil } return nil, errors.New("unauthorized user") }, } signer, err := ssh.ParsePrivateKey(testdata.PEMBytes["dsa"]) if err != nil { panic(err) } config.AddHostKey(signer) listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", *port)) if err != nil { panic(err) } *port = listener.Addr().(*net.TCPAddr).Port var wg sync.WaitGroup wg.Add(1) // service 1 request go func() { defer listener.Close() defer wg.Done() tcpConn, err := listener.Accept() if err != nil { log.Printf("Failed to accept incoming connection (%s)", err) return } // Before use, a handshake must be performed on the incoming net.Conn. sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config) if err != nil { log.Printf("Failed to handshake (%s)", err) return } log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) // Discard all global out-of-band Requests go ssh.DiscardRequests(reqs) // Accept all channels handleChannels(sshConn, chans, sh) }() return &wg, nil }
func (s *SSHServer) handleTCPConnection(parentTomb tomb.Tomb, conn net.Conn) error { // Convert to SSH connection sshConn, channels, requests, err := ssh.NewServerConn(conn, s.config.sshConfig) if err != nil { s.config.Logger.Warn("SSH handshake failed: %s", conn.RemoteAddr()) return err } // Close connection on exit s.config.Logger.Debug("Handshake successful") defer sshConn.Conn.Close() // Discard requests go ssh.DiscardRequests(requests) // Create new tomb stone var t tomb.Tomb for { select { case ch := <-channels: chType := ch.ChannelType() // Determine if channel is acceptable (has a registered handler) handler, ok := s.config.Handler(chType) if !ok { s.config.Logger.Info("UnknownChannelType", "type", chType) ch.Reject(ssh.UnknownChannelType, chType) break } // Accept channel channel, requests, err := ch.Accept() if err != nil { s.config.Logger.Warn("Error creating channel") continue } t.Go(func() error { return handler.Handle(t, sshConn, channel, requests) }) case <-parentTomb.Dying(): t.Kill(nil) if err := t.Wait(); err != nil { s.config.Logger.Warn("ssh handler error: %s", err) } sshConn.Close() return sshConn.Wait() } } return nil }
func (server *SshServer) run(addr string) { config := &ssh.ServerConfig{ PasswordCallback: func(_ ssh.ConnMetadata, pwd []byte) (*ssh.Permissions, error) { // it's just a demo, in a real server this should not be done :) if string(pwd) == "<3txt" { return nil, nil } return nil, errors.New("pwd error, please enter <3txt to enter") }, } // You can generate a keypair with 'ssh-keygen -t rsa' privateBytes, err := ioutil.ReadFile(server.id_rsa) if err != nil { fmt.Printf("Failed to load private key %s\n", server.id_rsa) return } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { fmt.Println("Failed to parse private key") return } config.AddHostKey(private) listener, err := net.Listen("tcp", addr) if err != nil { fmt.Printf("Failed to listen on %s (%s)\n", addr, err) return } fmt.Printf("Listening on %s...", addr) for { tcpConn, err := listener.Accept() if err != nil { fmt.Printf("Failed to accept incoming connection (%s)\n", err) continue } sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config) if err != nil { fmt.Printf("Failed to handshake (%s)\n", err) continue } fmt.Printf("New SSH connection from %s (%s)\n", sshConn.RemoteAddr(), sshConn.ClientVersion()) go ssh.DiscardRequests(reqs) go server.handleChannels(sshConn.User(), chans) } }
func handler(conn net.Conn, gm *GameManager, config *ssh.ServerConfig) { // Before use, a handshake must be performed on the incoming // net.Conn. _, chans, reqs, err := ssh.NewServerConn(conn, config) if err != nil { fmt.Println("Failed to handshake with new client") return } // The incoming Request channel must be serviced. go ssh.DiscardRequests(reqs) // Service the incoming Channel channel. for newChannel := range chans { // Channels have a type, depending on the application level // protocol intended. In the case of a shell, the type is // "session" and ServerShell may be used to present a simple // terminal interface. if newChannel.ChannelType() != "session" { newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") continue } channel, requests, err := newChannel.Accept() if err != nil { fmt.Println("could not accept channel.") return } // TODO: Remove this -- only temporary while we launch on HN // // To see how many concurrent users are online fmt.Printf("Player joined. Current stats: %d users, %d games\n", gm.SessionCount(), gm.GameCount()) // Reject all out of band requests accept for the unix defaults, pty-req and // shell. go func(in <-chan *ssh.Request) { for req := range in { switch req.Type { case "pty-req": req.Reply(true, nil) continue case "shell": req.Reply(true, nil) continue } req.Reply(false, nil) } }(requests) gm.HandleChannel <- channel } }
//DialServerConn serves in place of ssh.NewServerConn func DialServerConn(ds time.Duration, con net.Conn, conf *ssh.ServerConfig) (sc *ssh.ServerConn, cs <-chan ssh.NewChannel, rs <-chan *ssh.Request, ex error) { done := make(chan struct{}) reset := make(chan struct{}) authlog := conf.AuthLogCallback logger := func(conn ssh.ConnMetadata, method string, err error) { flux.GoDefer("AuthLogCallback", func() { flux.GoDefer("AuthLog", func() { if authlog != nil { authlog(conn, method, err) } }) reset <- struct{}{} }) } conf.AuthLogCallback = logger flux.GoDefer("NewServerConn", func() { defer close(done) sc, cs, rs, ex = ssh.NewServerConn(con, conf) return }) expiration := threshold(ds) func() { nsloop: for { select { case <-done: expiration = nil break nsloop case <-reset: expiration = threshold(ds) case <-expiration: if sc != nil { sc.Close() } sc = nil cs = nil rs = nil ex = fmt.Errorf("Expired NewServerConn call for ip:%+s ", con.RemoteAddr()) break nsloop } } }() return }
// HandleConn takes a net.Conn and runs it through sshmux. func (s *Server) HandleConn(c net.Conn) { sshConn, newChans, reqs, err := ssh.NewServerConn(c, s.sshConfig) if err != nil { c.Close() return } if sshConn.Permissions == nil || sshConn.Permissions.Extensions == nil { sshConn.Close() return } ext := sshConn.Permissions.Extensions pk := &publicKey{ publicKey: []byte(ext["pubKey"]), publicKeyType: ext["pubKeyType"], } user, err := s.Auther(sshConn, pk) session := &Session{ Conn: sshConn, User: user, PublicKey: pk, } s.Setup(session) go ssh.DiscardRequests(reqs) go func() { defer sshConn.Close() var wg sync.WaitGroup for newChannel := range newChans { wg.Add(1) if newChannel.ChannelType() == "session" { go func() { defer wg.Done() s.SessionForward(session, newChannel, newChans) }() break } else { go func() { defer wg.Done() s.HandleNewChannel(session, newChannel) }() } } wg.Wait() log.Printf("Closing connection for: %s", session.User.Name) }() }