Created
October 7, 2025 14:18
-
-
Save olliefr/1b4302ad71352633693926cbed099d14 to your computer and use it in GitHub Desktop.
Network Traffic Capture and Profiling for Python scripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Network Traffic Capture and Profiling for Python scripts | |
| # | |
| # - Runs a Python script in an isolated network namespace and captures all its network | |
| # traffic. | |
| # - Profiles the Python script's performance using cProfile. | |
| # - Captures SSL/TLS keys for decrypting HTTPS traffic in Wireshark. | |
| # | |
| # Usage: ./run.sh <python_script.py> | |
| # | |
| # Outputs: | |
| # - capture_TIMESTAMP.pcap: Network traffic capture | |
| # - profile_TIMESTAMP.prof: Python profiling data | |
| # - sslkeys_TIMESTAMP.log: SSL/TLS keys for decryption | |
| # | |
| # Requirements: sudo, tcpdump, ip, iptables, python with cProfile | |
| # | |
| # Copyright (c) 2025 Oliver Frolovs <[email protected]> | |
| # SPDX-License-Identifier: MIT | |
| set -e | |
| if [ $# -eq 0 ]; then | |
| echo "Usage: $0 <python_script.py>" | |
| exit 1 | |
| fi | |
| SCRIPT="$1" | |
| if [ ! -f "$SCRIPT" ]; then | |
| echo "Error: $SCRIPT not found" | |
| exit 1 | |
| fi | |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) | |
| SUBNET="10.200.1.0/24" | |
| CAPTURE_FILE="capture_${TIMESTAMP}.pcap" | |
| PROFILE_FILE="profile_${TIMESTAMP}.prof" | |
| SSLKEY_FILE="sslkeys_${TIMESTAMP}.log" | |
| NAMESPACE="python_ns_$$" | |
| VETH_HOST="veth_py_$$" | |
| ORIGINAL_FORWARD=$(< /proc/sys/net/ipv4/ip_forward) | |
| PYTHON_BIN=$(which python) | |
| cleanup() { | |
| if [ ! -z "$TCPDUMP_PID" ] && ps -p $TCPDUMP_PID > /dev/null 2>&1; then | |
| sudo kill $TCPDUMP_PID 2>/dev/null || true | |
| fi | |
| sudo iptables -t nat -D POSTROUTING -s $SUBNET -j MASQUERADE 2>/dev/null || true | |
| sudo sysctl -w net.ipv4.ip_forward=$ORIGINAL_FORWARD > /dev/null 2>&1 || true | |
| sudo rm -rf /etc/netns/$NAMESPACE 2>/dev/null || true | |
| sudo ip netns delete $NAMESPACE 2>/dev/null || true | |
| sudo ip link delete $VETH_HOST 2>/dev/null || true | |
| } | |
| trap cleanup EXIT INT TERM | |
| # Create network namespace | |
| sudo ip netns add $NAMESPACE | |
| sudo ip netns exec $NAMESPACE ip link set lo up | |
| # Configure DNS | |
| sudo mkdir -p /etc/netns/$NAMESPACE | |
| sudo cp /etc/resolv.conf /etc/netns/$NAMESPACE/ | |
| # Create and configure veth pair | |
| sudo ip link add $VETH_HOST type veth peer name veth1 | |
| sudo ip link set veth1 netns $NAMESPACE | |
| # Configure interfaces | |
| sudo ip addr add 10.200.1.1/24 dev $VETH_HOST | |
| sudo ip link set $VETH_HOST up | |
| sudo ip netns exec $NAMESPACE ip addr add 10.200.1.2/24 dev veth1 | |
| sudo ip netns exec $NAMESPACE ip link set veth1 up | |
| sudo ip netns exec $NAMESPACE ip route add default via 10.200.1.1 | |
| # Enable NAT | |
| if ! sudo iptables -t nat -A POSTROUTING -s $SUBNET -j MASQUERADE; then | |
| echo "Error: Failed to add iptables rule" | |
| exit 1 | |
| fi | |
| sudo sysctl -w net.ipv4.ip_forward=1 > /dev/null | |
| # Start capture | |
| sudo tcpdump -i $VETH_HOST -w "$CAPTURE_FILE" > /dev/null 2>&1 & | |
| TCPDUMP_PID=$! | |
| # Wait for capture file with exponential backoff | |
| WAIT=1 | |
| for i in {1..10}; do | |
| if [ -f "$CAPTURE_FILE" ]; then | |
| break | |
| fi | |
| sleep 0.$(printf "%02d" $WAIT) | |
| WAIT=$((WAIT * 2)) | |
| done | |
| if [ ! -f "$CAPTURE_FILE" ] || ! ps -p $TCPDUMP_PID > /dev/null 2>&1; then | |
| echo "Error: tcpdump failed to start" | |
| TCPDUMP_PID="" | |
| exit 1 | |
| fi | |
| # Run Python in namespace with profiling | |
| sudo SSLKEYLOGFILE="$SSLKEY_FILE" GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json" ip netns exec $NAMESPACE "$PYTHON_BIN" -m cProfile -o "$PROFILE_FILE" "$SCRIPT" | |
| echo "Capture saved to: $CAPTURE_FILE" | |
| echo "Profile saved to: $PROFILE_FILE" | |
| echo "SSL keys saved to: $SSLKEY_FILE" | |
Author
Author
- Tested with Python 3.12.3 on WSL2 Ubuntu 24.04.3 on Windows 11 24H2.
- Decrypted and analysed the result with Wireshark 4.4.9.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Useful resources: