Ограничение скорости для пользователей, подключающихся к PPTP-серверу

()

Иногда возникает необходимость ограничивать скорость пользователей, подключающихся к PPTP-серверу. В этой статье будет показано как можно это организовать.

Итак. Допустим что у вас есть PPTP-сервер подобный этому и мы хотим ограничить скорость подключения для каждого пользователя некоторой величиной. Допустим 256k. Заодно выделим гарантированные полосы пропускания для определённых видов трафика.

Для этого создадим скрипт /etc/ppp/ip-up.d/shaper следующего содержания:

#!/bin/sh

# Интерфейс
IFACE=${1}

# Ширина канала
LIMIT="256kbit"

# Гарантированная полоса для http и https
LIMIT_1="64kbit"

# Гарантированная полоса для smtp и dns
LIMIT_2="32kbit"


tc qdisc add dev ${IFACE} root handle 1: htb default 30
# Задаём верхний порог на интерфейсе
tc class add dev ${IFACE} parent 1: classid 1:1 htb rate ${LIMIT} burst 4k

# Создаём "трубу" с гарантированной полосой пропускания LIMIT_1
tc class add dev ${IFACE} parent 1:1 classid 1:10 htb rate ${LIMIT_1} burst 4k
tc qdisc add dev ${IFACE} parent 1:10 handle 10: sfq perturb 1

# Создаём "трубу" с гарантированной полосой пропускания LIMIT_2
tc class add dev ${IFACE} parent 1:1 classid 1:20 htb rate ${LIMIT_2} ceil ${LIMIT} burst 4k
tc qdisc add dev ${IFACE} parent 1:20 handle 20: sfq perturb 1

# "Труба" по умолчанию. Полоса пропускания динамически меняется от 16k до всей ширины канала.
tc class add dev ${IFACE} parent 1:1 classid 1:30 htb rate 16kbit ceil ${LIMIT} burst 4k
tc qdisc add dev ${IFACE} parent 1:30 handle 30: sfq perturb 1

# Кладём http и https в трубу с гарантированной полосой LIMIT_1
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 80   0xffff flowid 1:10
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 443  0xffff flowid 1:10

# Кладём smtp и dns в трубу с гарантированной полосой LIMIT_2
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 25   0xffff flowid 1:20
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 53   0xffff flowid 1:20

Когда к PPTP-серверу подключается пользователь, для него создаётся новый PPP-интерфейс и выполняются скрипты из директории /etc/ppp/ip-up.d. В том числе и этот скрипт, который ограничит скорость на интерфейсе.

Усложним задачу. Допустим что некоторым пользователям нужно ограничивать скорость в других пределах. Тогда придётся усовершенствовать скрипт, добавив к нему возможность читать файл конфигурации и действовать в соответствии с ним.

Файл конфигурации сохраним как /etc/shaper.conf и он будет иметь следующий вид:

192.168.0.1:512kbit:128kbit:32kbit
192.168.0.2:128kbit:64kbit:32kbit

Т.е. в каждой строке будет ip-адрес пользователя, ограничение скорости и гарантированные полосы для http и других видов трафика. Всё это разделено двоеточиями.

В этом случае скрипт примет вид:

#/bin/sh

# Параметры по умолчанию:
# Ширина канала
DEF_LIMIT="256kbit"
# Гарантированная полоса для http и https
DEF_LIMIT_1="64kbit"
# Гарантированная полоса для smtp и dns
DEF_LIMIT_2="32kbit"

# Файл конфигурации
CFG_FILE="/etc/shaper.conf"

# Интерфейс
IFACE=${1}

# IP клиента
LOCAL=${4}

