Pull to refresh

Mikrotik Router OS, скрипт для динамического деления скорости

Reading time 9 min
Views 22K

Mikrotik Router OS, скрипт для динамического деления скорости.



На днях встала следующая проблема: делить скорость поровну между всеми пользователями, причем так, чтобы скорость не выделялась на клиентов, которые на данный момент не пользуются интернетом, а отдавалась всем остальным, еще чтобы при большом количестве клиентов и узком канале получить некоторую «буферность» канала.

Внимательно изучив кучку мануалов, пришел к выводу, что без поднятия скрипта на внутреннем языке Router OS никак не обойтись.

Скрипт работает только с VPN клиентами, т.к. не нашел способа работы с отдельными IP.

Итак, поехали!

Пример на трех PPTP пользователей, первичная настройка

Адреса пользователей 192.168.70.10-192.168.70.12
Адрес сервера 192.168.70.1

Добавляем трех пользователей:

/ ppp secret add name="user1" service=pptp password="null" profile=default-encryption local address=192.168.70.1 remote-address=192.168.70.10 disabled=no
/ ppp secret add name="user2" service=pptp password="null" profile=default-encryption local-address=192.168.70.1 remote-address=192.168.70.11 disabled=no
/ ppp secret add name="user3" service=pptp password="null" profile=default-encryption local-address=192.168.70.1 remote-address=192.168.70.12 disabled=no


Добавляем на каждого из пользователей по интерфейсу, имя интерфейса и имя пользователя должны совпадать!

/ interface pptp-server add name="user1" user="user1" disabled=no
/ interface pptp-server add name="user2" user="user2" disabled=no
/ interface pptp-server add name="user3" user="user3" disabled=no


Mangle, не знаю почему, но во всех примерах специалисты сначала маркируют соединение, а потом помечают в нем пакеты, может быть я не совсем понимаю всей глубины мысли, но не вижу в этом особого толка и помечаю пакеты сразу в общем потоке, т.к. каждое лишнее правило заметно тормозит систему. Внимание! значение new-packet-mark должно быть «имя пользователя/сервера» +"_down” и “_up” соответственно.

/ ip firewall mangle add chain=forward src-address=192.168.70.10 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user1_up passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=192.168.70.11 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user2_up passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=192.168.70.12 dst-address=0.0.0.0/0 action=mark-packet new-packet-mark=user3_up passthrough=no disabled=no

/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.10 action=mark-packet new-packet-mark=user1_down passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.11 action=mark-packet new-packet-mark=user2_down passthrough=no disabled=no
/ ip firewall mangle add chain=forward src-address=0.0.0.0/0 dst-address=192.168.70.12 action=mark-packet new-packet-mark=user3_down passthrough=no disabled=no


Следующим шагом необходимо построить дерево в Queue. В нем и будут происходить все ограничения трафика.

/ queue tree add name="Download" parent=global-out limit-at=0 queue=hotspot-default priority=8 max-limit=0 burst-limit=0 burst-threshold=0 burst-time=0s disabled=no
/ queue tree add name="user1_down" parent=Download packet-mark=user1_down disabled=no
/ queue tree add name="user2_down" parent=Download packet-mark=user2_down disabled=no
/ queue tree add name="user3_down" parent=Download packet-mark=user3_down disabled=no

/ queue tree add name="Upload" parent=global-out limit-at=0 queue=hotspot-default priority=8 max-limit=0 burst-limit=0 burst-threshold=0 burst-time=0s disabled=no
/ queue tree add name="user1_up" parent=Upload packet-mark=user1_up disabled=no
/ queue tree add name="user2_up" parent=Upload packet-mark=user2_up disabled=no
/ queue tree add name="user3_up" parent=Upload packet-mark=user3_up disabled=no


Последним шагом будет настройка вычислительной части скрипта и помещения ее в планировщик системы, с интервалом 10-60 сек. в зависимости от производительности вашего микротика, чем меньше интервал — тем лучше.

Переменные и некоторые особенности настройки вычислительной части

MaxRateDownload -Ширина канала на всех пользователей (прием)
MaxRateUpload -Ширина канала на всех пользователей (отдача)
ActiveThresholddown -Порог при превышении которого пользователь будет считаться активным (прием)
ActiveThresholdup - Порог при превышении которого пользователь будет считаться активным (отдача)
ParentDownload -Родитель очереди (прием)
ParentUpload - Родитель очереди (отдача)


:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");


Следует устанавливать чуть меньше чем ширина вашего канала, дабы избежать тормозов при активности еще одного пользователя, который до этого не потреблял интернет.

:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");


