I want to build a Docker image containing tcpdump. That Docker image runs an application that needs to call tcpdump, but it should not run as root
all the time, for obvious security reasons. Instead, the non-root user should be able to run tcpdump directly.
Assuming the following Dockerfile:
FROM debian:bullseye
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -qq \
&& apt-get install -y \
libcap2 \
libcap2-bin \
tcpdump \
&& apt-get clean -y && apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*
RUN addgroup --system --gid 1001 user
RUN adduser --system --uid 1001 user --shell /bin/bash
RUN groupadd pcap && usermod -a -G pcap user \
&& chgrp pcap /usr/bin/tcpdump \
&& chmod 750 /usr/bin/tcpdump \
&& setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdump
USER user
ENTRYPOINT ["/usr/bin/tcpdump"]
When I run the image:
docker build -t tcpdump:latest .
docker run --rm -it tcpdump
… it fails with:
exec /usr/bin/tcpdump: operation not permitted
Someone else has raised this issue here but without a response.
What can I do to make this work?
Note that in regular installations it is not recommended to modify the permissions and group ownership of /usr/bin/tcpdump
, as that could be overwritten by system package upgrades. However, since the container image is immutable, this does not apply here.
The problem is that the Docker container itself is missing the required capabilities to run tcpdump
.
You can add those capabilities by adding the --privileged
option to the docker run
command, or, even better, only add the capabilities strictly needed:
$ docker run --rm --cap-add=NET_ADMIN --cap-add=NET_RAW -it tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C12:47:29.433403 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
1 packet captured
6 packets received by filter
0 packets dropped by kernel