# Читаем настройки:
LIMIT=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f2`
LIMIT_1=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f3`
LIMIT_2=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f4`

# Если какой-то параметр пустой - устанавливаем в значение по умолчанию:

if [ -z ${LIMIT} ]; then
	LIMIT=${DEF_LIMIT}
fi

if [ -z ${LIMIT_1} ]; then
	LIMIT_1=${DEF_LIMIT_1}
fi

if [ -z ${LIMIT_2} ]; then
	LIMIT_2=${DEF_LIMIT_2}
fi

tc qdisc add dev ${IFACE} root handle 1: htb default 30
# Задаём верхний порог на интерфейсе
tc class add dev ${IFACE} parent 1: classid 1:1 htb rate ${LIMIT} burst 4k

# Создаём "трубу" с гарантированной полосой пропускания LIMIT_1
tc class add dev ${IFACE} parent 1:1 classid 1:10 htb rate ${LIMIT_1} burst 4k
tc qdisc add dev ${IFACE} parent 1:10 handle 10: sfq perturb 1

# Создаём "трубу" с гарантированной полосой пропускания LIMIT_2
tc class add dev ${IFACE} parent 1:1 classid 1:20 htb rate ${LIMIT_2} ceil ${LIMIT} burst 4k
tc qdisc add dev ${IFACE} parent 1:20 handle 20: sfq perturb 1

# "Труба" по умолчанию. Полоса пропускания динамически меняется от 16k до всей ширины канала.
tc class add dev ${IFACE} parent 1:1 classid 1:30 htb rate 16kbit ceil ${LIMIT} burst 4k
tc qdisc add dev ${IFACE} parent 1:30 handle 30: sfq perturb 1

# Кладём http и https в трубу с гарантированной полосой LIMIT_1
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 80   0xffff flowid 1:10
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 443  0xffff flowid 1:10

# Кладём smtp и dns в трубу с гарантированной полосой LIMIT_2
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 25   0xffff flowid 1:20
tc filter add dev ${IFACE} protocol ip parent 1:0 prio 1 u32 match ip sport 53   0xffff flowid 1:20

Вобщем-то всё. Более подробно про управление скоростью можно прочитать в LARTC HowTo.

Ссылки по теме:

Ключевые слова: pptp, pptpd, shaper, tc, vpn.

Комментарии:

spir 2008-05-06 18:30:07 (#)

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

tc qdisc add dev $DEVICE handle ffff: ingress
tc filter add dev $DEVICE parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${UP}Kbit burst $DOWN drop flowid :1

MooSE 2008-05-07 08:23:47 (#)

немного не так: ограничения накладываются на исходящий с интерфейса трафик. т.е. как раз идущий к клиенту:)

2008-06-02 02:23:24 (#)

у меня в ASP данный срипт не работает
что я только с ним не делал
что харктерно: первый скрипт хоть выводит ошибки когда пишешь команду "./shaper"
а если второй вид данного скрипта туда зафигачить - невозможно выяснить даже ошибки! консоль замирает напроч! да нажатия клавиш отменяющих команду!

MooSE 2008-06-03 10:07:05 (#)

1. Какие ошибки?
2. Команды по одной выполнять пробовал?

2008-06-05 22:59:17 (#)

LIMIT=`grep ${LOCAL} ${CFG_FILE} | cut -d ':' -f2`
вот начиная с этого параметра кнсоль зависает!

2008-06-05 23:12:14 (#)

./shaper: line 9: =: команда не найдена
./shaper: line 13: =: команда не найдена
./shaper: line 17: =: команда не найдена
Cannot find device "root"
Error: Qdisc "1:" is classless.
Error: Qdisc "1:1" is classless.
Unknown qdisc "1:10", hence option "handle" is unparsable
Error: Qdisc "1:1" is classless.
Unknown qdisc "1:20", hence option "handle" is unparsable
Error: Qdisc "1:1" is classless.
Unknown qdisc "1:30", hence option "handle" is unparsable
Unknown filter "ip", hence option "parent" is unparsable
Unknown filter "ip", hence option "parent" is unparsable
Unknown filter "ip", hence option "parent" is unparsable
Unknown filter "ip", hence option "parent" is unparsable
а это ошибки!

MooSE 2008-06-06 08:58:30 (#)

просто так скрипт shaper запускать нельзя. как минимум внутри него тебе надо ${IFACE} указывать.

А по чтению конфига - а у тебя файл ${CFG_FILE} существует? Да и опять же переменная ${LOCAL} у тебя не пустая случаем?

2008-06-06 11:42:33 (#)

${CFG_FILE} существует!
${LOCAL} а ты думаешь я знаю чё там указывать?
Я всего 3ю неделю в люне-)

давай я не буде флудить пост?? напиши мне в асю плиз: 9-743-403
покавырялся... интерфейс указал... надо было не {ppp0} ставить а "ppp0"
что указовать в Local я ума не приложу... есл все адреса нахдяться в файле Shaper.conf
и ещё вот куча вской лабуды:

[root@zakachkin ~]# cd /etc/ppp
[root@zakachkin ppp]# ./shaper
./shaper: line 10: =: команда не найдена
./shaper: line 14: =: команда не найдена
./shaper: line 18: =: команда не найдена
RTNETLINK answers: File exists
Illegal "rate"
Usage: ... qdisc add ... htb [default N] [r2q N]
default minor id of class to which unclassified packets are sent {0}
r2q DRR quantums are computed as rate in Bps/r2q {10}
debug string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]
[prio P] [slot S] [pslot PS]
[ceil R2] [cburst B2] [mtu MTU] [quantum Q]
rate rate allocated to this class (class can still borrow)
burst max bytes burst which can be accumulated during idle period {computed}
mpu minimum packet size used in rate computations
overhead per-packet size overhead used in rate computations
ceil definite upper class rate (no borrows) {rate}
cburst burst but for ceil {computed}
mtu max packet size we create rate map for {1600}
prio priority of leaf; lower are served first {0}
quantum how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
Illegal "rate"
Usage: ... qdisc add ... htb [default N] [r2q N]
default minor id of class to which unclassified packets are sent {0}
r2q DRR quantums are computed as rate in Bps/r2q {10}
debug string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]
[prio P] [slot S] [pslot PS]
[ceil R2] [cburst B2] [mtu MTU] [quantum Q]
rate rate allocated to this class (class can still borrow)
burst max bytes burst which can be accumulated during idle period {computed}
mpu minimum packet size used in rate computations
overhead per-packet size overhead used in rate computations
ceil definite upper class rate (no borrows) {rate}
cburst burst but for ceil {computed}
mtu max packet size we create rate map for {1600}
prio priority of leaf; lower are served first {0}
quantum how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
RTNETLINK answers: Invalid argument
Illegal "rate"
Usage: ... qdisc add ... htb [default N] [r2q N]
default minor id of class to which unclassified packets are sent {0}
r2q DRR quantums are computed as rate in Bps/r2q {10}
debug string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]
[prio P] [slot S] [pslot PS]
[ceil R2] [cburst B2] [mtu MTU] [quantum Q]
rate rate allocated to this class (class can still borrow)
burst max bytes burst which can be accumulated during idle period {computed}
mpu minimum packet size used in rate computations
overhead per-packet size overhead used in rate computations
ceil definite upper class rate (no borrows) {rate}
cburst burst but for ceil {computed}
mtu max packet size we create rate map for {1600}
prio priority of leaf; lower are served first {0}
quantum how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
RTNETLINK answers: Invalid argument
Illegal "ceil"
Usage: ... qdisc add ... htb [default N] [r2q N]
default minor id of class to which unclassified packets are sent {0}
r2q DRR quantums are computed as rate in Bps/r2q {10}
debug string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]
[prio P] [slot S] [pslot PS]
[ceil R2] [cburst B2] [mtu MTU] [quantum Q]
rate rate allocated to this class (class can still borrow)
burst max bytes burst which can be accumulated during idle period {computed}
mpu minimum packet size used in rate computations
overhead per-packet size overhead used in rate computations
ceil definite upper class rate (no borrows) {rate}
cburst burst but for ceil {computed}
mtu max packet size we create rate map for {1600}
prio priority of leaf; lower are served first {0}
quantum how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
RTNETLINK answers: Invalid argument

MooSE 2008-06-06 19:11:27 (#)

В асю не пишу. Принципиально так как саппортом своих решений занимается в очень редких случаях и только на платной основе (без обид).

Здесь же в качестве ${LOCAL} берётся четвёртый параметр, переданный скрипту. Смотри на строчку "${LOCAL}=${4}"

2008-06-06 22:34:58 (#)

А сколько денег надо?? где обитаешь?
каковы условия оплаты? если сумма разумная - то почему бы и нет-)

MooSE 2008-06-08 00:33:21 (#)

да нет... давай уж лучше здесь...:)

ты знаешь что попробуй: добавить запись выполняемых строк скрипта в файл.

Т.е. например так:

echo tc qdisc add dev ${IFACE} root handle 1: htb default 30 >> /var/log/shaper.log
tc qdisc add dev ${IFACE} root handle 1: htb default 30

и посмотри что будет падать в лог. возможно натолкнёт на какую-нибудь мысль.

просто всё это чудо работает у меня на корпоративном сервере под управлением debian. проблем не возникало:)

2008-06-08 02:19:17 (#)

в лог валиться вот что

tc qdisc add dev root handle 1: htb default 30

а когда запускаю скрипт командой /etc/ppp/ip-up.d/shaper ppp0

выходит во что /etc/ppp/ip-up.d/shaper: line 47: ошибка синтаксиса: неожиданный конец файла

MooSE 2008-06-08 09:01:11 (#)

когда pppd запускает этот скрипт сам, то передаёт ему кучу параметров. имя интерфейса идёт четвёртым параметром а не первых. так что попробуй запускать так:

/shaper 1 2 3 ppp0

и что у тебя такого в строке 47 и вокруг неё? пытался разобраться?

2008-06-08 09:19:25 (#)

Он почему-то выдаёт ошибку на несуществующую строку

ксли я пишу что-то на 47 строку то следующяя ошибка приходиться на 48! и так до бесконечности!

MooSE 2008-06-09 00:03:41 (#)

мля. чувак, обижать не хочу, но такая трабла может означать только одно: ошибка не на 47 строке, а на 46 )

lessless 2008-10-19 19:26:28 (#)

стоически приветствую. следующая ситуация, по состоянию на сегодняшний день
ArchLinux с core/ppp 2.4.4-6 (base)

1. скрипты в директории /etc/ppp/ip-up.d автоматически не вsыполняются, поэтому было принято решение запускать руками из /etc/ppp/ip-up
killall -HUP dnsmasq
/etc/ppp/ip-up.d/shaper.sh ${1} ${2} ${3} ${4} ${5}
2. исправил параметр ${LOCAL}=${4} на
LOCAL=${5}
в соответствии с man:
interface-name tty-device speed local-IP-address remote-IP-address ipparam


( что бы ограничивать скорость на IP? или я ошибаюсь...)

3. при подключении скрипт запускается но не срабатывает, например:
#tc qdisc ls
qdisc pfifo_fast 0: dev ppp0 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev ppp3 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev ppp4 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

хотя добавленные в скрипт строки
echo $(whoami) recived 1:${1} 2:${2} 3:${3} 4:${4} 5:${5} >> ${LOGF}
echo sets LIMIT:${LIMIT} LIMIT_1:${LIMIT_1} LIMIT2:${LIMIT_2} IFACE:${IFACE} LOCAL:${LOCAL} >> ${LOGF}

дают следующий вывод
root recived 1:ppp3 2:/dev/pts/5 3:115200 4:172.16.10.1 5:172.16.10.19
sets LIMIT:256kbit LIMIT_1:128kbit LIMIT2:32kbit IFACE:ppp3 LOCAL:172.16.10.19

root recived 1:ppp4 2:/dev/pts/8 3:115200 4:172.16.10.1 5:172.16.10.14
sets LIMIT:256kbit LIMIT_1:128kbit LIMIT2:32kbit IFACE:ppp4 LOCAL:172.16.10.14

.

а если запустить скрипт через оболочку напрямую, то ситуация сразу меняется:
/etc/ppp/ip-up.d/shaper.sh ppp4 /dev/pts/8 115200 172.16.10.1 172.16.10.14
[root@piggy ~]# tc qdisc ls dev ppp4
qdisc htb 1: root r2q 10 default 30 direct_packets_stat 0
qdisc sfq 10: parent 1:10 limit 127p quantum 1400b perturb 1sec
qdisc sfq 20: parent 1:20 limit 127p quantum 1400b perturb 1sec
qdisc sfq 30: parent 1:30 limit 127p quantum 1400b perturb 1sec
[root@piggy ~]# tail -n 2 /var/log/shaper.log
root recived 1:ppp4 2:/dev/pts/8 3:115200 4:172.16.10.1 5:172.16.10.14
sets LIMIT:256kbit LIMIT_1:128kbit LIMIT2:32kbit IFACE:ppp4 LOCAL:172.16.10.14

прошу указать на ошибку и/или помочь в разрешении проблемы :)


MooSE 2008-10-21 16:31:39 (#)

Вобщем там надо указывать не адрес а имя создаваемого интерфейса. Я думаю что проблема именно в этом.

grey137 2008-11-16 19:19:16 (#)

Скрипт на некоторых системах не работает потому, что программа ip-up не передает ip-адрес интерфейса.
Решить проблему можно, вставив следующие строки в вышеуказанную программу вместо строки "LOCAL=$(4)":
---
AWK=/bin/awk
IFCONFIG=/sbin/ifconfig

LOCAL="`$IFCONFIG $IFACE | $AWK /$IFACE/'{next}// \
{split($0,a,"P-t-P:");split(a[2],a," ");print a[1];exit}'`"
---

С помощью данного скрипта вычисляется ip поднятого интерфейса.
Да, и ещё один момент: не забывайте удалять "трубу" для соответствующего устройства (tc qdisc del dev $IFACE root).

Удачи.

Oper.kh 2008-11-29 18:06:06 (#)

Стоит Debian, который случайно апгрейтанулся до убунты.
В общем создал файл /etc/ppp/ip-up.d/shaper, настроил всё по инструкции. И не получается заставить работать второй скрипт, скорость клиентам не режется вообще, выдаёт весь канал, не обращая даже на дефолтные настройки, но первый скрипт работает, и всем клиентам четко режет скорость на заданную.
(tc qdisc del dev $IFACE root) естественно не забыл, а так же в начале второго скрипта вписать (#!/bin/sh) тоже не забыл.
Попытался в /var/log/shaper.log записать лог, в итоге создался пустой файл

MooSE 2008-11-30 13:49:03 (#)

Oper.kh, ты пробовал дебажить какие он значения скоростей из конфига достаёт?

Oper.kh 2008-11-30 19:26:28 (#)

я не знаю что там у меня в системе, но никогда не получалось что либо записать в файл. Файл создаётся и в него ничего не записывается.

MooSE 2008-11-30 21:30:42 (#)

А как именно ты пытаешь писать всё в лог? Может способ записи в лог выбираешь не правильный?

Oper.kh 2008-12-01 00:42:40 (#)

Итак, разобрался со вторым скриптом.
1. В первой строке пишем "#!/bin/sh"
2. Как писалось ранее "LOCAL=${4}" меняем на "LOCAL=${5}"
3. В скрипте с if'ами ошибочка. Привожу ниже поправленный кусок:

if (test ${LIMIT}1 == "1") then
LIMIT=${DEF_LIMIT}
fi

if (test ${LIMIT_1}1 == "1") then
LIMIT_1=${DEF_LIMIT_1}
fi

if (test ${LIMIT_2}1 == "1") then
LIMIT_2=${DEF_LIMIT_2}
fi

4. http и https были ограничены лимитом LIMIT_1, и не могли достигать максимально допустимой скорости для данного клиента. В принципе не принципиально, ибо кому нужно, тот поставит предел.

Хотя и не завёлся с первого раза второй скрипт, я выражаю автору огромную благадарность за данный скрипт! Материал представлен в отличном виде, понятным даже для новичка, расписано всё детально, вплоть до того, куда этот скрипт необходимо положить что бы он работал.

А как бы его дописать, что бы он и отдачу резал?

MooSE 2008-12-01 16:07:53 (#)

Про отдачу написано в самом первом комментарии:) Позволю себе скопировать:

tc qdisc add dev $DEVICE handle ffff: ingress
tc filter add dev $DEVICE parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${UP}Kbit burst $DOWN drop flowid :1

----------------
Про ошибку: я когда разворачивал это решение в одной конторе - там жёстко для всех прописывалась скорость и потом небыло необходимости обрабатывать исключения. А тут вот решил добавить такую проверку.

Вобщем спасибо за замечание. Листинг скрипта поправил:)

Oper.kh 2008-12-02 12:30:48 (#)

Всётаки сам разобрался с отдачей

Конкретно для этого скрипта резалка отдачи выглядит так:

tc qdisc del dev ${IFACE} handle ffff: ingress
tc qdisc add dev ${IFACE} handle ffff: ingress
tc filter add dev ${IFACE} parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${LIMIT} burst 8k drop flowid :1

Я вот только начинаю разбиратся с линуксом, и я наивно думал, что скрипты лежащие в /etc/ppp/ip-up.d/ автовыполняются при подключении клиентов к серверу, но у меня самого инет подключается через впн, В общем немного дописав скриптик скорость на впнке, которая подключается к инету у меня теперь не режится.

MooSE, ещё раз огромное спасибо, за то что дал такой хороший шейпер. У меня б крыша поехала со всем этим разобратся)

MooSE 2008-12-04 04:18:43 (#)

На самом деле и тебе спасибо:) Всё-таки косяки у меня ты нашёл в тексте, да и со многим ты разобрался сам:)

antonmayko 2008-12-21 18:24:26 (#)

Скажите пожалуйста, а в /etc/ppp/ip-down.d/ нужно какой нибудь скрипт ложить??? Если да, то что нужно написать?

MooSE 2008-12-24 11:40:12 (#)

нет, не нужно. После того как убивается интерфейс - правила шейпера сбрасываются сами. Проверено.

Oper.kh 2009-01-11 15:42:24 (#)

Вот шейпер работал, работал нормально, как вот недавно подключил нового пользователеля, и в логах шейпера заметил, что переменным присваиваются 2 скорости.

Вот к примеру кусок конфига шейпера:

192.168.3.3:1024kbit:512kbit:16kbit
192.168.3.30:2048kbit:512kbit:16kbit

Пользователь с айпи 192.168.3.30 подключается нормлаьно, а пользователю 192.168.3.3 переменной присваивается скорость "1024kbit 2048kbit". Т.е. при подключении юзера 192.168.3.3 шейпер обрабатывает обе строки.

Для того что бы это исправить нужно строки:

LIMIT=`grep ${LOCAL} ${CFG_FILE} | cut -d ':' -f2`
LIMIT_1=`grep ${LOCAL} ${CFG_FILE} | cut -d ':' -f3`
LIMIT_2=`grep ${LOCAL} ${CFG_FILE} | cut -d ':' -f4`

Заменить на:

LIMIT=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f2`
LIMIT_1=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f3`
LIMIT_2=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f4`