Эти значения устанавливайте согласно своим потребностям, но исходя из расчета: кол-во пользователей умноженное на Thresholddown =не дожно превышать MaxRateDownload иначе ваши пользователи будут всегда не активными! Естественно users*ActiveThresholdup= не должно превышать MaxRateUpload. Всегда оставляйте некоторый запас.

Принцип работы скрипта

Скрипт замеряет, с какой скоростью работает клиент и если она превышает ActiveThresholddown, добавляет его как активного на прием,
так же, увеличивает счетчик, если пользователь подключен к PPTP своей учетной записи.
Далее скрипт производит проверку ActiveThresholdup, если пользователь превысил эту отметку, то добавляет его как активного на отдачу.

Если количество активных клиентов равно нулю, изменяет его на единицу, ибо впоследствии произвести математические расчеты, а то что то на ноль не делится :)

Рассчитывает:
MaxRateDownload делит на количество активных пользователей на прием, выводит скорость на одного пользователя.
MaxRateUpload делит на количество активных пользователей на отдачу, выводит скорость на одного пользователя.

Далее устанавливает лимит всем пользователям в Queue Tree согласно рассчитанной выше.

Далее рассчитывает значение в килобитах и выводит в лог статистику.

Код скрипта

Для разных версий Router OS, нужна своя версия скрипта. Это связано с тем, что внутренний синтаксис языка постепенно эволюционирует и тем самым не всегда радует пользователей.

Код скрипта для версий 2.9.xx:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($received-bits-per-second>=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($sent-bits-per-second>=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!


Код скрипта для версии 3.22:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"received-bits-per-second">=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"sent-bits-per-second">=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!


Код скрипта для версий 3.30 — 4.x — 5.x:

######################
:local MaxRateDownload ("2000000");
:local MaxRateUpload ("2000000");
:local ActiveThresholddown ("5000");
:local ActiveThresholdup ("5000");
:local ParentDownload ("Download");
:local ParentUpload ("Upload");
######################

######################
:local z;
:local i;
:local ii;
:local userX;
:global onlineclientsdown (0);
:global onlineclientsup (0);
:global connected (0);
######################

######################
:foreach i in=[/ppp active find] do={ :set userX [/ppp active get $i name];
:global connected ($connected+1);
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"rx-bits-per-second">=$ActiveThresholddown) do { :set onlineclientsdown ($onlineclientsdown+1);}} };

:foreach ii in=[/ppp active find] do={ :set userX [/ppp active get $ii name];
/interface monitor-traffic [/interface find name=$userX] once do {:if ($"tx-bits-per-second">=$ActiveThresholdup) do { :set onlineclientsup ($onlineclientsup+1);}} };

:if ($onlineclientsdown = 0) do {:set onlineclientsdown (1)};
:if ($onlineclientsup= 0) do {:set onlineclientsup (1)};

:local ratelimitdown ($MaxRateDownload/$onlineclientsdown)
:local ratelimitup ($MaxRateUpload/$onlineclientsup)

:foreach z in=[/ppp active find] do={ :set userX [/ppp active get $z name];
/queue tree set [/queue tree find name=($userX . "_down")] parent=$ParentDownload packet-mark=($userX . "_down") queue=hotspot-default priority=8 max-limit=$ratelimitdown

/queue tree set [/queue tree find name=($userX . "_up")] parent=$ParentUpload packet-mark=($userX . "_up") queue=hotspot-default priority=8 max-limit=$ratelimitup};
######################

######################
:local kbsmaxdown ($MaxRateDownload/1000);
:local kbsmaxup ($MaxRateUpload /1000);
:local kbsthr ($ActiveThresholddown/1000);
:local kbsdown ($ratelimitdown/1000);
:local kbsup ($ratelimitup/1000);

:log warning ("Shaper:");
:log info ("MaxRate Download : " . $MaxRateDownload . " bps /" . $kbsmaxdown . " kbs / Upload : " . $MaxRateUpload . " bps /" . $kbsmaxup . " kbs");
:log info ("Threshold: Download : " . $ActiveThresholddown . " bps /" . $kbsthr . " kbs / Upload : " . $ActiveThresholdup . " bps /" . $kbsthr . " kbs");
:log info ("Connected Users : " . $connected);
:log info ("Active Users : Download : " . $onlineclientsdown . " / Upload : " . $onlineclientsup);
:log info ("User Speed Download : " . $ratelimitdown . " bps /" . $kbsdown . " kbs / Upload : " . $ratelimitup . " bps /" . $kbsup . " kbs");
######################
# (C) Inlarion icq 429-587 Copyright!
Tags:
Hubs:
+26
Comments 12
Comments Comments 12

Articles