Perform the check on accept, not in processing CONNECT

This will protect the server from non NATS clients (telnet, etc),
or misbehaving clients that would create the tcp connection but
block before sending the CONNECT.
The drawback is that the client may or may not receive the error
message (in my tests, it was getting only between 10%-20% of times).
This commit is contained in:
Ivan Kozlovic
2016-12-01 08:48:04 -07:00
parent 6bcd324955
commit ca268290a6
4 changed files with 11 additions and 29 deletions

View File

@@ -447,12 +447,6 @@ func (c *client) processConnect(arg []byte) error {
srv.mu.Unlock()
}
// Check for max connections
if ok := srv.checkMaxConn(c); !ok {
c.maxConnLimit()
return ErrTooManyConnections
}
// Check for Auth
if ok := srv.checkAuth(c); !ok {
c.authViolation()
@@ -496,14 +490,8 @@ func (c *client) authViolation() {
c.closeConnection()
}
func (c *client) maxConnLimit() {
if c.srv != nil && c.srv.opts.Users != nil {
c.Errorf("%s - User %q",
ErrTooManyConnections.Error(),
c.opts.Username)
} else {
c.Errorf(ErrTooManyConnections.Error())
}
func (c *client) maxConnExceeded() {
c.Errorf(ErrTooManyConnections.Error())
c.sendErr(ErrTooManyConnections.Error())
c.closeConnection()
}

View File

@@ -28,5 +28,5 @@ var (
// ErrTooManyConnections signals a client that the maximum number of connections supported by the
// server has been reached.
ErrTooManyConnections = errors.New("Too many connections")
ErrTooManyConnections = errors.New("Maximum Connections Exceeded")
)

View File

@@ -546,6 +546,13 @@ func (s *Server) createClient(conn net.Conn) *client {
s.mu.Unlock()
return c
}
// If there is a max connections specified, check that adding
// this new client would not push us over the max
if s.opts.MaxConn > 0 && len(s.clients) >= s.opts.MaxConn {
s.mu.Unlock()
c.maxConnExceeded()
return nil
}
s.clients[c.cid] = c
s.mu.Unlock()
@@ -731,17 +738,6 @@ func (s *Server) checkAuth(c *client) bool {
}
}
// Check that number of clients is below Max connection setting.
func (s *Server) checkMaxConn(c *client) bool {
if c.typ == CLIENT {
s.mu.Lock()
ok := len(s.clients) <= s.opts.MaxConn
s.mu.Unlock()
return ok
}
return true
}
// Remove a client or route from our internal accounting.
func (s *Server) removeClient(c *client) {
var rID string

View File

@@ -242,9 +242,7 @@ func TestMaxConnections(t *testing.T) {
nc2, err := nats.Connect(addr)
if err == nil {
if nc2 != nil {
nc2.Close()
}
nc2.Close()
t.Fatal("Expected connection to fail")
}
}