MooSE 2009-01-14 17:41:10 (#)

Oper.kh, спасибо, статью в очередной раз поправил.

Вообще глядя на количество комментариев мне начинает казаться что это самая популярная статья на сайте:)

Кстати в дополнение фиксу от Oper.kh могу предложить ещё одну вещь, на случай если один и тот же IP фигурирует в конфиге больше одного раза (может админ ошибся) можно поправить кусок следующим образом:

LIMIT=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f2 | tail -n 1`
LIMIT_1=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f3 | tail -n 1`
LIMIT_2=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f4 | tail -n 1`


То есть принудительно вырезать все лишние скорости, и оставлять только последнюю указанную (как в rc.conf во фряхе - там тоже один и тот же параметр можно указать раз десять, но будет использовано последнее значение).

ssslll 2009-02-11 18:54:39 (#)

Поправьте меня, если я ошибаюсь. Для пользователей, имеющих разные скорости (ширину канала), при нехватке общей ширины канала, скорость каждого будет ограничиватся до значения, примерно равного общей ширине канала/число одновременных закачек, т.е. "несправедливо", если речь идет о провайдинге.

MooSE 2009-02-11 19:42:18 (#)

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

другое дело что некоторые товарищи тут используют его для провайдинга...:)

Oper.kh 2009-03-03 21:19:17 (#)

Заметил обновления во втором скрипте, а именно в коде:
if [ -z ${LIMIT} ]; then
	LIMIT = ${DEF_LIMIT}
fi

if [ -z ${LIMIT_1} ]; then
	LIMIT_1 = ${DEF_LIMIT_1}
fi

if [ -z ${LIMIT_2} ]; then
	LIMIT_2 = ${DEF_LIMIT_2}
fi

И обнаружил очередную ошибку. У меня под Debian lenny с пробелами до и после знака "=" не присваивает переменным LIMIT* значения DEF_LIMIT*.
Необходимо убрать пробелы до и после знака "="

MooSE 2009-03-04 01:00:13 (#)

Oper.kh, ты в очередной раз нашёл багу:) Спасибо:)

Oper.kh 2009-03-10 21:33:44 (#)

Время идёт... а файл shaper.conf растёт и растёт и из-за того, что в нём всё написано в строку и без пробелов, он выглядит не очень красиво, и сам начинаешь путаться что и куда писать. Поэтому я решил отказаться от разделений двоеточиями и разделить айпи и скорости табуляциями, после чего shaper.conf у меня имеет такой вид:

ppp_user_ip	INCOMING	HTTP_traf	DNS

192.168.100.50	1Mbit		512kbit		32kbit
192.168.3.13	4Mbit		1Mbit		32kbit
192.168.3.3	7Mbit		3Mbit		32kbit

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

    # Читаем настройки:
    LIMIT=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $2'} | tail -n 1`
    LIMIT_1=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $3'} | tail -n 1`
    LIMIT_2=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $4'} | tail -n 1`

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

