Files
AWG2_harness/Amnezia limits (old bash)/limit_peers.sh.txt
T

139 lines
4.4 KiB
Plaintext

#!/usr/bin/env bash
# Traffic control for AmneziaWG (production-ready)
set -euo pipefail
LOG="/var/log/amnezia-tc.log"
LOCK_FILE="/tmp/amnezia-tc.lock"
LIMIT="${LIMIT:-70mbit}"
CONTAINER=""
WG_IF="${WG_IF:-wg0}"
# Prefer new container name, fall back to old
for c in amnezia-awg2 amnezia-awg; do
if docker ps --format '{{.Names}}' 2>/dev/null | grep -xq "$c"; then
CONTAINER="$c"
break
fi
done
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG"
}
# Lock to avoid concurrent runs
exec 200>"$LOCK_FILE"
flock -n 200 || { log "Script already running, exit"; exit 0; }
if [ -z "$CONTAINER" ]; then
log "Container amnezia-awg2/amnezia-awg not found, exit"
exit 0
fi
# detect interface inside container if default not present there
if ! docker exec "$CONTAINER" ip link show "$WG_IF" >/dev/null 2>&1; then
DET_IF=$(docker exec "$CONTAINER" sh -c "ip -o link show 2>/dev/null | awk -F': ' '{print $2}'" 2>/dev/null \
| egrep -o '^(wg[0-9]+|wg|awg[0-9]*|amnezia[0-9]*|tun[0-9]+)' | head -n1 || true)
if [ -n "$DET_IF" ]; then
WG_IF="$DET_IF"
log "Detected interface inside container: $WG_IF"
else
log "Interface $WG_IF not found inside container $CONTAINER, exit"
exit 0
fi
fi
log "=== Start updating rules === (container=$CONTAINER, iface=$WG_IF, limit=$LIMIT)"
# Get current clients
CLIENT_IPS=$(docker exec "$CONTAINER" sh -c "wg show all allowed-ips 2>/dev/null" 2>/dev/null \
| awk '{print $3}' | grep -oE '10\.8\.1\.[0-9]{1,3}' | sort -u || true)
# fallback
if [ -z "$CLIENT_IPS" ]; then
CLIENT_IPS=$(docker exec "$CONTAINER" sh -c "wg show 2>/dev/null" 2>/dev/null \
| grep -Eo '10\.8\.1\.[0-9]{1,3}' | sort -u || true)
fi
if [ -z "$CLIENT_IPS" ]; then
log "No clients found, exit"
exit 0
fi
log "Clients: $(echo $CLIENT_IPS | tr '\n' ' ')"
EXISTING_RULES=$(docker exec "$CONTAINER" sh -c "tc filter show dev $WG_IF parent 1: 2>/dev/null || true" 2>/dev/null \
| grep -oE 'match [0-9a-f]+' | awk '{print $2}' | sort -u || true)
NEEDS_UPDATE=false
num_ips=$(echo "$CLIENT_IPS" | wc -w)
num_rules=$(echo "$EXISTING_RULES" | wc -w)
if [ "$num_rules" -ne "$num_ips" ] || [ -z "$EXISTING_RULES" ]; then
NEEDS_UPDATE=true
else
for ip in $CLIENT_IPS; do
hex_ip=$(printf '%02x' ${ip//./ } | tr -d '\n' || true)
if ! echo "$EXISTING_RULES" | grep -q "$hex_ip"; then
NEEDS_UPDATE=true
break
fi
done
fi
if [ "$NEEDS_UPDATE" = false ]; then
log "Rules are already up-to-date, skip"
exit 0
fi
log "Updating rules (old will be removed)"
docker exec "$CONTAINER" sh -c "
tc qdisc del dev $WG_IF root 2>/dev/null || true
tc qdisc del dev $WG_IF ingress 2>/dev/null || true
ip link del ifb0 2>/dev/null || true
" 2>/dev/null || true
docker exec "$CONTAINER" sh -c "
tc qdisc add dev $WG_IF root handle 1: htb 2>/dev/null || true
tc class add dev $WG_IF parent 1: classid 1:1 htb rate 1000mbit ceil 1000mbit 2>/dev/null || true
" 2>/dev/null || true
docker exec "$CONTAINER" sh -c "
modprobe ifb 2>/dev/null || true
ip link add name ifb0 type ifb 2>/dev/null || true
ip link set dev ifb0 up 2>/dev/null || true
tc qdisc add dev $WG_IF handle ffff: ingress 2>/dev/null || true
tc filter add dev $WG_IF parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev ifb0 2>/dev/null || true
tc qdisc add dev ifb0 root handle 2: htb 2>/dev/null || true
tc class add dev ifb0 parent 2: classid 2:1 htb rate 1000mbit ceil 1000mbit 2>/dev/null || true
" 2>/dev/null || true
class_id=10
count=0
for ip in $CLIENT_IPS; do
log "Adding limit for $ip (class $class_id)"
docker exec "$CONTAINER" sh -c "
tc class add dev $WG_IF parent 1:1 classid 1:$class_id htb rate $LIMIT ceil $LIMIT 2>/dev/null || true
tc qdisc add dev $WG_IF parent 1:$class_id fq_codel 2>/dev/null || true
tc filter add dev $WG_IF parent 1: protocol ip u32 match ip dst $ip flowid 1:$class_id 2>/dev/null || true
" 2>/dev/null || true
docker exec "$CONTAINER" sh -c "
tc class add dev ifb0 parent 2:1 classid 2:$class_id htb rate $LIMIT ceil $LIMIT 2>/dev/null || true
tc qdisc add dev ifb0 parent 2:$class_id fq_codel 2>/dev/null || true
tc filter add dev ifb0 parent 2: protocol ip u32 match ip src $ip flowid 2:$class_id 2>/dev/null || true
" 2>/dev/null || true
class_id=$((class_id + 1))
count=$((count + 1))
done
log "Limits applied for $count clients"
log "=== Completed successfully ==="
exit 0