Files
parahub-mesh/files/usr/bin/parahub-speed-control
Parahub AI c5b9229ad0 feat: Add OTA auto-update and guest IPv6 via Yggdrasil
OTA: build.sh writes version/profile to firmware, generates manifest.json
with SHA256 per device. parahub-autoupdate script runs nightly at 3am,
fetches manifest (Yggdrasil first), verifies checksum, runs sysupgrade.
sysupgrade.conf preserves /etc/parahub/, yggdrasil.conf, dropbear keys.

Guest IPv6: Yggdrasil 300::/64 subnet assigned to guest via SLAAC.
Separate yggdrasil firewall zone (5 zones total) with guest→yggdrasil
forwarding. IPv6 exempt from tc shaping — full speed to Parahub services.
IPv6 to WAN blocked. Heartbeat now reads version from file, not hardcoded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 08:09:27 +00:00

82 lines
3.5 KiB
Bash
Executable File

#!/bin/sh
# Parahub Mesh — Per-client speed control
# Free tier: 512kbps (default), Paid tier: full speed (via nftables set + tc HTB)
#
# Usage: parahub-speed-control init|add <ip>|remove <ip>|list|flush
IFACE="br-guest"
SLOW_RATE="512kbit"
case "$1" in
init)
# Remove SQM if active
/etc/init.d/sqm stop 2>/dev/null
/etc/init.d/sqm disable 2>/dev/null
# --- Egress shaping (router → client, i.e. download for client) ---
tc qdisc del dev $IFACE root 2>/dev/null
tc qdisc add dev $IFACE root handle 1: htb default 10
tc class add dev $IFACE parent 1: classid 1:1 htb rate 1000mbit
tc class add dev $IFACE parent 1:1 classid 1:10 htb rate $SLOW_RATE ceil $SLOW_RATE # free tier
tc class add dev $IFACE parent 1:1 classid 1:20 htb rate 1000mbit # paid tier
tc qdisc add dev $IFACE parent 1:10 fq_codel
tc qdisc add dev $IFACE parent 1:20 fq_codel
# tc filter: packets with mark 0x20 → paid class
tc filter add dev $IFACE parent 1: protocol ip handle 0x20 fw flowid 1:20
# Exempt ALL IPv6 from shaping — only Yggdrasil IPv6 reaches guests (firewall enforced)
tc filter add dev $IFACE parent 1: protocol ipv6 prio 1 u32 match u32 0 0 flowid 1:20
# --- Ingress shaping (client → router, i.e. upload for client) via IFB ---
ip link add ifb-guest type ifb 2>/dev/null
ip link set ifb-guest up
tc qdisc del dev $IFACE ingress 2>/dev/null
tc qdisc add dev $IFACE ingress
tc filter add dev $IFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb-guest
tc filter add dev $IFACE parent ffff: protocol ipv6 u32 match u32 0 0 action mirred egress redirect dev ifb-guest
tc qdisc del dev ifb-guest root 2>/dev/null
tc qdisc add dev ifb-guest root handle 1: htb default 10
tc class add dev ifb-guest parent 1: classid 1:1 htb rate 1000mbit
tc class add dev ifb-guest parent 1:1 classid 1:10 htb rate $SLOW_RATE ceil $SLOW_RATE
tc class add dev ifb-guest parent 1:1 classid 1:20 htb rate 1000mbit
tc qdisc add dev ifb-guest parent 1:10 fq_codel
tc qdisc add dev ifb-guest parent 1:20 fq_codel
tc filter add dev ifb-guest parent 1: protocol ip handle 0x20 fw flowid 1:20
# Exempt ALL IPv6 from ingress shaping
tc filter add dev ifb-guest parent 1: protocol ipv6 prio 1 u32 match u32 0 0 flowid 1:20
# --- nftables: paid_clients set + mark rules ---
nft add table inet parahub 2>/dev/null
nft flush table inet parahub 2>/dev/null
nft add set inet parahub paid_clients '{ type ipv4_addr; }'
nft add chain inet parahub speed_mark '{ type filter hook forward priority -150; }'
nft add rule inet parahub speed_mark ip daddr @paid_clients meta mark set 0x20
nft add rule inet parahub speed_mark ip saddr @paid_clients meta mark set 0x20
logger -t parahub-speed "Speed control initialized: free=${SLOW_RATE}, paid=unlimited"
;;
add)
[ -z "$2" ] && echo "Usage: $0 add <ip>" && exit 1
nft add element inet parahub paid_clients "{ $2 }" 2>/dev/null
logger -t parahub-speed "Added paid client: $2"
;;
remove)
[ -z "$2" ] && echo "Usage: $0 remove <ip>" && exit 1
nft delete element inet parahub paid_clients "{ $2 }" 2>/dev/null
logger -t parahub-speed "Removed paid client: $2"
;;
list)
nft list set inet parahub paid_clients 2>/dev/null
;;
flush)
nft flush set inet parahub paid_clients 2>/dev/null
;;
*)
echo "Usage: $0 {init|add <ip>|remove <ip>|list|flush}"
exit 1
;;
esac