浏览代码

lib/discover: Filter locally announced addresses (fixes #7289) (#8302)

Jakob Borg 3 年之前
父节点
当前提交
f8c51d801a
共有 2 个文件被更改,包括 65 次插入0 次删除
  1. 34 0
      lib/discover/local.go
  2. 31 0
      lib/discover/local_test.go

+ 34 - 0
lib/discover/local.go

@@ -109,6 +109,13 @@ func (c *localClient) Error() error {
 // send.
 func (c *localClient) announcementPkt(instanceID int64, msg []byte) ([]byte, bool) {
 	addrs := c.addrList.AllAddresses()
+
+	// The list of all addresses can include unspecified addresses intended
+	// for a discovery server to complete, based on the packet source. We
+	// don't do that for local discovery, so filter out addresses that are
+	// usable as-is.
+	addrs = filterUnspecifiedLocal(addrs)
+
 	if len(addrs) == 0 {
 		// Nothing to announce
 		return msg, false
@@ -281,3 +288,30 @@ func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
 
 	return isNewDevice
 }
+
+// filterUnspecifiedLocal returns the list of addresses after removing any
+// unspecified, localhost, multicast, broadcast or port-zero addresses.
+func filterUnspecifiedLocal(addrs []string) []string {
+	filtered := addrs[:0]
+	for _, addr := range addrs {
+		u, err := url.Parse(addr)
+		if err != nil {
+			continue
+		}
+
+		tcpAddr, err := net.ResolveTCPAddr("tcp", u.Host)
+		if err != nil {
+			continue
+		}
+
+		switch {
+		case len(tcpAddr.IP) == 0:
+		case tcpAddr.Port == 0:
+		case tcpAddr.IP.IsUnspecified():
+		case !tcpAddr.IP.IsGlobalUnicast() && !tcpAddr.IP.IsLinkLocalUnicast():
+		default:
+			filtered = append(filtered, addr)
+		}
+	}
+	return filtered
+}

+ 31 - 0
lib/discover/local_test.go

@@ -9,6 +9,7 @@ package discover
 import (
 	"bytes"
 	"context"
+	"fmt"
 	"net"
 	"testing"
 
@@ -89,3 +90,33 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
 		t.Fatal("new instance ID should be new")
 	}
 }
+
+func TestFilterUnspecified(t *testing.T) {
+	addrs := []string{
+		"quic://[2001:db8::1]:22000",             // OK
+		"tcp://192.0.2.42:22000",                 // OK
+		"quic://[2001:db8::1]:0",                 // remove, port zero
+		"tcp://192.0.2.42:0",                     // remove, port zero
+		"quic://[::]:22000",                      // remove, unspecified
+		"tcp://0.0.0.0:22000",                    // remove, unspecified
+		"tcp://[2001:db8::1]",                    // remove, no port
+		"tcp://192.0.2.42",                       // remove, no port
+		"tcp://foo:bar",                          // remove, host/port does not resolve
+		"tcp://127.0.0.1:22000",                  // remove, not usable from outside
+		"tcp://[::1]:22000",                      // remove, not usable from outside
+		"tcp://224.1.2.3:22000",                  // remove, not usable from outside (multicast)
+		"tcp://[fe80::9ef:dff1:b332:5e56]:55681", // OK
+		"pure garbage",                           // remove, garbage
+		"",                                       // remove, garbage
+	}
+	exp := []string{
+		"quic://[2001:db8::1]:22000",
+		"tcp://192.0.2.42:22000",
+		"tcp://[fe80::9ef:dff1:b332:5e56]:55681",
+	}
+	res := filterUnspecifiedLocal(addrs)
+	if fmt.Sprint(res) != fmt.Sprint(exp) {
+		t.Log(res)
+		t.Error("filterUnspecified returned invalid addresses")
+	}
+}