The AllowedPublicKeys option should not apply to multicast listeners

Another fix for #1141.
This commit is contained in:
Neil Alexander 2024-09-29 21:38:56 +01:00
parent d1b849588f
commit 377bc664c9
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
4 changed files with 28 additions and 19 deletions

View File

@ -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 // 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. // link-local address, the interface should be provided as the second argument.
func (c *Core) Listen(u *url.URL, sintf string) (*Listener, error) { 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 // Address gets the IPv6 address of the Yggdrasil node. This is always a /128

View File

@ -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) c.log.Errorf("Invalid listener URI %q specified, ignoring\n", listenaddr)
continue 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) c.log.Errorf("Failed to start listener %q: %s\n", listenaddr, err)
} }
} }

View File

@ -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 // Give the connection to the handler. The handler will block
// for the lifetime of the connection. // 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) 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 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) ctx, cancel := context.WithCancel(l.core.ctx)
var protocol linkProtocol var protocol linkProtocol
switch strings.ToLower(u.Scheme) { 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 // Give the connection to the handler. The handler will block
// for the lifetime of the connection. // 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 err == nil:
case errors.Is(err, io.EOF): case errors.Is(err, io.EOF):
case errors.Is(err, net.ErrClosed): 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) 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 := version_getBaseMetadata()
meta.publicKey = l.core.public meta.publicKey = l.core.public
meta.priority = options.priority 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 // Check if we're authorized to connect to this key / IP
var allowed map[[32]byte]struct{} if !local {
phony.Block(l.core, func() { var allowed map[[32]byte]struct{}
allowed = l.core.config._allowedPublicKeys phony.Block(l.core, func() {
}) allowed = l.core.config._allowedPublicKeys
isallowed := len(allowed) == 0 })
for k := range allowed { isallowed := len(allowed) == 0
if bytes.Equal(k[:], meta.publicKey) { for k := range allowed {
isallowed = true if bytes.Equal(k[:], meta.publicKey) {
break 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" dir := "outbound"

View File

@ -327,7 +327,7 @@ func (m *Multicast) _announce() {
Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)), Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)),
RawQuery: v.Encode(), 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) m.log.Debugln("Started multicasting on", iface.Name)
// Store the listener so that we can stop it later if needed // Store the listener so that we can stop it later if needed
linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port} linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port}