tsnet: add CapturePcap method for debugging

Application code can call the tsnet s.CapturePcap(filename) method
to write all packets, sent and received, to a pcap file. The cleartext
packets are written, outside the Wireguard tunnel. This is expected
to be useful for debugging.

Updates https://github.com/tailscale/tailscale/issues/9707

Signed-off-by: Denton Gentry <dgentry@tailscale.com>
This commit is contained in:
Denton Gentry
2023-11-24 07:26:50 -08:00
committed by Denton Gentry
parent b247435d66
commit 67f3b2a525
2 changed files with 82 additions and 0 deletions

View File

@@ -691,3 +691,56 @@ func TestFallbackTCPHandler(t *testing.T) {
t.Errorf("s1TcpConnCount = %d, want %d", got, 1)
}
}
func TestCapturePcap(t *testing.T) {
const timeLimit = 120
ctx, cancel := context.WithTimeout(context.Background(), timeLimit*time.Second)
defer cancel()
dir := t.TempDir()
s1Pcap := filepath.Join(dir, "s1.pcap")
s2Pcap := filepath.Join(dir, "s2.pcap")
controlURL, _ := startControl(t)
s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
s2, _, _ := startServer(t, ctx, controlURL, "s2")
s1.CapturePcap(ctx, s1Pcap)
s2.CapturePcap(ctx, s2Pcap)
lc2, err := s2.LocalClient()
if err != nil {
t.Fatal(err)
}
// send a packet which both nodes will capture
res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
if err != nil {
t.Fatal(err)
}
t.Logf("ping success: %#+v", res)
fileSize := func(name string) int64 {
fi, err := os.Stat(name)
if err != nil {
return 0
}
return fi.Size()
}
const pcapHeaderSize = 24
// there is a lag before the io.Copy writes a packet to the pcap files
for i := 0; i < (timeLimit * 10); i++ {
time.Sleep(100 * time.Millisecond)
if (fileSize(s1Pcap) > pcapHeaderSize) && (fileSize(s2Pcap) > pcapHeaderSize) {
break
}
}
if got := fileSize(s1Pcap); got <= pcapHeaderSize {
t.Errorf("s1 pcap file size = %d, want > pcapHeaderSize(%d)", got, pcapHeaderSize)
}
if got := fileSize(s2Pcap); got <= pcapHeaderSize {
t.Errorf("s2 pcap file size = %d, want > pcapHeaderSize(%d)", got, pcapHeaderSize)
}
}