Files
homelab-docker-stacks/capture.sh
T

87 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
readonly NETSHOOT_IMAGE="${NETSHOOT_IMAGE:-nicolaka/netshoot}"
usage() {
cat <<EOF
Usage: $(basename "$0") CONTAINER [PORT | FILTER]
Capture traffic from a running container's network namespace.
Arguments:
CONTAINER Container name or ID
PORT Capture inbound TCP traffic to this port
FILTER Custom tcpdump filter expression (quote it as one argument)
Examples:
$(basename "$0") gitea 3000
$(basename "$0") immich-server 2283
$(basename "$0") nginx 'tcp port 443'
$(basename "$0") adguardhome 'udp port 53'
Environment:
NETSHOOT_IMAGE Packet-capture image (default: nicolaka/netshoot)
EOF
}
die() {
echo "ERROR: $*" >&2
exit 1
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
[[ $# -ge 1 ]] || {
usage >&2
exit 2
}
[[ $# -le 2 ]] || die "FILTER must be quoted as one argument"
readonly CONTAINER="$1"
readonly CAPTURE_TARGET="${2:-tcp}"
command -v docker >/dev/null 2>&1 || die "docker is not installed or not in PATH"
running="$(docker container inspect --format '{{.State.Running}}' "$CONTAINER" 2>/dev/null)" ||
die "container not found: $CONTAINER"
[[ "$running" == "true" ]] || die "container is not running: $CONTAINER"
network_mode="$(docker container inspect --format '{{.HostConfig.NetworkMode}}' "$CONTAINER")"
if [[ "$network_mode" == "host" ]]; then
echo "WARNING: $CONTAINER uses host networking; the capture may include host traffic." >&2
fi
if [[ "$CAPTURE_TARGET" =~ ^[0-9]+$ ]]; then
((CAPTURE_TARGET >= 1 && CAPTURE_TARGET <= 65535)) ||
die "invalid TCP port: $CAPTURE_TARGET"
filter="tcp dst port $CAPTURE_TARGET"
else
filter="$CAPTURE_TARGET"
fi
docker_args=(
run
--rm
--network "container:$CONTAINER"
--cap-add NET_RAW
--cap-add NET_ADMIN
)
if [[ -t 0 && -t 1 ]]; then
docker_args+=(-it)
else
docker_args+=(-i)
fi
echo "Container: $CONTAINER"
echo "Filter: $filter"
echo "Press Ctrl-C to stop. Packet contents may include credentials or other secrets." >&2
exec docker "${docker_args[@]}" "$NETSHOOT_IMAGE" \
tcpdump -ni any -A -s 0 "$filter"