Add check prevent leafnode connecting to client port

Signed-off-by: Waldemar Quevedo <wally@synadia.com>
This commit is contained in:
Waldemar Quevedo
2020-01-28 10:42:14 -08:00
parent 308037e8ea
commit ecb5008fe3
4 changed files with 83 additions and 4 deletions

View File

@@ -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
}

View File

@@ -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")

View File

@@ -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

View File

@@ -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")
}
}
}