MooSE 2009-03-11 11:26:27 (#)

Предлагаю такой велосипед:

ppp_user_ip	INCOMING	HTTP_traf	DNS

:192.168.100.50	:1Mbit		:512kbit		:32kbit
:192.168.3.13	:4Mbit		:1Mbit		:32kbit
:192.168.3.3	:7Mbit		:3Mbit		:32kbit


А чтение настроек сделать так:

    # Читаем настройки:
    LIMIT=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $2'} | cut -d ':' -f2 | tail -n 1`
    LIMIT_1=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $3'} | cut -d ':' -f2 | tail -n 1`
    LIMIT_2=`grep -w ${LOCAL} ${CFG_FILE} | awk {'print $4'} | cut -d ':' -f2 | tail -n 1`



В этом случае если нужно оставить скорость по дефолту - оставляешь только двоеточие а циферьку убираешь.

Хотя насколько я знаю твою задачу - тебе можно вообще без приоритезации трафика обойтись. Тупо нарезать на фиксированные полосы. Тогда конфиг вообще можно привести к виду:

192.168.100.50=1Mbit
192.168.3.13=4Mbit
192.168.3.3=7Mbit


И наступит тебе счастье:)

Oper.kh 2009-03-11 18:04:53 (#)

Приоритезация пусть будет, с ней приятнее) у меня вообщето в конфиге и скорость отдачи настраивается, так же сделал логирование в папочку, файлы по месяцам бьются, ну это уже так... фичи, главное - это твоя основа)

