mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-22 13:37:10 +00:00
wgengine/netlog: embed node information in network flow logs (#17668)
This rewrites the netlog package to support embedding node information in network flow logs. Some bit of complexity comes in trying to pre-compute the expected size of the log message after JSON serialization to ensure that we can respect maximum body limits in log uploading. We also fix a bug in tstun, where we were recording the IP address after SNAT, which was resulting in non-sensible connection flows being logged. Updates tailscale/corp#33352 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
@@ -21,6 +21,9 @@ type Message struct {
|
||||
Start time.Time `json:"start"` // inclusive
|
||||
End time.Time `json:"end"` // inclusive
|
||||
|
||||
SrcNode Node `json:"srcNode,omitzero"`
|
||||
DstNodes []Node `json:"dstNodes,omitempty"`
|
||||
|
||||
VirtualTraffic []ConnectionCounts `json:"virtualTraffic,omitempty"`
|
||||
SubnetTraffic []ConnectionCounts `json:"subnetTraffic,omitempty"`
|
||||
ExitTraffic []ConnectionCounts `json:"exitTraffic,omitempty"`
|
||||
@@ -28,14 +31,30 @@ type Message struct {
|
||||
}
|
||||
|
||||
const (
|
||||
messageJSON = `{"nodeId":"n0123456789abcdefCNTRL",` + maxJSONTimeRange + `,` + minJSONTraffic + `}`
|
||||
messageJSON = `{"nodeId":` + maxJSONStableID + `,` + minJSONNodes + `,` + maxJSONTimeRange + `,` + minJSONTraffic + `}`
|
||||
maxJSONStableID = `"n0123456789abcdefCNTRL"`
|
||||
minJSONNodes = `"srcNode":{},"dstNodes":[]`
|
||||
maxJSONTimeRange = `"start":` + maxJSONRFC3339 + `,"end":` + maxJSONRFC3339
|
||||
maxJSONRFC3339 = `"0001-01-01T00:00:00.000000000Z"`
|
||||
minJSONTraffic = `"virtualTraffic":{},"subnetTraffic":{},"exitTraffic":{},"physicalTraffic":{}`
|
||||
|
||||
// MaxMessageJSONSize is the overhead size of Message when it is
|
||||
// serialized as JSON assuming that each traffic map is populated.
|
||||
MaxMessageJSONSize = len(messageJSON)
|
||||
// MinMessageJSONSize is the overhead size of Message when it is
|
||||
// serialized as JSON assuming that each field is minimally populated.
|
||||
// Each [Node] occupies at least [MinNodeJSONSize].
|
||||
// Each [ConnectionCounts] occupies at most [MaxConnectionCountsJSONSize].
|
||||
MinMessageJSONSize = len(messageJSON)
|
||||
|
||||
nodeJSON = `{"nodeId":` + maxJSONStableID + `,"name":"","addresses":` + maxJSONAddrs + `,"user":"","tags":[]}`
|
||||
maxJSONAddrV4 = `"255.255.255.255"`
|
||||
maxJSONAddrV6 = `"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"`
|
||||
maxJSONAddrs = `[` + maxJSONAddrV4 + `,` + maxJSONAddrV6 + `]`
|
||||
|
||||
// MinNodeJSONSize is the overhead size of Node when it is
|
||||
// serialized as JSON assuming that each field is minimally populated.
|
||||
// It does not account for bytes occupied by
|
||||
// [Node.Name], [Node.User], or [Node.Tags]. The [Node.Addresses]
|
||||
// is assumed to contain a pair of IPv4 and IPv6 address.
|
||||
MinNodeJSONSize = len(nodeJSON)
|
||||
|
||||
maxJSONConnCounts = `{` + maxJSONConn + `,` + maxJSONCounts + `}`
|
||||
maxJSONConn = `"proto":` + maxJSONProto + `,"src":` + maxJSONAddrPort + `,"dst":` + maxJSONAddrPort
|
||||
@@ -52,6 +71,26 @@ const (
|
||||
MaxConnectionCountsJSONSize = len(maxJSONConnCounts)
|
||||
)
|
||||
|
||||
// Node is information about a node.
|
||||
type Node struct {
|
||||
// NodeID is the stable ID of the node.
|
||||
NodeID tailcfg.StableNodeID `json:"nodeId"`
|
||||
|
||||
// Name is the fully-qualified name of the node.
|
||||
Name string `json:"name,omitzero"` // e.g., "carbonite.example.ts.net"
|
||||
|
||||
// Addresses are the Tailscale IP addresses of the node.
|
||||
Addresses []netip.Addr `json:"addresses,omitempty"`
|
||||
|
||||
// User is the user that owns the node.
|
||||
// It is not populated if the node is tagged.
|
||||
User string `json:"user,omitzero"` // e.g., "johndoe@example.com"
|
||||
|
||||
// Tags are the tags of the node.
|
||||
// It is not populated if the node is owned by a user.
|
||||
Tags []string `json:"tags,omitempty"` // e.g., ["tag:prod","tag:logs"]
|
||||
}
|
||||
|
||||
// ConnectionCounts is a flattened struct of both a connection and counts.
|
||||
type ConnectionCounts struct {
|
||||
Connection
|
||||
|
||||
Reference in New Issue
Block a user