wgengine/magicsock: gather physical-layer statistics (#5925)
There is utility in logging traffic statistics that occurs at the physical layer. That is, in order to send packets virtually to a particular tailscale IP address, what physical endpoints did we need to communicate with? This functionality logs IP addresses identical to what had always been logged in magicsock prior to #5823, so there is no increase in PII being logged. ExtractStatistics returns a mapping of connections to counts. The source is always a Tailscale IP address (without port), while the destination is some endpoint reachable on WAN or LAN. As a special case, traffic routed through DERP will use 127.3.3.40 as the destination address with the port being the DERP region. This entire feature is only enabled if data-plane audit logging is enabled on the tailnet (by default it is disabled). Example of type of information logged: ------------------------------------ Tx[P/s] Tx[B/s] Rx[P/s] Rx[B/s] PhysicalTraffic: 25.80 3.39Ki 38.80 5.57Ki 100.1.2.3 -> 143.11.22.33:41641 15.40 2.00Ki 23.20 3.37Ki 100.4.5.6 -> 192.168.0.100:41641 10.20 1.38Ki 15.60 2.20Ki 100.7.8.9 -> 127.3.3.40:2 0.20 6.40 0.00 0.00 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
@@ -28,6 +28,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"go4.org/mem"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/tuntest"
|
||||
"tailscale.com/derp"
|
||||
@@ -42,6 +43,7 @@ import (
|
||||
"tailscale.com/tstest/natlab"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/netlogtype"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/types/nettype"
|
||||
"tailscale.com/util/cibuild"
|
||||
@@ -1093,17 +1095,45 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
||||
}
|
||||
}
|
||||
|
||||
m1.conn.SetStatisticsEnabled(true)
|
||||
m2.conn.SetStatisticsEnabled(true)
|
||||
|
||||
checkStats := func(t *testing.T, m *magicStack, wantConns []netlogtype.Connection) {
|
||||
stats := m.conn.ExtractStatistics()
|
||||
for _, conn := range wantConns {
|
||||
if _, ok := stats[conn]; ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Helper()
|
||||
t.Errorf("missing any connection to %s from %s", wantConns, maps.Keys(stats))
|
||||
}
|
||||
|
||||
addrPort := netip.MustParseAddrPort
|
||||
m1Conns := []netlogtype.Connection{
|
||||
{Src: addrPort("1.0.0.2:0"), Dst: m2.conn.pconn4.LocalAddr().AddrPort()},
|
||||
{Src: addrPort("1.0.0.2:0"), Dst: addrPort("127.3.3.40:1")},
|
||||
}
|
||||
m2Conns := []netlogtype.Connection{
|
||||
{Src: addrPort("1.0.0.1:0"), Dst: m1.conn.pconn4.LocalAddr().AddrPort()},
|
||||
{Src: addrPort("1.0.0.1:0"), Dst: addrPort("127.3.3.40:1")},
|
||||
}
|
||||
|
||||
outerT := t
|
||||
t.Run("ping 1.0.0.1", func(t *testing.T) {
|
||||
setT(t)
|
||||
defer setT(outerT)
|
||||
ping1(t)
|
||||
checkStats(t, m1, m1Conns)
|
||||
checkStats(t, m2, m2Conns)
|
||||
})
|
||||
|
||||
t.Run("ping 1.0.0.2", func(t *testing.T) {
|
||||
setT(t)
|
||||
defer setT(outerT)
|
||||
ping2(t)
|
||||
checkStats(t, m1, m1Conns)
|
||||
checkStats(t, m2, m2Conns)
|
||||
})
|
||||
|
||||
t.Run("ping 1.0.0.2 via SendPacket", func(t *testing.T) {
|
||||
@@ -1120,6 +1150,8 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
||||
if err := sendWithTimeout(msg1to2, in, send); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
checkStats(t, m1, m1Conns)
|
||||
checkStats(t, m2, m2Conns)
|
||||
})
|
||||
|
||||
t.Run("no-op dev1 reconfig", func(t *testing.T) {
|
||||
@@ -1130,6 +1162,8 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
||||
}
|
||||
ping1(t)
|
||||
ping2(t)
|
||||
checkStats(t, m1, m1Conns)
|
||||
checkStats(t, m2, m2Conns)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user