Есть проблема - дети забили на учёбу, всё свободное время уделяется онлайн-дрочильням, соцсетям, видео и прочим тиктокам, оценки в школе пробили дно. Мне нужно сознательно снизить скорость, поднять пинг и джиттер. В шейпинге трафика разбираюсь плохо.
Есть роутер на OpenWrt 23+, устройства получают постоянные аренды адреса по маку.
Закинул запрос в нейронку, после нескольких часов боданий она выдала это:
#!/bin/sh
[ ! -f /etc/bw_spoiler.enabled.yes ] && exit 0
# Hotplug скрипт для ограничения трафика и порчи пинга/джиттера по MAC/IP
IFACE=${DEVICE}
IF_UP=${ACTION}
# Конфигурация: список MAC/IP и параметры
CONFIG_FILE="/etc/bw_spoiler.conf"
MAC_LIST="" # Пустой по умолчанию
IP_LIST="" # Ваш IP
DOWNLOAD_RATE="512kbit" # Лимит download (to client)
UPLOAD_RATE="512kbit" # Лимит upload (from client)
PING_DELAY="100ms" # Задержка
JITTER="80ms" # Джиттер
LOSS="10%" # Потери пакетов
# Логирование
logger -t bw_spoiler "Starting script for $IFACE $IF_UP"
# Чтение конфигурации из файла, если он есть
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
# Проверка: запуск только для br-lan при поднятии
if [ "$IFACE" = "br-lan" ] && [ "$IF_UP" = "ifup" ]; then
# Загрузка модулей
modprobe ifb && logger -t bw_spoiler "Loaded ifb module" || logger -t bw_spoiler "Failed to load ifb module"
modprobe sch_netem && logger -t bw_spoiler "Loaded sch_netem module" || logger -t bw_spoiler "Failed to load sch_netem module"
# Очистка старых правил
tc qdisc del dev br-lan root 2>/dev/null
tc qdisc del dev br-lan ingress 2>/dev/null
tc qdisc del dev ifb-spoiler root 2>/dev/null
ip link del ifb-spoiler 2>/dev/null
# Создание ifb-spoiler
ip link add ifb-spoiler type ifb && logger -t bw_spoiler "Created ifb-spoiler" || logger -t bw_spoiler "Failed to create ifb-spoiler"
ip link set ifb-spoiler up && logger -t bw_spoiler "Activated ifb-spoiler" || logger -t bw_spoiler "Failed to activate ifb-spoiler"
# Download to client (egress на br-lan): HTB для лимита + netem для задержек
tc qdisc add dev br-lan root handle 1: htb default 1 && logger -t bw_spoiler "Added qdisc to br-lan"
tc class add dev br-lan parent 1: classid 1:1 htb rate 10gbit burst 0b cburst 0b
tc class add dev br-lan parent 1:1 classid 1:20 htb rate $DOWNLOAD_RATE ceil $DOWNLOAD_RATE burst 1600b cburst 1600b
tc qdisc add dev br-lan parent 1:20 handle 20: netem delay $PING_DELAY $JITTER loss $LOSS && logger -t bw_spoiler "Added netem to br-lan"
# Upload from client (ingress через ifb-spoiler)
tc qdisc add dev br-lan ingress && logger -t bw_spoiler "Added ingress qdisc to br-lan"
tc filter add dev br-lan parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev ifb-spoiler && logger -t bw_spoiler "Added ingress filter"
tc qdisc add dev ifb-spoiler root handle 1: htb default 1
tc class add dev ifb-spoiler parent 1: classid 1:1 htb rate 10gbit burst 0b cburst 0b
tc class add dev ifb-spoiler parent 1:1 classid 1:20 htb rate $UPLOAD_RATE ceil $UPLOAD_RATE burst 1600b cburst 1600b
tc qdisc add dev ifb-spoiler parent 1:20 handle 20: netem delay $PING_DELAY $JITTER loss $LOSS && logger -t bw_spoiler "Added netem to ifb-spoiler"
# tc filters для классификации по IP (download: dst IP, upload: src IP)
for ip in $IP_LIST; do
tc filter add dev br-lan parent 1: protocol ip prio 1 u32 match ip dst $ip flowid 1:20 && logger -t bw_spoiler "Added IP filter for br-lan dst $ip"
tc filter add dev ifb-spoiler parent 1: protocol ip prio 1 u32 match ip src $ip flowid 1:20 && logger -t bw_spoiler "Added IP filter for ifb-spoiler src $ip"
done
# tc filters для классификации по MAC (если список не пустой; download: ether daddr, upload: ether saddr)
for mac in $MAC_LIST; do
# Преобразование MAC в hex для u32 (offset -14 для ether src, -8 для daddr; negative offsets from nexthdr)
mac_hex=$(echo $mac | sed 's/://g' | tr 'a-f' 'A-F')
mac1=$(echo 0x${mac_hex:0:8})
mac2=$(echo 0x${mac_hex:8:4}0000)
tc filter add dev br-lan parent 1: protocol all prio 2 u32 match u32 $mac1 0xffffffff at -8 match u16 $mac2 0xffff0000 at -4 flowid 1:20 && logger -t bw_spoiler "Added MAC filter for br-lan daddr $mac"
tc filter add dev ifb-spoiler parent 1: protocol all prio 2 u32 match u32 $mac1 0xffffffff at -14 match u16 $mac2 0xffff0000 at -10 flowid 1:20 && logger -t bw_spoiler "Added MAC filter for ifb-spoiler saddr $mac"
done
fi
# Cleanup при отключении интерфейса
if [ "$IFACE" = "br-lan" ] && [ "$IF_UP" = "ifdown" ]; then
tc qdisc del dev br-lan root 2>/dev/null
tc qdisc del dev br-lan ingress 2>/dev/null
tc qdisc del dev ifb-spoiler root 2>/dev/null
ip link del ifb-spoiler 2>/dev/null
logger -t bw_spoiler "Cleaned up for $IFACE"
fi
Скрипт помещается в hotplug для br-lan. Файлы настройки с переопределениями переменных и списков IP и MAC, флагового файла для переключения активности - в /etc. Вроде должно работать:
root@Xi4A:~# tc -s class show dev br-lan
class htb 1:1 root rate 10Gbit ceil 10Gbit burst 0b cburst 0b
Sent 54508411 bytes 45848 pkt (dropped 0, overlimits 37205 requeues 0)
backlog 0b 0p requeues 0
lended: 0 borrowed: 0 giants: 0
tokens: 13 ctokens: 13
class htb 1:20 parent 1:1 leaf 0: prio 0 rate 1Mbit ceil 1Mbit burst 1600b cburst 1600b
Sent 54508411 bytes 45848 pkt (dropped 5157, overlimits 26037 requeues 0)
backlog 0b 0p requeues 0
lended: 45848 borrowed: 0 giants: 0
tokens: 188000 ctokens: 188000
root@Xi4A:~# tc -s class show dev ifb-spoiler
class htb 1:1 root rate 10Gbit ceil 10Gbit burst 0b cburst 0b
Sent 6392299 bytes 42984 pkt (dropped 0, overlimits 1153 requeues 0)
backlog 0b 0p requeues 0
lended: 1 borrowed: 0 giants: 0
tokens: 14 ctokens: 14
class htb 1:20 parent 1:1 leaf 0: prio 0 rate 1Mbit ceil 1Mbit burst 1600b cburst 1600b
Sent 6392239 bytes 42983 pkt (dropped 4670, overlimits 492 requeues 0)
backlog 0b 0p requeues 0
lended: 42590 borrowed: 0 giants: 0
tokens: 192500 ctokens: 192500
root@Xi4A:~# tc qdisc show dev br-lan
qdisc htb 1: root refcnt 2 r2q 10 default 0x1 direct_packets_stat 87499 direct_qlen 1000
qdisc netem 20: parent 1:20 limit 1000 delay 400ms 100ms loss 10%
qdisc ingress ffff: parent ffff:fff1 ----------------
root@Xi4A:~# tc qdisc show dev ifb-spoiler
qdisc htb 1: root refcnt 2 r2q 10 default 0x1 direct_packets_stat 106879 direct_qlen 32
qdisc netem 20: parent 1:20 limit 1000 delay 400ms 100ms loss 10%
Но, во-первых, скорость по спидтестам ограничивается согласно настройкам только для входящего трафика, а для исходящего трепыхается на уровне 0,5 Мб/с независимо от настроек, а во-вторых, такое ощущение, что это не работает вне скачивания файлов и синтетических спидтестов - жалоб нет (обычно при проблемах с интернетами они сразу бегут жаловаться), подсматриваю по vnc - смотрят ютуб без проблем, а скорость vnc-трафика между моим и их устройствами достигает 0,5 Гб/с (судя по графикам в диспетчере задач винды), хотя если ради теста я вношу в список адрес своего компа - у меня люто лагает даже консольный ssh до роутера. Стек ipv6 не поддерживается провайдером и отключен на роутере на системном уровне. Logread показывает построчное внесение адресов в список, для которых должно применяться ограничение, и эти адреса правильные.
Что-то в скрипте не так? Или, может быть, есть более правильный и надежный способ, чтобы решить эту проблему? Прошу помочь.


















