Bladeren bron

wgengine/netlog: embed the StableNodeID of the authoring node (#6105)

This allows network messages to be annotated with which node it came from.

Signed-off-by: Joe Tsai <[email protected]>
Joe Tsai 3 jaren geleden
bovenliggende
commit
a3602c28bd

+ 6 - 0
types/netlogtype/netlogtype.go

@@ -9,11 +9,17 @@ import (
 	"net/netip"
 	"net/netip"
 	"time"
 	"time"
 
 
+	"tailscale.com/tailcfg"
 	"tailscale.com/types/ipproto"
 	"tailscale.com/types/ipproto"
 )
 )
 
 
+// TODO(joetsai): Remove "omitempty" if "omitzero" is ever supported in both
+// the v1 and v2 "json" packages.
+
 // Message is the log message that captures network traffic.
 // Message is the log message that captures network traffic.
 type Message struct {
 type Message struct {
+	NodeID tailcfg.StableNodeID `json:"nodeId"` // e.g., "n123456CNTRL"
+
 	Start time.Time `json:"start"` // inclusive
 	Start time.Time `json:"start"` // inclusive
 	End   time.Time `json:"end"`   // inclusive
 	End   time.Time `json:"end"`   // inclusive
 
 

+ 7 - 6
wgengine/netlog/logger.go

@@ -22,6 +22,7 @@ import (
 	"tailscale.com/logtail"
 	"tailscale.com/logtail"
 	"tailscale.com/net/tsaddr"
 	"tailscale.com/net/tsaddr"
 	"tailscale.com/smallzstd"
 	"tailscale.com/smallzstd"
+	"tailscale.com/tailcfg"
 	"tailscale.com/types/netlogtype"
 	"tailscale.com/types/netlogtype"
 	"tailscale.com/wgengine/router"
 	"tailscale.com/wgengine/router"
 )
 )
@@ -91,7 +92,7 @@ var testClient *http.Client
 // is a non-tailscale IP address to contact for that particular tailscale node.
 // is a non-tailscale IP address to contact for that particular tailscale node.
 // The IP protocol and source port are always zero.
 // The IP protocol and source port are always zero.
 // The sock is used to populated the PhysicalTraffic field in Message.
 // The sock is used to populated the PhysicalTraffic field in Message.
-func (nl *Logger) Startup(nodeID, domainID logtail.PrivateID, tun, sock Device) error {
+func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID logtail.PrivateID, tun, sock Device) error {
 	nl.mu.Lock()
 	nl.mu.Lock()
 	defer nl.mu.Unlock()
 	defer nl.mu.Unlock()
 	if nl.logger != nil {
 	if nl.logger != nil {
@@ -110,8 +111,8 @@ func (nl *Logger) Startup(nodeID, domainID logtail.PrivateID, tun, sock Device)
 	}
 	}
 	logger := logtail.NewLogger(logtail.Config{
 	logger := logtail.NewLogger(logtail.Config{
 		Collection:    "tailtraffic.log.tailscale.io",
 		Collection:    "tailtraffic.log.tailscale.io",
-		PrivateID:     nodeID,
-		CopyPrivateID: domainID,
+		PrivateID:     nodeLogID,
+		CopyPrivateID: domainLogID,
 		Stderr:        io.Discard,
 		Stderr:        io.Discard,
 		// TODO(joetsai): Set Buffer? Use an in-memory buffer for now.
 		// TODO(joetsai): Set Buffer? Use an in-memory buffer for now.
 		NewZstdEncoder: func() logtail.Encoder {
 		NewZstdEncoder: func() logtail.Encoder {
@@ -161,7 +162,7 @@ func (nl *Logger) Startup(nodeID, domainID logtail.PrivateID, tun, sock Device)
 				addrs := nl.addrs
 				addrs := nl.addrs
 				prefixes := nl.prefixes
 				prefixes := nl.prefixes
 				nl.mu.Unlock()
 				nl.mu.Unlock()
-				recordStatistics(logger, start, end, tunStats, sockStats, addrs, prefixes)
+				recordStatistics(logger, nodeID, start, end, tunStats, sockStats, addrs, prefixes)
 			}
 			}
 
 
 			if ctx.Err() != nil {
 			if ctx.Err() != nil {
@@ -174,8 +175,8 @@ func (nl *Logger) Startup(nodeID, domainID logtail.PrivateID, tun, sock Device)
 	return nil
 	return nil
 }
 }
 
 
-func recordStatistics(logger *logtail.Logger, start, end time.Time, tunStats, sockStats map[netlogtype.Connection]netlogtype.Counts, addrs map[netip.Addr]bool, prefixes map[netip.Prefix]bool) {
-	m := netlogtype.Message{Start: start.UTC(), End: end.UTC()}
+func recordStatistics(logger *logtail.Logger, nodeID tailcfg.StableNodeID, start, end time.Time, tunStats, sockStats map[netlogtype.Connection]netlogtype.Counts, addrs map[netip.Addr]bool, prefixes map[netip.Prefix]bool) {
+	m := netlogtype.Message{NodeID: nodeID, Start: start.UTC(), End: end.UTC()}
 
 
 	classifyAddr := func(a netip.Addr) (isTailscale, withinRoute bool) {
 	classifyAddr := func(a netip.Addr) (isTailscale, withinRoute bool) {
 		// NOTE: There could be mis-classifications where an address is treated
 		// NOTE: There could be mis-classifications where an address is treated

+ 1 - 1
wgengine/netlog/logger_test.go

@@ -58,7 +58,7 @@ func TestResourceCheck(t *testing.T) {
 	var l Logger
 	var l Logger
 	var d fakeDevice
 	var d fakeDevice
 	for i := 0; i < 10; i++ {
 	for i := 0; i < 10; i++ {
-		must.Do(l.Startup(logtail.PrivateID{}, logtail.PrivateID{}, &d, nil))
+		must.Do(l.Startup("", logtail.PrivateID{}, logtail.PrivateID{}, &d, nil))
 		l.ReconfigRoutes(&router.Config{})
 		l.ReconfigRoutes(&router.Config{})
 		must.Do(l.Shutdown(context.Background()))
 		must.Do(l.Shutdown(context.Background()))
 		c.Assert(d.toggled, qt.Equals, 2*(i+1))
 		c.Assert(d.toggled, qt.Equals, 2*(i+1))

+ 1 - 1
wgengine/userspace.go

@@ -953,7 +953,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config,
 		nid := cfg.NetworkLogging.NodeID
 		nid := cfg.NetworkLogging.NodeID
 		tid := cfg.NetworkLogging.DomainID
 		tid := cfg.NetworkLogging.DomainID
 		e.logf("wgengine: Reconfig: starting up network logger (node:%s tailnet:%s)", nid.Public(), tid.Public())
 		e.logf("wgengine: Reconfig: starting up network logger (node:%s tailnet:%s)", nid.Public(), tid.Public())
-		if err := e.networkLogger.Startup(nid, tid, e.tundev, e.magicConn); err != nil {
+		if err := e.networkLogger.Startup(cfg.NodeID, nid, tid, e.tundev, e.magicConn); err != nil {
 			e.logf("wgengine: Reconfig: error starting up network logger: %v", err)
 			e.logf("wgengine: Reconfig: error starting up network logger: %v", err)
 		}
 		}
 	}
 	}

+ 2 - 0
wgengine/wgcfg/config.go

@@ -9,6 +9,7 @@ import (
 	"net/netip"
 	"net/netip"
 
 
 	"tailscale.com/logtail"
 	"tailscale.com/logtail"
+	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/key"
 )
 )
 
 
@@ -18,6 +19,7 @@ import (
 // It only supports the set of things Tailscale uses.
 // It only supports the set of things Tailscale uses.
 type Config struct {
 type Config struct {
 	Name       string
 	Name       string
+	NodeID     tailcfg.StableNodeID
 	PrivateKey key.NodePrivate
 	PrivateKey key.NodePrivate
 	Addresses  []netip.Prefix
 	Addresses  []netip.Prefix
 	MTU        uint16
 	MTU        uint16

+ 1 - 0
wgengine/wgcfg/nmcfg/nmcfg.go

@@ -62,6 +62,7 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
 
 
 	// Setup log IDs for data plane audit logging.
 	// Setup log IDs for data plane audit logging.
 	if nm.SelfNode != nil {
 	if nm.SelfNode != nil {
+		cfg.NodeID = nm.SelfNode.StableID
 		canNetworkLog := slices.Contains(nm.SelfNode.Capabilities, tailcfg.CapabilityDataPlaneAuditLogs)
 		canNetworkLog := slices.Contains(nm.SelfNode.Capabilities, tailcfg.CapabilityDataPlaneAuditLogs)
 		if canNetworkLog && nm.SelfNode.DataPlaneAuditLogID != "" && nm.DomainAuditLogID != "" {
 		if canNetworkLog && nm.SelfNode.DataPlaneAuditLogID != "" && nm.DomainAuditLogID != "" {
 			nodeID, errNode := logtail.ParsePrivateID(nm.SelfNode.DataPlaneAuditLogID)
 			nodeID, errNode := logtail.ParsePrivateID(nm.SelfNode.DataPlaneAuditLogID)

+ 2 - 0
wgengine/wgcfg/wgcfg_clone.go

@@ -10,6 +10,7 @@ import (
 	"net/netip"
 	"net/netip"
 
 
 	"tailscale.com/logtail"
 	"tailscale.com/logtail"
+	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/key"
 )
 )
 
 
@@ -33,6 +34,7 @@ func (src *Config) Clone() *Config {
 // A compilation failure here means this code must be regenerated, with the command at the top of this file.
 // A compilation failure here means this code must be regenerated, with the command at the top of this file.
 var _ConfigCloneNeedsRegeneration = Config(struct {
 var _ConfigCloneNeedsRegeneration = Config(struct {
 	Name           string
 	Name           string
+	NodeID         tailcfg.StableNodeID
 	PrivateKey     key.NodePrivate
 	PrivateKey     key.NodePrivate
 	Addresses      []netip.Prefix
 	Addresses      []netip.Prefix
 	MTU            uint16
 	MTU            uint16