MooSE 2009-03-11 19:59:27 (#)

А что именно логгируешь? Трафик? Или срабатывания шейпера? Там много кода? Может мы тут коллективным разумом это до статьи дотянем?:)

UPD: А про скорость отдачи: а она у тебя не равняется скорости получения? Это не одна и та же цифра?

Oper.kh 2009-03-11 20:09:07 (#)

Вот так выглядит лог:

«11.03.2009 19:08:33» Подключился юзер 192.168.3.214(DreamX); лимит скорости: 512kbit/512kbit/384kbit/16kbit; Интерфейс: ppp8.
«11.03.2009 19:15:36» Отключился юзер 192.168.3.5(Dimasik); Интерфейс: ppp7.
«11.03.2009 19:41:12» Отключился юзер 192.168.3.4(Legofon); Интерфейс: ppp1.
«11.03.2009 19:44:26» Подключился юзер 192.168.3.23(Ligor); лимит скорости: 512kbit/512kbit/384kbit/16kbit; Интерфейс: ppp1.
«11.03.2009 19:59:59» Отключился юзер 192.168.3.127(Diamond); Интерфейс: ppp6.
«11.03.2009 20:02:56» Подключился юзер 192.168.3.9(Margo); лимит скорости: 512kbit/512kbit/256kbit/16kbit; Интерфейс: ppp6.
«11.03.2009 20:04:34» Подключился юзер 192.168.3.127(Diamond); лимит скорости: 512kbit/512kbit/384kbit/16kbit; Интерфейс: ppp7.

В коде добавлено несколько переменных, которые формируют дату, путь к файлу лога, так же из-за того, что у меня подключается впн на провайдера, то идёт проверка по имени интерфейса, что бы не применять шейпер на впн с интернетом. Ну и ещё один файл лежит в ip-down.d который пишет в лог, что юзер отключился.

А статья как бы есть, вот только со временем она обновляется))) В первом сообщении работающий шейпер есть, сделан красиво, а дальше уже каждый сам может доработать его под себя. Самое главное это строки начинающийся с tc, а всё остальное - косметика)

