From 624b1da9a69be7f4d7b92d3b3037a05d748ddbc3 Mon Sep 17 00:00:00 2001 From: goldsquid Date: Thu, 8 Jan 2026 09:38:38 +0700 Subject: [PATCH] better limits --- limit-bandwidth.sh | 74 +++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/limit-bandwidth.sh b/limit-bandwidth.sh index acb01a02..7aaf823c 100755 --- a/limit-bandwidth.sh +++ b/limit-bandwidth.sh @@ -1,11 +1,18 @@ #!/bin/bash -# General script to limit bandwidth for all public ports in a Docker Compose file -# Limits each port to specified bandwidth (default: 100 MBit/s) +# General script to limit OUTGOING bandwidth for all public ports in a Docker Compose file +# Limits each port's outgoing traffic to specified bandwidth (default: 100 MBit/s) +# +# Note: This script limits OUTGOING bandwidth only. Limiting incoming bandwidth is +# impractical for P2P networks because: +# - You can't control what other nodes send you +# - Dropping incoming packets causes retransmissions and wastes bandwidth +# - P2P protocols have backpressure - if you're slow to respond, peers back off +# - Limiting outgoing is usually sufficient to control your bandwidth usage # # Usage: # ./limit-bandwidth.sh [start|stop|status] [--limit BANDWIDTH] -# ./limit-bandwidth.sh rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start -# ./limit-bandwidth.sh rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start --limit 20mbit +# ./limit-bandwidth.sh rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace start +# ./limit-bandwidth.sh rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace start --limit 20mbit # # Environment variable: # BANDWIDTH_LIMIT=20mbit ./limit-bandwidth.sh start @@ -61,10 +68,11 @@ if [ $# -lt 1 ]; then echo " Can also use BANDWIDTH_LIMIT environment variable" echo "" echo "Examples:" + echo " $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace start" echo " $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start" - echo " $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start --limit 20mbit" - echo " BANDWIDTH_LIMIT=20mbit $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start" - echo " $0 rpc/ethereum/geth/ethereum-mainnet-geth-pruned-pebble-path.yml status" + echo " $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace start --limit 20mbit" + echo " BANDWIDTH_LIMIT=20mbit $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace start" + echo " $0 rpc/ethereum/geth/ethereum-mainnet-geth-pruned-pebble-path status" exit 1 fi @@ -86,6 +94,12 @@ elif [ "$ACTION" = "--limit" ]; then exit 1 fi +# Handle .yml extension (like latest.sh does) +# If filename doesn't end in .yml, append it +if [[ ! "$COMPOSE_FILE" == *.yml ]]; then + COMPOSE_FILE="${COMPOSE_FILE}.yml" +fi + # Resolve compose file path if [ ! -f "$COMPOSE_FILE" ]; then # Try relative to BASEPATH @@ -93,6 +107,7 @@ if [ ! -f "$COMPOSE_FILE" ]; then COMPOSE_FILE="$BASEPATH/$COMPOSE_FILE" else echo -e "${RED}Error: Compose file not found: $1${NC}" + echo "Tried: $COMPOSE_FILE and $BASEPATH/$COMPOSE_FILE" exit 1 fi fi @@ -222,7 +237,12 @@ case "$ACTION" in # Remove existing qdisc if any tc qdisc del dev "$BRIDGE" root 2>/dev/null || true - # Create HTB (Hierarchical Token Bucket) qdisc + # Create HTB (Hierarchical Token Bucket) qdisc for egress (outgoing traffic only) + # We only limit outgoing because: + # - You control what you send (outgoing) + # - You can't control what others send (incoming) + # - Dropping incoming packets causes retransmissions and wastes bandwidth + # - P2P protocols have backpressure mechanisms tc qdisc add dev "$BRIDGE" root handle 1: htb default 30 # Create root class with high bandwidth @@ -236,39 +256,31 @@ case "$ACTION" in for port in "${PORTS[@]}"; do echo -e "${BLUE} Limiting port ${port} to ${BANDWIDTH_LIMIT}...${NC}" - # Create limited class for this port + # Create limited class for this port (outgoing traffic only) tc class add dev "$BRIDGE" parent 1:1 classid 1:${PORT_ID} htb rate ${BANDWIDTH_LIMIT} burst ${BURST} ceil ${BANDWIDTH_LIMIT} - # Add filter to route marked packets to this class + # Add filter to route marked packets to this class (outgoing only) tc filter add dev "$BRIDGE" parent 1: protocol ip prio ${PORT_ID} handle ${PORT_ID} fw flowid 1:${PORT_ID} - # Mark TCP traffic for this port + # Mark outgoing traffic in OUTPUT chain (traffic from host) iptables -t mangle -C OUTPUT -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ iptables -t mangle -A OUTPUT -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} - iptables -t mangle -C OUTPUT -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ - iptables -t mangle -A OUTPUT -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} - - # Mark UDP traffic for this port iptables -t mangle -C OUTPUT -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ iptables -t mangle -A OUTPUT -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} - iptables -t mangle -C OUTPUT -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ - iptables -t mangle -A OUTPUT -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} - # Mark in FORWARD chain (container traffic) + # Mark outgoing traffic in FORWARD chain (traffic from containers) + # This catches traffic from containers going out through the bridge iptables -t mangle -C FORWARD -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ iptables -t mangle -A FORWARD -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} - iptables -t mangle -C FORWARD -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ - iptables -t mangle -A FORWARD -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} iptables -t mangle -C FORWARD -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ iptables -t mangle -A FORWARD -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} - iptables -t mangle -C FORWARD -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || \ - iptables -t mangle -A FORWARD -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} PORT_ID=$((PORT_ID + 1)) done - echo -e "${GREEN}✓ Bandwidth limiting configured!${NC}" - echo -e "${GREEN}All ports are now limited to ${BANDWIDTH_LIMIT} each${NC}" + echo -e "${GREEN}✓ Outgoing bandwidth limiting configured!${NC}" + echo -e "${GREEN}All ports are now limited to ${BANDWIDTH_LIMIT} outgoing traffic each${NC}" + echo -e "${YELLOW}Note: Only OUTGOING traffic is limited. Incoming traffic is not limited.${NC}" ;; stop) echo -e "${YELLOW}Removing bandwidth limiting...${NC}" @@ -278,14 +290,13 @@ case "$ACTION" in for port in "${PORTS[@]}"; do echo -e "${BLUE} Removing limits for port ${port}...${NC}" + # Remove OUTPUT rules (outgoing from host) iptables -t mangle -D OUTPUT -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true - iptables -t mangle -D OUTPUT -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true iptables -t mangle -D OUTPUT -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true - iptables -t mangle -D OUTPUT -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true + + # Remove FORWARD rules (outgoing from containers) iptables -t mangle -D FORWARD -p tcp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true - iptables -t mangle -D FORWARD -p tcp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true iptables -t mangle -D FORWARD -p udp --sport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true - iptables -t mangle -D FORWARD -p udp --dport ${port} -j MARK --set-mark ${PORT_ID} 2>/dev/null || true PORT_ID=$((PORT_ID + 1)) done @@ -304,12 +315,15 @@ case "$ACTION" in echo -e "${BLUE}TC Classes:${NC}" tc class show dev "$BRIDGE" 2>/dev/null || echo " No classes configured" echo "" - echo -e "${BLUE}Iptables rules (OUTPUT):${NC}" + echo -e "${BLUE}Iptables rules (OUTPUT - outgoing from host):${NC}" iptables -t mangle -L OUTPUT -n --line-numbers | grep -E "MARK|${PORTS[0]}" || echo " No rules found" echo "" - echo -e "${BLUE}Iptables rules (FORWARD):${NC}" + echo -e "${BLUE}Iptables rules (FORWARD - outgoing from containers):${NC}" iptables -t mangle -L FORWARD -n --line-numbers | grep -E "MARK|${PORTS[0]}" || echo " No rules found" echo "" + echo -e "${YELLOW}Note: Only outgoing traffic is limited. Incoming traffic is not limited${NC}" + echo -e "${YELLOW} because you can't control what other nodes send you.${NC}" + echo "" echo -e "${BLUE}Monitored ports: ${PORTS[*]}${NC}" ;; *)