Running Wireshark on Docker

Docker runs with a variety of networking models which involve networking namespaces, forwarding rules, virtual bridges, veth pairs etc. This makes packet analysis hard.

I ran into the problem myself when I wanted to measure how exactly my containers were communicating with each other. Wireshark along with it’s conversation features was my first thought. All the virtual networking elements, however, complicated things.

So, I tried to find a solution to run wireshark as if it was running within that container. This would mean that I modify my containers, install wireshark inside them and run it — too complicated.

Luckily however, network namespaces solve the issue. Docker uses network namespaces to create a new networking stack for each container. All we now need to do is to run wireshark within the correct namespace.

I have written a small piece of Go code which can execute any program within a container. I used the https://github.com/vishvananda/netns library which is also used by docker for manipulating network namespaces.

package main
import (
“os”
“fmt”
“net”
“runtime”
“github.com/vishvananda/netns”
“os/exec”
)
func main() {
// Lock the OS Thread so we don’t accidentally switch namespaces
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// Save the current network namespace
origns, _ := netns.Get()
defer origns.Close()
// Get the network namespace based on container id
newns, _ := netns.GetFromDocker(“a115e93f5137”)
defer newns.Close()
netns.Set(newns)
// Do something with the network namespace
ifaces, _ := net.Interfaces()
fmt.Printf(“Interfaces: %v\n”, ifaces)
cmd := exec.Command(“tshark”,”-z”,”conv,ip”,”-i”,”eth0")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Run()
 //Return to original namespace
`netns.Set(origns)
}

This program must be run as root since it changes the network namespace. Instead of using wireshark, i used the command line version tshark, and run it in the conversation mode. This can be changed according to the needs.