How to TCPdump effectively in Docker !

An introduction and references for tcpdump troubleshooting in kubernetes.

Containers can use the network stack in a few different ways. It all depends on how they connect to the network. A couple of options are:

  • docker bridge
  • host (ex. docker run --rm -it --net=host ...)
  • container networks (ex. docker run --rm -it --net=container:id ...)
  • overlay

Building a container and run good old stuff like tcpdump or ngrep would not yield much interesting information, because you link directly to the bridge network or overlay in a default scenario.

The good news is, that you can link your tcpdump container to the host network stack or even better, to the container network stack directly.

In the --net=host scenario, you can capture all traffic between the host and the physical network.

In the --net=container:id usecase, all traffic in/out a specific container can be captured.

So let’s get started !

Pre-requisites

Doing hands-on is important to follow and learn as it helps us to understand the concepts easily. It is recommended to do hands-on with your local machine.

  • Install docker as compatible to your operating system. Docker installation for ubuntu Linux distribution is given below.

Install Docker

apt update; apt install -y docker.io
docker version

Creating a tcpdump container image

First create a tcpdump container image.

docker build -t tcpdump - <<EOF 
FROM ubuntu 
RUN apt-get update && apt-get install -y tcpdump 
CMD tcpdump -i eth0 -n
EOF

Create a demo environment

Now let’s create a network and a nginx webserver container… and run some traffic !

docker network create demo-net
docker run -d --network demo-net --name wwwnginx nginx

You can note the ip address of wwwnginx for later reference.
The ipaddress is in the range of the docker network: ex. 172.18.0.2

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' wwwnginx

In this example we are using siege (https://github.com/JoeDog/siege) to generate some traffic. siege is an open source regression test and benchmark utility. It can stress test a single URL with a user defined number of simulated users (amongst many other interesting features).

docker run -it --network demo-net dockersec/siege \
      -c 1 http://wwwnginx/

Let’s run the capture

Add a tcpdump container and connect to the nginx networking stack.
Now open a new Terminal and link the tcpdump container.

docker run -it --net=container:wwwnginx tcpdump

or if you want to pass some more specific tcpdump parameters.

docker run -it --net=container:wwwnginx tcpdump tcpdump port 80 -A -n

If everything works out, you can now see the traffic flows inside the nginx container !!

08:52:08.984920 IP 172.18.0.2.80 &gt; 172.18.0.3.60566: Flags [.], ack 149, win 508, options [nop,nop,TS val 1874164652 ecr 467161649], length 0
E..4..@.@............P...a....t.....XP.....
o.{...R1
08:52:08.985298 IP 172.18.0.2.80 &gt; 172.18.0.3.60566: Flags [P.], seq 1:234, ack 149, win 508, options [nop,nop,TS val 1874164652 ecr 467161649], length 233: HTTP: HTTP/1.1 200 OK
E.....@.@............P...a....t.....Y9.....
o.{...R1HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Mon, 13 Jun 2022 08:52:08 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
Connection: close
ETag: "61f01158-267"
Accept-Ranges: bytes


08:52:08.985356 IP 172.18.0.3.60566 &gt; 172.18.0.2.80: Flags [.], ack 234, win 501, options [nop,nop,TS val 467161649 ecr 1874164652], length 0
E..4
C@.@..W...........P..t..a......XP.....
..R1o.{.
08:52:08.985401 IP 172.18.0.2.80 &gt; 172.18.0.3.60566: Flags [P.], seq 234:849, ack 149, win 508, options [nop,nop,TS val 1874164652 ecr 467161649], length 615: HTTP
E.....@.@..b.........P...a....t.....Z......
o.{...R1&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Welcome to nginx!&lt;/title&gt;
&lt;style&gt;
...

When we look closer into the traffic capture, we can see:
– traffic is send between the ip address of the siege (172.18.0.3) and 
  nginx (172.18.0.2)  container
– -n will print the ip addresses instead of the fully quafilied domain name

– -A will print the tcp payload in readable format

– port 80 will filter tcp packets send to and from this port

Of course, all the tcpdump parameters, filtering capablities and flags can be used in order to further inspect the traffic flow.

Conclusion

How easy was that?  Have fun sniffing.
Watch out for the next lab, explaining how we can extend this technique to Kubernetes.

Join Our Newsletter

Share this article:

Table of Contents