Skip to content

Instantly share code, notes, and snippets.

@mbeijen
Created February 26, 2026 13:36
Show Gist options
  • Select an option

  • Save mbeijen/8d42972f28fff8102140b81c7014cade to your computer and use it in GitHub Desktop.

Select an option

Save mbeijen/8d42972f28fff8102140b81c7014cade to your computer and use it in GitHub Desktop.
netcap: capture and sum bytes send for command
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "usage: netcap <command> [args...]"
exit 1
fi
RAND=$(head -c 32 /dev/urandom | tr -dc a-z0-9 | head -c 6)
NS="netcap-$RAND"
VETH_HOST="veth-$RAND"
VETH_NS="eth0"
SUBNET="10.200.200.0/24"
HOST_IP="10.200.200.1"
NS_IP="10.200.200.2"
PCAP="capture-${$}.pcap"
cleanup() {
ip link del "$VETH_HOST" 2>/dev/null || true
ip netns del "$NS" 2>/dev/null || true
rm -rf /etc/netns/$NS 2>/dev/null || true
}
trap cleanup EXIT
# Pre-clean in case previous run crashed
ip link del "$VETH_HOST" 2>/dev/null || true
ip netns del "$NS" 2>/dev/null || true
echo "[+] Creating namespace"
ip netns add "$NS"
mkdir -p /etc/netns/$NS
echo "nameserver 1.1.1.1" > /etc/netns/$NS/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/netns/$NS/resolv.conf
echo "[+] Creating veth pair"
VETH_PEER="vpeer-$RAND"
ip link add "$VETH_HOST" type veth peer name "$VETH_PEER"
ip link set "$VETH_PEER" netns "$NS"
ip netns exec "$NS" ip link set "$VETH_PEER" name "$VETH_NS"
echo "[+] Configuring host side"
ip addr add "$HOST_IP/24" dev "$VETH_HOST"
ip link set "$VETH_HOST" up
echo "[+] Configuring namespace side"
ip netns exec "$NS" ip addr add "$NS_IP/24" dev "$VETH_NS"
ip netns exec "$NS" ip link set "$VETH_NS" up
ip netns exec "$NS" ip link set lo up
ip netns exec "$NS" ip route add default via "$HOST_IP"
echo "[+] Enabling NAT"
iptables -t nat -A POSTROUTING -s "$SUBNET" -j MASQUERADE
echo "[+] Starting tcpdump → $PCAP"
tcpdump -i "$VETH_HOST" -w "$PCAP" '(tcp or udp) and not multicast' &
TCPDUMP_PID=$!
sleep 0.5
echo "[+] Running command in namespace"
ip netns exec "$NS" "$@"
sleep 0.5
kill "$TCPDUMP_PID"
wait "$TCPDUMP_PID" 2>/dev/null || true
echo "[+] Calculating totals..."
TOTAL_BYTES=$(tcpdump -nn -r "$PCAP" 2>/dev/null | \
awk '
/length/ {
for (i=1; i<=NF; i++) {
if ($i == "length") {
sum += $(i+1)
}
}
}
END { print sum+0 }'
)
human() {
local bytes=$1
if (( bytes > 1024*1024 )); then
printf "%.2f MiB" "$(echo "$bytes / 1024 / 1024" | bc -l)"
elif (( bytes > 1024 )); then
printf "%.2f KiB" "$(echo "$bytes / 1024" | bc -l)"
else
printf "%d B" "$bytes"
fi
}
echo
echo "Traffic summary:"
echo " Packets: $(tcpdump -r "$PCAP" 2>/dev/null | wc -l)"
echo " Total: $(human "$TOTAL_BYTES")"
echo
echo "[+] Capture saved to $PCAP"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment