From 377bc664c9b2458ea2906fd9e4f3a6788cd1327f Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 29 Sep 2024 21:38:56 +0100 Subject: [PATCH] The `AllowedPublicKeys` option should not apply to multicast listeners Another fix for #1141. --- src/core/api.go | 9 ++++++++- src/core/core.go | 2 +- src/core/link.go | 34 ++++++++++++++++++---------------- src/multicast/multicast.go | 2 +- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/core/api.go b/src/core/api.go index c236b1b5..2aa1ba87 100644 --- a/src/core/api.go +++ b/src/core/api.go @@ -150,7 +150,14 @@ func (c *Core) GetSessions() []SessionInfo { // parsed from a string of the form e.g. "tcp://a.b.c.d:e". In the case of a // link-local address, the interface should be provided as the second argument. func (c *Core) Listen(u *url.URL, sintf string) (*Listener, error) { - return c.links.listen(u, sintf) + return c.links.listen(u, sintf, false) +} + +// ListenLocal starts a listener, like the Listen function, but is used for +// more trustworthy situations where you want to ignore AllowedPublicKeys, i.e. +// with multicast listeners. +func (c *Core) ListenLocal(u *url.URL, sintf string) (*Listener, error) { + return c.links.listen(u, sintf, true) } // Address gets the IPv6 address of the Yggdrasil node. This is always a /128 diff --git a/src/core/core.go b/src/core/core.go index 41858cb1..2b206ee1 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -127,7 +127,7 @@ func New(cert *tls.Certificate, logger Logger, opts ...SetupOption) (*Core, erro c.log.Errorf("Invalid listener URI %q specified, ignoring\n", listenaddr) continue } - if _, err = c.links.listen(u, ""); err != nil { + if _, err = c.links.listen(u, "", false); err != nil { c.log.Errorf("Failed to start listener %q: %s\n", listenaddr, err) } } diff --git a/src/core/link.go b/src/core/link.go index 66cf517d..04fe0266 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -336,7 +336,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error { // Give the connection to the handler. The handler will block // for the lifetime of the connection. - if err = l.handler(linkType, options, lc, resetBackoff); err != nil && err != io.EOF { + if err = l.handler(linkType, options, lc, resetBackoff, false); err != nil && err != io.EOF { l.core.log.Debugf("Link %s error: %s\n", info.uri, err) } @@ -395,7 +395,7 @@ func (l *links) remove(u *url.URL, sintf string, _ linkType) error { return retErr } -func (l *links) listen(u *url.URL, sintf string) (*Listener, error) { +func (l *links) listen(u *url.URL, sintf string, local bool) (*Listener, error) { ctx, cancel := context.WithCancel(l.core.ctx) var protocol linkProtocol switch strings.ToLower(u.Scheme) { @@ -522,7 +522,7 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) { // Give the connection to the handler. The handler will block // for the lifetime of the connection. - switch err = l.handler(linkTypeIncoming, options, lc, nil); { + switch err = l.handler(linkTypeIncoming, options, lc, nil, local); { case err == nil: case errors.Is(err, io.EOF): case errors.Is(err, net.ErrClosed): @@ -563,7 +563,7 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options return dialer.dial(ctx, u, info, options) } -func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, success func()) error { +func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, success func(), local bool) error { meta := version_getBaseMetadata() meta.publicKey = l.core.public meta.priority = options.priority @@ -606,19 +606,21 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s } } // Check if we're authorized to connect to this key / IP - var allowed map[[32]byte]struct{} - phony.Block(l.core, func() { - allowed = l.core.config._allowedPublicKeys - }) - isallowed := len(allowed) == 0 - for k := range allowed { - if bytes.Equal(k[:], meta.publicKey) { - isallowed = true - break + if !local { + var allowed map[[32]byte]struct{} + phony.Block(l.core, func() { + allowed = l.core.config._allowedPublicKeys + }) + isallowed := len(allowed) == 0 + for k := range allowed { + if bytes.Equal(k[:], meta.publicKey) { + isallowed = true + break + } + } + if linkType == linkTypeIncoming && !isallowed { + return fmt.Errorf("node public key %q is not in AllowedPublicKeys", hex.EncodeToString(meta.publicKey)) } - } - if linkType == linkTypeIncoming && !isallowed { - return fmt.Errorf("node public key %q is not in AllowedPublicKeys", hex.EncodeToString(meta.publicKey)) } dir := "outbound" diff --git a/src/multicast/multicast.go b/src/multicast/multicast.go index 32f5dcad..77ea8a50 100644 --- a/src/multicast/multicast.go +++ b/src/multicast/multicast.go @@ -327,7 +327,7 @@ func (m *Multicast) _announce() { Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)), RawQuery: v.Encode(), } - if li, err := m.core.Listen(u, iface.Name); err == nil { + if li, err := m.core.ListenLocal(u, iface.Name); err == nil { m.log.Debugln("Started multicasting on", iface.Name) // Store the listener so that we can stop it later if needed linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port}