feat: add container packet capture helper
This commit is contained in:
1 parent
1881eac588
commit
ce835b5a09
1 file changed
+86
Executable
+86
@@ -0,0 +1,86 @@
|
|||||||
|
#!/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"
|
||||||
Reference in new issue
Block a user