better limits
This commit is contained in:
@@ -1,11 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# General script to limit bandwidth for all public ports in a Docker Compose file
|
# General script to limit OUTGOING bandwidth for all public ports in a Docker Compose file
|
||||||
# Limits each port to specified bandwidth (default: 100 MBit/s)
|
# 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:
|
# Usage:
|
||||||
# ./limit-bandwidth.sh <compose-file> [start|stop|status] [--limit BANDWIDTH]
|
# ./limit-bandwidth.sh <compose-file> [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 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 20mbit
|
||||||
#
|
#
|
||||||
# Environment variable:
|
# Environment variable:
|
||||||
# BANDWIDTH_LIMIT=20mbit ./limit-bandwidth.sh <compose-file> start
|
# BANDWIDTH_LIMIT=20mbit ./limit-bandwidth.sh <compose-file> start
|
||||||
@@ -61,10 +68,11 @@ if [ $# -lt 1 ]; then
|
|||||||
echo " Can also use BANDWIDTH_LIMIT environment variable"
|
echo " Can also use BANDWIDTH_LIMIT environment variable"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Examples:"
|
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"
|
||||||
echo " $0 rpc/gnosis/reth/gnosis-mainnet-reth-pruned-trace.yml start --limit 20mbit"
|
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.yml start"
|
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.yml status"
|
echo " $0 rpc/ethereum/geth/ethereum-mainnet-geth-pruned-pebble-path status"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -86,6 +94,12 @@ elif [ "$ACTION" = "--limit" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
# Resolve compose file path
|
||||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||||
# Try relative to BASEPATH
|
# Try relative to BASEPATH
|
||||||
@@ -93,6 +107,7 @@ if [ ! -f "$COMPOSE_FILE" ]; then
|
|||||||
COMPOSE_FILE="$BASEPATH/$COMPOSE_FILE"
|
COMPOSE_FILE="$BASEPATH/$COMPOSE_FILE"
|
||||||
else
|
else
|
||||||
echo -e "${RED}Error: Compose file not found: $1${NC}"
|
echo -e "${RED}Error: Compose file not found: $1${NC}"
|
||||||
|
echo "Tried: $COMPOSE_FILE and $BASEPATH/$COMPOSE_FILE"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -222,7 +237,12 @@ case "$ACTION" in
|
|||||||
# Remove existing qdisc if any
|
# Remove existing qdisc if any
|
||||||
tc qdisc del dev "$BRIDGE" root 2>/dev/null || true
|
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
|
tc qdisc add dev "$BRIDGE" root handle 1: htb default 30
|
||||||
|
|
||||||
# Create root class with high bandwidth
|
# Create root class with high bandwidth
|
||||||
@@ -236,39 +256,31 @@ case "$ACTION" in
|
|||||||
for port in "${PORTS[@]}"; do
|
for port in "${PORTS[@]}"; do
|
||||||
echo -e "${BLUE} Limiting port ${port} to ${BANDWIDTH_LIMIT}...${NC}"
|
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}
|
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}
|
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 -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 -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 -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 -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 -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 -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 -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 -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))
|
PORT_ID=$((PORT_ID + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -e "${GREEN}✓ Bandwidth limiting configured!${NC}"
|
echo -e "${GREEN}✓ Outgoing bandwidth limiting configured!${NC}"
|
||||||
echo -e "${GREEN}All ports are now limited to ${BANDWIDTH_LIMIT} each${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)
|
stop)
|
||||||
echo -e "${YELLOW}Removing bandwidth limiting...${NC}"
|
echo -e "${YELLOW}Removing bandwidth limiting...${NC}"
|
||||||
@@ -278,14 +290,13 @@ case "$ACTION" in
|
|||||||
for port in "${PORTS[@]}"; do
|
for port in "${PORTS[@]}"; do
|
||||||
echo -e "${BLUE} Removing limits for port ${port}...${NC}"
|
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 --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 --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 --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 --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))
|
PORT_ID=$((PORT_ID + 1))
|
||||||
done
|
done
|
||||||
@@ -304,12 +315,15 @@ case "$ACTION" in
|
|||||||
echo -e "${BLUE}TC Classes:${NC}"
|
echo -e "${BLUE}TC Classes:${NC}"
|
||||||
tc class show dev "$BRIDGE" 2>/dev/null || echo " No classes configured"
|
tc class show dev "$BRIDGE" 2>/dev/null || echo " No classes configured"
|
||||||
echo ""
|
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"
|
iptables -t mangle -L OUTPUT -n --line-numbers | grep -E "MARK|${PORTS[0]}" || echo " No rules found"
|
||||||
echo ""
|
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"
|
iptables -t mangle -L FORWARD -n --line-numbers | grep -E "MARK|${PORTS[0]}" || echo " No rules found"
|
||||||
echo ""
|
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}"
|
echo -e "${BLUE}Monitored ports: ${PORTS[*]}${NC}"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
Reference in New Issue
Block a user