Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add netcheck
  • Loading branch information
ethanndickson committed Jul 2, 2024
commit 5c0f30ca668682acbc94546c7baf43782f192bfc
8 changes: 4 additions & 4 deletions tailnet/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ func (c *Conn) AwaitReachable(ctx context.Context, ip netip.Addr) bool {
case <-completedCtx.Done():
// TODO(ethanndickson): For now, I'm interpreting 'connected' as when the
// agent is reachable.
_ = c.connectedTelemetryEvent()
// _ = c.connectedTelemetryEvent()
return true
case <-t.C:
// Pings can take a while, so we can run multiple
Expand Down Expand Up @@ -735,16 +735,16 @@ func (c *Conn) newTelemetryEvent() (*proto.TelemetryEvent, error) {
return nil, xerrors.Errorf("marshal uuid to bytes: %w", err)
}

logs, ips, dm, ni := c.telemeteryStore.getStore()
logs, ips, dm, nc := c.telemeteryStore.getStore()
return &proto.TelemetryEvent{
Id: id,
Time: timestamppb.Now(),
ClientType: c.clientType,
NodeIdSelf: uint64(c.nodeID),
Logs: logs,
LogIpHashes: ips,
DerpMap: DERPMapToProto(dm),
LatestNetcheck: NetInfoToProto(ni),
DerpMap: dm,
LatestNetcheck: nc,

// TODO:
Application: "",
Expand Down
48 changes: 47 additions & 1 deletion tailnet/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ package tailnet

import (
"net/netip"
"strconv"
"strings"
"time"

"github.com/google/uuid"
"golang.org/x/xerrors"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"tailscale.com/tailcfg"
"tailscale.com/types/key"

Expand Down Expand Up @@ -275,8 +280,49 @@ func NetInfoToProto(netInfo *tailcfg.NetInfo) *proto.Netcheck {
if netInfo == nil {
return nil
}
rlv4 := make(map[int64]*durationpb.Duration)
rlv6 := make(map[int64]*durationpb.Duration)
for k, seconds := range netInfo.DERPLatency {
res := strings.Split(k, "-")
if len(res) != 2 {
continue
}

rid, err := strconv.ParseInt(res[0], 10, 64)
if err != nil {
continue
}

dur := time.Duration(seconds * float64(time.Second))

switch res[1] {
case "v4":
rlv4[rid] = durationpb.New(dur)
case "v6":
rlv6[rid] = durationpb.New(dur)
}
}
return &proto.Netcheck{
// TODO:
UDP: netInfo.WorkingUDP.EqualBool(true),
IPv6CanSend: netInfo.WorkingIPv6.EqualBool(true),
OSHasIPv6: netInfo.OSHasIPv6.EqualBool(true),
ICMPv4: netInfo.WorkingICMPv4.EqualBool(true),
MappingVariesByDestIP: wrapperspb.Bool(netInfo.MappingVariesByDestIP.EqualBool(true)),
HairPinning: wrapperspb.Bool(netInfo.HairPinning.EqualBool(true)),
UPnP: wrapperspb.Bool(netInfo.UPnP.EqualBool(true)),
PMP: wrapperspb.Bool(netInfo.PMP.EqualBool(true)),
PCP: wrapperspb.Bool(netInfo.PCP.EqualBool(true)),
PreferredDERP: int64(netInfo.PreferredDERP),
RegionV4Latency: rlv4,
RegionV6Latency: rlv6,
// TODO: what's the most useful value to have here?
RegionLatency: make(map[int64]*durationpb.Duration),
// TODO: None of these are exposed by tailscale
IPv4CanSend: false,
IPv4: false,
IPv6: false,
GlobalV4: &proto.Netcheck_NetcheckIP{},
GlobalV6: &proto.Netcheck_NetcheckIP{},
CaptivePortal: &wrapperspb.BoolValue{},
}
}
12 changes: 6 additions & 6 deletions tailnet/logger_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,12 @@ func TestTelemetryStore(t *testing.T) {
require.Len(t, dm.Regions[999].Nodes, 1)
node := dm.Regions[999].Nodes[0]
require.NotContains(t, node.HostName, "coolderp.com")
require.NotContains(t, node.IPv4, "1.2.3.4")
require.NotContains(t, node.IPv6, "2001:db8::1")
require.NotContains(t, node.STUNTestIP, "5.6.7.8")
require.NotContains(t, node.Ipv4, "1.2.3.4")
require.NotContains(t, node.Ipv6, "2001:db8::1")
require.NotContains(t, node.StunTestIp, "5.6.7.8")
require.Contains(t, logs[0], node.HostName)
require.Contains(t, ips, node.STUNTestIP)
require.Contains(t, ips, node.IPv6)
require.Contains(t, ips, node.IPv4)
require.Contains(t, ips, node.StunTestIp)
require.Contains(t, ips, node.Ipv6)
require.Contains(t, ips, node.Ipv4)
})
}
7 changes: 3 additions & 4 deletions tailnet/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ func newTelemetryStore() (*TelemetryStore, error) {

// getStore returns a deep copy of all current telemetry state.
// TODO: Should this return a populated event instead?
func (b *TelemetryStore) getStore() ([]string, map[string]*proto.IPFields, *tailcfg.DERPMap, *tailcfg.NetInfo) {
func (b *TelemetryStore) getStore() ([]string, map[string]*proto.IPFields, *proto.DERPMap, *proto.Netcheck) {
b.mu.Lock()
defer b.mu.Unlock()
return append([]string{}, b.logs...), b.hashedIPs, b.cleanDerpMap.Clone(), b.netInfo.Clone()
return append([]string{}, b.logs...), b.hashedIPs, DERPMapToProto(b.cleanDerpMap), NetInfoToProto(b.netInfo)
}

// Given a DERPMap, anonymise all IPs and hostnames.
Expand Down Expand Up @@ -167,8 +167,7 @@ func (b *TelemetryStore) updateDerpMap(cur *tailcfg.DERPMap) {
func (b *TelemetryStore) setNetInfo(ni *tailcfg.NetInfo) {
b.mu.Lock()
defer b.mu.Unlock()
// TODO: Scrub PII from NetInfo
b.netInfo = ni
b.netInfo = ni.Clone()
}

// Write implements io.Writer.
Expand Down