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 > 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 > 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 > 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 > 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<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> ...
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.