wiresharktcpdump

piping tcpdump from a docker container to local macOS Wireshark instance


I've attached a tcpdump sidecar to one of my containers and I'm trying feed the capture into a local instance of Wireshark on macOS.

This kicks back pretty much as soon as it starts, with the Frame 1 too long error:

# docker exec -it tcpdump-tcpdump-1 tcpdump -s 0 -Un -i eth0 -w - | wireshark -k -i -
 ** (wireshark:69470) 17:53:07.939482 [GUI WARNING] -- Populating font family aliases took 112 ms. Replace uses of missing font family ".AppleSystemUIFont" with one that exists to avoid this cost.
 ** (wireshark:69470) 17:53:09.214024 [Capture MESSAGE] -- Capture Start ...
 ** (wireshark:69470) 17:53:09.295301 [Capture MESSAGE] -- Capture started
 ** (wireshark:69470) 17:53:09.295325 [Capture MESSAGE] -- File: "/var/folders/ht/pffb_rd133jd1x12w50hdzcr0000gn/T/wireshark_-4ATK31.pcapng"
 ** (wireshark:69470) 17:53:09.348556 [Capture MESSAGE] -- Error message from child: "Frame 1 too long (1936288800 bytes)", ""
 ** (wireshark:69470) 17:53:12.191059 [Capture MESSAGE] -- Capture stopped.
#

Removing Wireshark from the equation, piping it directly to tcpdump doesn't decode the packet like I'm expecting it to either:

# tcpdump -s 0 -Un -i en0 -c 1 -w - | tcpdump -r -
tcpdump: listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes
tcpdump: unknown file format
1 packet captured
80 packets received by filter
0 packets dropped by kernel
%
#

Omitting the pipe works, so I can be fairly confident that everything is being passed around intact:

# docker exec -it tcpdump-tcpdump-1 tcpdump -s 0 -Un -i eth0 -c 1
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
22:02:04.419247 IP 172.21.0.1.56032 > 172.21.0.7.389: Flags [S], seq 167416269, win 65495, options [mss 65495,sackOK,TS val 78109604 ecr 0,nop,wscale 7], length 0
1 packet captured
10 packets received by filter
0 packets dropped by kernel
#

I was supposing the "unknown file format" was important, so I tried with -P to force the read and write to apple pcapng with no joy.

# tcpdump -P -s 0 -Un -i en0 -c 1 -w - | tcpdump -Pr -
tcpdump: listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes
tcpdump: 1 packet captured
unknown file format
38 packets received by filter
0 packets dropped by kernel
%
#

I'm missing something that I can't put my finger on.


Solution

  • Try removing -it from your docker exec.

    The -t argument is probably the culprit, as it tells Docker to impersonate an interactive terminal, which, when detected via probing, nudges many apps into emitting user-friendly codes that don't suit programmatic ingestion via piping.

    Usually non-interactive contexts are detectable by the source app automatically (ie if you use a pipe, a clever program will know and adapt), but the additional layer of indirection introduced by Docker defeats this probing, meaning you can't just pipe and expect things to work - you also need to explicitly choose the right context to match.

    Meanwhile, the -i, which usually comes as a pair with the above, won't be breaking anything, but isn't necessary unless you're piping something in to the app (or using it interactively)