diff --git a/server/client.go b/server/client.go index 5e9ec94f..d774f042 100644 --- a/server/client.go +++ b/server/client.go @@ -1264,7 +1264,7 @@ func (c *client) processInfo(arg []byte) error { case GATEWAY: c.processGatewayInfo(&info) case LEAF: - c.processLeafnodeInfo(&info) + return c.processLeafnodeInfo(&info) } return nil } diff --git a/server/errors.go b/server/errors.go index c1733438..9472f30d 100644 --- a/server/errors.go +++ b/server/errors.go @@ -66,6 +66,10 @@ var ( // attempted to connect to the leaf node listen port. ErrClientConnectedToLeafNodePort = errors.New("attempted to connect to leaf node port") + // ErrLeafConnectedToClientPort represents an error condition when a client + // attempted to connect to the leaf node listen port. + ErrLeafConnectedToClientPort = errors.New("attempted to connect to client port") + // ErrAccountExists is returned when an account is attempted to be registered // but already exists. ErrAccountExists = errors.New("account exists") diff --git a/server/leafnode.go b/server/leafnode.go index ff021fe3..b8a5e6b3 100644 --- a/server/leafnode.go +++ b/server/leafnode.go @@ -628,7 +628,12 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client { c.mu.Unlock() // Error will be handled below, so ignore here. - c.parse([]byte(info)) + err = c.parse([]byte(info)) + if err != nil { + c.Debugf("Error reading remote leafnode's INFO: %s", err) + c.closeConnection(ReadError) + return nil + } c.mu.Lock() if !c.flags.isSet(infoReceived) { @@ -785,12 +790,17 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client { return c } -func (c *client) processLeafnodeInfo(info *Info) { +func (c *client) processLeafnodeInfo(info *Info) error { c.mu.Lock() defer c.mu.Unlock() if c.leaf == nil || c.isClosed() { - return + return nil + } + + // Prevent connecting to client port. + if info.ClientConnectURLs != nil { + return ErrLeafConnectedToClientPort } // Mark that the INFO protocol has been received. @@ -810,6 +820,8 @@ func (c *client) processLeafnodeInfo(info *Info) { // representation of the remote cluster's list of URLs. c.updateLeafNodeURLs(info) } + + return nil } // When getting a leaf node INFO protocol, use the provided diff --git a/server/leafnode_test.go b/server/leafnode_test.go index 251ae059..f7f7d484 100644 --- a/server/leafnode_test.go +++ b/server/leafnode_test.go @@ -869,3 +869,66 @@ func TestLeafCloseTLSConnection(t *testing.T) { leaf.closeConnection(SlowConsumerWriteDeadline) ch <- true } + +type captureDebugErrorLogger struct { + DummyLogger + errCh chan string +} + +func (l *captureDebugErrorLogger) Debugf(format string, v ...interface{}) { + select { + case l.errCh <- fmt.Sprintf(format, v...): + default: + } +} + +func TestLeafNodeRemoteWrongPort(t *testing.T) { + port := 8786 + + // Server with the wrong config against other server client's port. + leafURL, _ := url.Parse(fmt.Sprintf("nats://127.0.0.1:%d", port)) + oa := DefaultOptions() + oa.Port = -1 + oa.PingInterval = 15 * time.Millisecond + oa.LeafNode.Remotes = []*RemoteLeafOpts{{URLs: []*url.URL{leafURL}}} + sa := RunServer(oa) + defer sa.Shutdown() + l := &captureDebugErrorLogger{errCh: make(chan string, 10)} + sa.SetLogger(l, true, true) + + // Make a cluster so that connect_urls is gossiped to clients. + ob := DefaultOptions() + ob.PingInterval = 15 * time.Millisecond + ob.Host = "127.0.0.1" + ob.Port = -1 + ob.Cluster = ClusterOpts{ + Host: "127.0.0.1", + Port: -1, + } + sb := RunServer(ob) + defer sb.Shutdown() + + oc := DefaultOptions() + oc.PingInterval = 15 * time.Millisecond + oc.Host = "127.0.0.1" + oc.Port = port + oc.Cluster = ClusterOpts{ + Host: "127.0.0.1", + Port: -1, + } + routeURL, _ := url.Parse(fmt.Sprintf("nats://127.0.0.1:%d", ob.Cluster.Port)) + oc.Routes = []*url.URL{routeURL} + sc := RunServer(oc) + defer sc.Shutdown() + + for { + select { + case e := <-l.errCh: + if strings.Contains(e, `attempted to connect to client port`) { + return + } + case <-time.After(2 * time.Second): + t.Fatalf("Did not get any error about connecting to client port") + } + } +}