MooSE 2009-03-11 20:13:55 (#)

У меня просто была мысль сженить всё это с MySQL.Плюс добавить ещё учёт трафика по netflow. И чтобы фильтры для NetFlow и chap-secrets для pptpd генерировались скриптом через каждый час на основании данных в базе. Тогда будет уже комплексное решение:)

Oper.kh 2009-03-11 21:31:23 (#)

Звучит заманчиво)))

MooSE 2009-03-12 20:16:50 (#)

угу. осталось сделать...:)

Anonymous 2009-09-02 16:29:19 (#)

Помогите плиз что не так делаю?
При вводе строк по отдельности выдает следующее:
root@vpn-server:~# IFACE=${1}
root@vpn-server:~# LIMIT="256kbit"
root@vpn-server:~# LIMIT_1="64kbit"
root@vpn-server:~# LIMIT_2="32kbit"
root@vpn-server:~# tc qdisc add dev ${IFACE} root handle 1: htb default 30
Cannot find device "root"
root@vpn-server:~#

Может что то не установлено?

MooSE 2009-09-02 20:53:53 (#)

А чему у тебя равно ${1} ? :)

Anonymous 2009-09-03 09:31:43 (#)

Я тупо скопировал конфиг и вставил, думал так и нужно.
Мои интерфейсы: eth0 -внешний
eth1 -внутренний.
А что там нужно прописать? Может укажите где я должен прописать свои параметры и что именно,
ps:я новичок в этом деле, для меня это все ново.

MooSE 2009-09-03 11:36:11 (#)

И где ты хочешь скорость порезать? на чём? и куда ты вставил конфиг?

Anonymous 2009-09-03 12:53:52 (#)

1. Скорость порезать нужно для пользователей, подключающихся к PPTP-серверу (выход в инет).
2. не понял вопроса :)
3. Конфиг вставил в /etc/ppp/ip-up.d

Мои параметры:
eth0 - интернет по dhcp
eth1 - локалка (10.10.0.0/24)
ppp(X) - выход в инет (10.249.5.0/)интерфейс появляется только после конекта юзера
Подняты dhcp, pptpd на eth1 согласно инструкциям на форумах(помоему на вашем)единственно вопросы возникли иммено по урезанию скорости.

MooSE 2009-09-03 17:04:11 (#)

всё. дошло. ты просто вообще не понял что делает этот скрипт и как он должен работать.


не надо тупо и неосмысленно водить команды в командную строку.

Например LIMIT="256kbit" это не команда, а установка переменной, которая работает только внутри скрипта.

Anonymous 2009-09-07 13:54:06 (#)

Давай по существу... я вопрос, а ты если не сложно ответ.
# Интерфейс
IFACE=${1}

# IP клиента
LOCAL=${4}

Я так понимаю это так же установка переменной? Если да:
Просьба расшифровать что есть ${1}? (интерфейс на котором нужно урезать eth0,eth1,ppp или цифровое значение)

тоже самое про ip клиента. что есть ${4} (диапазон ip или цифровое значение).

С остальными переменными понятно.

MooSE 2009-09-07 14:34:51 (#)

${1} это первый параметр, переданный скрипту в командной строке. А ${4} соответственно четвёртый.

и установка переменной таким образом работает только внутри скрипта. в командной строке нужно использовать env или export

Anonymous 2009-09-07 14:50:52 (#)

да бы развеять все сомнения получаем следующее:

IFACE=${1} где- (${1}-ширина канала)
LOCAL=${4} где- (${4}-Файл конфигурации)

Правильно я понял?
Заранее спасибо :)

MooSE 2009-09-07 17:43:17 (#)

нет!!! IFACE это имя интерфейса. а LOCAL - IP-адрес на нём.

Anonymous 2009-12-13 20:11:09 (#)

в убунте

# This script is called with the following arguments:
#    Arg  Name                          Example
#    $1   Interface name                ppp0
#    $2   The tty                       ttyS1
#    $3   The link speed                38400
#    $4   Local IP number               12.34.56.78
#    $5   Peer  IP number               12.34.56.99
#    $6   Optional ``ipparam'' value    foo

# The  environment is cleared before executing this script
# so the path must be reset
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
export PATH

# These variables are for the use of the scripts run by run-parts
PPP_IFACE="$1"
PPP_TTY="$2"
PPP_SPEED="$3"
PPP_LOCAL="$4"
PPP_REMOTE="$5"
PPP_IPPARAM="$6"


И скрипты запускаются
run-parts /etc/ppp/ip-up.d \
  --arg="$1" --arg="$2" --arg="$3" --arg="$4" --arg="$5" --arg="$6"

Anonymous 2009-12-13 20:13:19 (#)

поэтому проще nfr
# Интерфейс
IFACE=${PPP_IFACE}

# IP клиента
LOCAL=${PPP_REMOTE}

Anonymous 2010-03-20 15:29:51 (#)

Подскажите как в centos 5.4 присвоить имя интерфейса, если в первом скрипте исправить на IFACE=ppp0 - то работает, пробовал так:
IFACE=ifconfig $EXT_IF|grep ppp|cut -c 1-4|awk '{print $1}'
- ничего не присваивается (

MooSE 2010-03-21 00:02:32 (#)

Я хз как оно в CentOS работает. Как вообще переменные скрипту передаются можно узнать? там в /etc/ppp скриптов много, большая часть проблем решается вдумчивым чтением скриптов.

Но имя интерфейса уже точно нужно брать не из вывода ifconfig.

Anonymous 2011-10-14 21:56:48 (#)

Цитата:

Всётаки сам разобрался с отдачей

Конкретно для этого скрипта резалка отдачи выглядит так:

tc qdisc del dev ${IFACE} handle ffff: ingress
tc qdisc add dev ${IFACE} handle ffff: ingress
tc filter add dev ${IFACE} parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${LIMIT} burst 8k drop flowid :1

Я вот только начинаю разбиратся с линуксом, и я наивно думал, что скрипты лежащие в /etc/ppp/ip-up.d/ автовыполняются при подключении клиентов к серверу, но у меня самого инет подключается через впн, В общем немного дописав скриптик скорость на впнке, которая подключается к инету у меня теперь не режится.

MooSE, ещё раз огромное спасибо, за то что дал такой хороший шейпер. У меня б крыша поехала со всем этим разобратся)

Здравствуйте , подскажите пожалуйста что надо изменить в этих строках ,чтобы скорость отдачи была такаяже как и скорость загрузки , а то в таком виде как есть , скорость отдачи это треть от скоросте указаной в лимите для юзера ??? Спасибо !!!1

MooSE 2011-10-15 00:02:35 (#)

Цитата:

Здравствуйте , подскажите пожалуйста что надо изменить в этих строках ,чтобы скорость отдачи была такаяже как и скорость загрузки , а то в таком виде как есть , скорость отдачи это треть от скоросте указаной в лимите для юзера ??? Спасибо !!!1


Проблема у тебя. Строки правильные:)

Anonymous 2011-10-15 00:57:04 (#)

Вот содержимое моего /etc/ppp/ip-up.d/shaper
#!/bin/sh

# Параметры по умолчанию:
# Ширина канала
DEF_LIMIT="20Mbit"

# Файл конфигурации
CFG_FILE="/etc/shaper.conf"

# Интерфейс
IFACE=${PPP_IFACE}

# IP клиента
LOCAL=${PPP_REMOTE}

#
# Читаем настройки:
LIMIT=`grep ${LOCAL}: ${CFG_FILE} | cut -d ':' -f2`

# Если какой-то параметр пустой - устанавливаем в значение по умолчанию:

if [ -z ${LIMIT} ]; then
	LIMIT=${DEF_LIMIT}
fi


tc qdisc add dev ${IFACE} root handle 1: htb default 30
# Задаём верхний порог на интерфейсе
tc class add dev ${IFACE} parent 1: classid 1:1 htb rate ${LIMIT} burst 4k

# "Труба" по умолчанию. Полоса пропускания динамически меняется от 16k до всей ширины канала.
tc class add dev ${IFACE} parent 1:1 classid 1:30 htb rate 16kbit ceil ${LIMIT} burst 4k
tc qdisc add dev ${IFACE} parent 1:30 handle 30: sfq perturb 1

#  Ограничение скорости отдачи
tc qdisc del dev ${IFACE} handle ffff: ingress
tc qdisc add dev ${IFACE} handle ffff: ingress
tc filter add dev ${IFACE} parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${LIMIT} burst 8k drop flowid :1

Вот содержимое /etc/shaper.conf
192.168.1.71:10Mbit
192.168.1.72:10Mbit


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

MooSE 2011-10-15 04:33:46 (#)

всё правильно. скорее всего у тебя канал не очень симметричный

Anonymous 2011-10-15 11:26:05 (#)

Цитата:

всё правильно. скорее всего у тебя канал не очень симметричный

Странно , канал очень даже семетричный 40/40 Mbit , проверяю спидтестом так он и показывает , подключаюсь посредством VPN после этого также проверяю скорость тем же спидтестом , закачку кажет так как надо 9.96 Mbit , а от отдачу показывает 3.3 Mbit (проверял на разных серверах )
Пробовал просто залить файл на файлобменник ,так таже ситуация . Ну да ладно , спасибо большое за статью , и за быстрые ответы !!!

MooSE 2011-10-15 14:23:57 (#)

Тут возможно ещё дело в том что ingress работает достаточно грубо, просто убивая лишний исходящий трафик на интерфейсе. Когда начинают теряться пакеты происходит пересинхронизация и пакеты начинают отправляться медленее. Вопрос в том насколько медленее они начинают отправляться:)

max2007 2011-10-15 15:07:43 (#)

Цитата:

Тут возможно ещё дело в том что ingress работает достаточно грубо, просто убивая лишний исходящий трафик на интерфейсе. Когда начинают теряться пакеты происходит пересинхронизация и пакеты начинают отправляться медленее. Вопрос в том насколько медленее они начинают отправляться:)

Я токо начинаю немного познавать линукс , так что из того что вы написали практически ничё не понял (извините)
Если у вас есть возможность то подскажите как решить мою проблему ?? Спасибо !!

MooSE 2011-10-15 23:41:59 (#)

Цитата:

Я токо начинаю немного познавать линукс , так что из того что вы написали практически ничё не понял (извините)
Если у вас есть возможность то подскажите как решить мою проблему ?? Спасибо !!


Дело не в Linux. Тут надо вообще понимать сетевые протоколы. Помогать человеку без этих знаний мне очень тяжело.

max2007 2011-10-16 01:18:30 (#)

Ну и на этом спасибо .

max2007 2011-10-17 20:42:47 (#)

Решил свою проблему но немного коряво наверное , поменял в последнюю строку на вот такую
tc filter add dev ${IFACE} parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${LIMIT} burst 3Mbit drop flowid :1

MooSE 2011-10-17 22:49:02 (#)

Цитата:

Решил свою проблему но немного коряво наверное , поменял в последнюю строку на вот такую
tc filter add dev ${IFACE} parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${LIMIT} burst 3Mbit drop flowid :1


Хм. burst это превышение :) То есть ты просто нарезаешь канал до ширины ${LIMIT}+3Mbit

max2007 2011-10-17 23:44:49 (#)

Я понемаю что это не совсем правильно , но по крайней мере это хоть как то работает , лучшего решения я пока найти не смог

Anonymous 2012-03-01 10:00:59 (#)

прошу прощения, читал бегло, я не совсем понял, раз ограничения выставляются на каждый pppX интерфейс, значит нету динамического распределения канал между всеми pppXXX интерфейсами? или я что то упустил?


заранее благодарен.

MooSE 2012-03-04 19:12:34 (#)

Цитата:

раз ограничения выставляются на каждый pppX интерфейс, значит нету динамического распределения канал между всеми pppXXX интерфейсами?


Да. Именно так...

Anonymous 2012-04-25 11:56:44 (#)

Добрый день! Скрипт очень нравится, но мне нужно организовать полосы для онлайн игр и обмена файлами. Т.е. вместо выших http https smtp dns, вбить tcp и udp? Спасибо!

MooSE 2012-04-27 11:21:49 (#)

Цитата:

Добрый день! Скрипт очень нравится, но мне нужно организовать полосы для онлайн игр и обмена файлами. Т.е. вместо выших http https smtp dns, вбить tcp и udp? Спасибо!


Вы похоже не внимательно читали. Приоритезация идёт по портам. Всмотритесь в скрипты.

Anonymous 2013-03-27 03:40:25 (#)

я немного попарился и думал почему у меня скорость во втором скрипте всегда выставляется дефектная, оказалось что ip адрес выданный удаленному пользователю идет не 4 строчкой, а пятой, поменял на LOCAL=${5} и всё заработало(debian 6.0.7).
Во втором скрипте есть ошибка в самой первой строчке
#/bin/sh пропущен !.
Я конечно понимаю что это элементарно, но не где не описано что к файлу shaper нужно применить chmod +x или chmod 766.
Для тех у кого интернет и так поднимается через ppp и они не знают как сделать что бы сделать так что бы скрипт не распространялся на ppp0 я опишу свой вариант решения этой проблемы
после определения переменных я добавил
if [ $IFACE != ppp0 ];
then
далее скрипт и в конце
fi
Новый комментарий



© 2006-2016 Вадим Калинников aka MooSE