From 60070fffdb584b88986e1af56a8598c01fb54ee4 Mon Sep 17 00:00:00 2001 From: Louis Poinsignon Date: Mon, 18 May 2020 14:51:28 -0700 Subject: [PATCH] Protection against "too many open files" * Raised in #65, if the server does not have enough sockets, Accept returns error * Due to a bug, it was causing `invalid memory address or nil pointer dereference` if no other limit was specified * Issue was triggered around 1024 concurrent sessions on out of box Linux (check `ulimit -a | grep "open files"`) --- lib/server.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/server.go b/lib/server.go index 413ef45..5fa14fa 100644 --- a/lib/server.go +++ b/lib/server.go @@ -501,8 +501,7 @@ func (s *Server) Start(bind string) error { if err != nil { return err } - s.loopTCP(tcplist, "tcp", s.acceptClientTCP) - return nil + return s.loopTCP(tcplist, "tcp", s.acceptClientTCP) } func (s *Server) acceptClientTCP(tcpconn net.Conn) error { @@ -583,27 +582,34 @@ func (s *Server) acceptClientSSH(tcpconn net.Conn) error { type ClientCallback func(net.Conn) error -func (s *Server) loopTCP(tcplist net.Listener, logEnv string, clientCallback ClientCallback) { +func (s *Server) loopTCP(tcplist net.Listener, logEnv string, clientCallback ClientCallback) error { for { - tcpconn, _ := tcplist.Accept() + tcpconn, err := tcplist.Accept() + if err != nil { + if s.log != nil { + s.log.Errorf("Failed to accept %s connection: %s", logEnv, err) + } + continue + } if s.maxconn > 0 && s.connected >= s.maxconn { if s.log != nil { - s.log.Warnf("Could not accept %v connection from %v (not enough slots avaible: %v)", logEnv, tcpconn.RemoteAddr(), s.maxconn) + s.log.Warnf("Could not accept %s connection from %v (not enough slots avaible: %d)", logEnv, tcpconn.RemoteAddr(), s.maxconn) } tcpconn.Close() } else { if s.log != nil { - s.log.Infof("Accepted %v connection from %v (%v/%v)", logEnv, tcpconn.RemoteAddr(), s.connected+1, s.maxconn) + s.log.Infof("Accepted %s connection from %v (%d/%d)", logEnv, tcpconn.RemoteAddr(), s.connected+1, s.maxconn) } if clientCallback != nil { err := clientCallback(tcpconn) if err != nil && s.log != nil { - s.log.Errorf("Error with %v client %v: %v", logEnv, tcpconn.RemoteAddr(), err) + s.log.Errorf("Error with %s client %v: %v", logEnv, tcpconn.RemoteAddr(), err) } } } } + return nil } func (s *Server) StartSSH(bind string, config *ssh.ServerConfig) error { @@ -612,8 +618,7 @@ func (s *Server) StartSSH(bind string, config *ssh.ServerConfig) error { return err } s.sshconfig = config - s.loopTCP(tcplist, "ssh", s.acceptClientSSH) - return nil + return s.loopTCP(tcplist, "ssh", s.acceptClientSSH) } func (s *Server) StartTLS(bind string, config *tls.Config) error { @@ -621,8 +626,7 @@ func (s *Server) StartTLS(bind string, config *tls.Config) error { if err != nil { return err } - s.loopTCP(tcplist, "tls", s.acceptClientTCP) - return nil + return s.loopTCP(tcplist, "tls", s.acceptClientTCP) } func (s *Server) GetClientList() []*Client {