среда, 26 августа 2015 г.

nShaper. Динамический шейпер для Linux.

Рано или поздно у многих встает вопрос грамотного распределения трафика в сети. А точнее шейпинга.  Особенно если в сети есть участники, качающие по протоколу bittorrent.  Во времена, когда интернет у меня раздавал роутер DIR-320 с Олеговской прошивкой, этот вопрос особенно остро и для меня встал, так как канал у меня был слабый. И вот однажды нашел на форуме, посвященному этой прошивке, замечательный скрипт с названием nShaper (тема тут). Это был динамический шейпер, суть которого сводилась в динамическом распределении ширины канала в зависимости от типа и источника/назначения трафика. То есть он сам распределял скорость, в зависимости какой трафик проходит. И не надо было отключать торрент клиент, если кому-то в сети захотелось посидеть в ютубе или послушать музыку. Шейпер урезал скорость торренту и оставлял гарантированную полосу для остального трафика.

Но вот роутер отправился на заслуженный покой, а на смешу пришел полноценный Linux шлюз с Ubuntu. Конечно захотелось и на нем использовать этот шайпер. Сразу он работать отказался. Тогда я уже взял в руки "напильник" и стал заниматься "адаптацией", а после и тестированием. По ходу так же немного расширил функционал, добавив создание правил с использованием nDpi и iptables, и приоритезация трафика на основе маркировки трафика (через тот же ndpi или iptables). Скрипт в 2 версиях, с nDpi и без, если кому-то  nDpi не нужен.

Скрипт состоит из 3 файлов. 2 конфиг. файла (nshaper.conf и ip_z1.lst) и самого скрипта (nshaper.sh). Первые 2 лежат в /etc/nshaper, второй в /etc/init.d/ соответственно (естественно надо дать права на запуск и закинуть в автозагрузку при желании).

Конфиг достаточно простой. Основные параметры:

WAN_IF — интерфейс интернет соединения (eth0, ppp0 и т.п)
LAN_IF — интерфейс локальной сети

Если провайдер использует так называемый Russian PPTP, то так же указываем
pptp_ip — сервер подключения pptp
PPTP_IF – название сетевого интерфейса, который смотрит в сеть провайдера (интерфейс, куда воткнут кабель провайдера)
В противном случае их нужно закомментировать.

WAN_DN_RATE — максимально возможная скорость. Не физическая! Например если есть локальные ресурсы, то та самая скорость в локальной сети (если она к примеру выше, чем скорость интернет тарифа). Если же локальных ресурсов нет, то выставляем максимальную скорость интернет соединения. (К примеру, у меня тариф 40мбит Интернет и пиринговые зоны со скоростью 100мбит. Мне надо выставить 100000. Значения в кбит)
WAN_UP_RATE — тоже самое, но для исходящего канала.


WAN_ZONES – название зон. Первая зона всегда остается inet. Вторая уже на Ваш вкус. Если  таких зон нет, то оставляем только inet
ZONE_PATH – каталог с файлами зон. (по умолчанию там же, где и сам конфиг, /etc/nshaper)

WAN_ZONES_DN_RATE, WAN_ZONES_UP_RATE – скорость интернет соединения (входящая и исходящая). Значения в кбит. Первая цифра, это скорость интернет соединения. Вторая и последующая -  для пиринговых зон. Если зон нет, то указываем только скорость тарифа. Например WAN_ZONES_UP_RATE="40000 100000" или WAN_ZONES_UP_RATE="40000" если нет локальных ресурсов.

В этом же блоке настраиваются скорости для тарифов с ночным увеличением. По комментариям в конфиге думаю все понятно.

RATES="10 10 20 40 15 5"
INET_NAMES="200 201 202 203 204 205"
Приоритеты. % от максимальной ширины канала и их названия. % в принципе редактировать нет необходимости. В данном случае для первого и второго приоритета резервируется 10% канала, для второго 20%, для третьего 40%, для четвертого 15% и для самого низкого 5%. Если в какой-то очереди трафика нет, то его ширина «отдается» остальным. Но если канал забит, то каждый получает свой минимум. То есть запусти вы хоть 100 закачек торрента, свои 40% ширины веб трафик получит. Если же торрентов нет, то веб возьмет все что свободно.
Второй параметр это название приоритетов. Видны при просмотре статуса. Можно как угодно называть. Например Prio, Web, Torrent и т. д.

Синтаксис правил в конфиге подробно описан. Если будут вопросы, отвечу в комментариях.

Теперь требования для работы скрипта.
Во первых (и самое главное) нужна поддержка IMQ. Для этого нужно патчить ядро. В принципе ничего сложного нет. Инструкция тут же в блоге. Она же включает и сборку nDpi (не обязательно).
Во вторых модуль nDpi (если он нужен конечно)
В третьих  gawk, conntrack и ipcalc (для корректной работы скрипта).

Запуск скрипта /etc/init.d/nshaper start либо start2 (если нужен полный вывод статистики, подробней читать в nshaper.conf). Просмотр статистики /etc/init.d/nshaper status.

По CPU особых требований нет. У меня на шлюзе слабый AMD E-350 без проблем «переваривает»  40мбит/с интернет трафика + еще 50-60 пирингового.

Скрипт возможно не идеален. Но работает.  Если есть замечания — буду рад исправить.

Версия с nDpi и без. Работоспособность проверял на Centos 7 и Ubuntu 12.04/14.04. Без проблем должно работать и в Debian.

UPD. Обновил. Теперь получение адресов и маски через ip, а не ifconfig.

17 комментариев:

  1. на CentOS 7.1
    не парсит ip и маску
    [root@localhost nshaper]# ./nshaper.sh restart
    Remove Iptables and shaper rules
    Check availability IMQ and nDPI modules
    Check IP and MTU
    Activate interfaces
    Setup shapers
    Not enough bandwidth - limiting rate
    Not enough bandwidth - limiting rate
    Create class
    Apply filters and enable traffic redirection
    Syntax error: "flags=4099" at rule "lan ip enp5s0f1:/enp5s0f1: flags=4099 mtu 1500 afc 4 queue 1"
    Syntax error: "flags=4099" at rule "lan ip enp5s0f1:/enp5s0f1: flags=4099 mtu 1500 afc 3 queue 2"
    Syntax error: "flags=4099" at rule "lan ip enp5s0f1:/enp5s0f1: flags=4099 mtu 1500 queue 4"
    which: no conntrack in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
    Conntrack not found. Ignorring
    nShaper restarted

    ОтветитьУдалить
  2. сломал голову уже и так и этак, со скриптом и без пытаюсь ограничить трафик tc исходящий режет - входящий не в какую !!!

    ОтветитьУдалить
    Ответы
    1. Я сегодня поднял новую систему на Centos. К сожалению не успел со сборкой ядра, чтоб повторить Вашу ошибку. Думаю завтра смогу но свежей ОС проверить скрипт (хотя на старой работе тоже Centos 7 и там работало)

      У вас ifconfig есть? Пакет net-tools стоит? без него не сможет парсить.

      Удалить
  3. да есть
    enp5s0f0: flags=4163 mtu 1500
    inet 172.16.1.63 netmask 255.255.255.0 broadcast 172.16.1.255
    inet6 fe80::226:55ff:fe86:b0ac prefixlen 64 scopeid 0x20
    ether 00:26:55:86:b0:ac txqueuelen 1000 (Ethernet)
    RX packets 1158788 bytes 1735500032 (1.6 GiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 106927 bytes 34766662 (33.1 MiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
    device memory 0xfbe60000-fbe80000

    enp5s0f1: flags=4163 mtu 1500
    inet 172.16.1.61 netmask 255.255.255.0 broadcast 172.16.1.255
    inet6 fe80::226:55ff:fe86:b0ad prefixlen 64 scopeid 0x20
    ether 00:26:55:86:b0:ad txqueuelen 1000 (Ethernet)
    RX packets 751757 bytes 1010446070 (963.6 MiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 23782 bytes 7653639 (7.2 MiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
    device memory 0xfbee0000-fbf00000

    imq0: flags=193 mtu 1500
    unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 11000 (UNSPEC)
    RX packets 1143249 bytes 1704821789 (1.5 GiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 1143226 bytes 1704787473 (1.5 GiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    imq1: flags=193 mtu 1500
    unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 11000 (UNSPEC)
    RX packets 104117 bytes 32869313 (31.3 MiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 104076 bytes 32866269 (31.3 MiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    ОтветитьУдалить
    Ответы
    1. разный формат вывода информации. Попробую сегодня поправить.

      Удалить
  4. ошибок не выдаёт но и не режет входящий.
    пробую ручками
    tc qdisc del dev imq1 root
    tc qdisc del dev imq0 root

    ip link set imq0 up
    tc qdisc add dev imq0 root handle 1: htb default 10
    tc class add dev imq0 parent 1: classid 1:1 htb rate 10Mbit
    tc class add dev imq0 parent 1: classid 1:2 htb rate 10Mbit
    tc class add dev imq0 parent 1:1 classid 1:10 htb rate 10Mbit.
    tc class add dev imq0 parent 1:1 classid 1:20 htb rate 10Mbit.
    tc filter add dev imq0 parent 1: protocol ip prio 1 u32 match ip src 0.0.0.0/0 flowid 1:10
    tc filter add dev imq0 parent 1: protocol ip prio 1 u32 match ip dst 0.0.0.0/0 flowid 1:20

    ip link set imq1 up
    tc qdisc add dev imq1 root handle 2: htb default 20
    tc class add dev imq1 parent 2: classid 2:1 htb rate 10Mbit
    tc class add dev imq1 parent 2: classid 2:2 htb rate 10Mbit
    tc class add dev imq1 parent 2:1 classid 2:10 htb rate 5Mbit.
    tc class add dev imq1 parent 2:1 classid 2:20 htb rate 5Mbit.
    tc filter add dev imq1 parent 2: protocol ip prio 1 u32 match ip src 0.0.0.0/0 flowid 2:10
    tc filter add dev imq1 parent 2: protocol ip prio 1 u32 match ip dst 0.0.0.0/0 flowid 2:20

    +
    $IPTABLES -t mangle -A PREROUTING -i enp5s0f0 -j IMQ --todev 0

    $IPTABLES -t mangle -A POSTROUTING -o enp5s0f0 -j IMQ --todev 1

    трафик по интерфейсам ходит но входящий на клиенте не шейпит.

    ОтветитьУдалить
  5. http://c2n.me/3mJ8uCc Download rate практически не меняется

    ОтветитьУдалить
    Ответы
    1. так вроде бы скачено 25 мбайт и pps нормальный. Трафик детектится это точно. Может в конфиге что-то не так настроили?

      Удалить
    2. pps только на upload увеличивается, на доунлоад цифры практически постоянны!!!!
      ## Скорость приема
      WAN_DN_RATE=1000000
      ## Скорость отдачи
      WAN_UP_RATE=1000000
      WAN_ZONES="inet"

      if [ `date +%H` -ge 0 -a `date +%H` -le 7 ]; then
      ## Скорость приема и отдачи с 0 до 8.
      WAN_ZONES_DN_RATE="5000 5000"
      WAN_ZONES_UP_RATE="5000 5000"
      else
      ## Скорость приема и отдачи с 8 до 24
      WAN_ZONES_DN_RATE="10000 10000"
      WAN_ZONES_UP_RATE="10000 10000"
      fi

      всё в конфиге больше не менял
      Что-то мне подсказывает что это косяк гдето глубже.
      Думаю или центос 6 или убунту поставить.

      Удалить
    3. 1. Под Centos 6 не получится. Работает только под Centos 7 (я это даже указал), так как патч imq только для ядер 3 ветки. Под centos 6 ядра 3 ветки мне не удалось собрать, там только 2 ветки. Когда будет время займусь Centos 6 и патчами imq для 2 ветки.
      2. Сегодня тогда постараюсь закончить со сборкой ядра для своего Centos 7 и проверю там скрипт.

      Удалить
    4. Этот комментарий был удален автором.

      Удалить
    5. WAN_IF/LAN_IF правильно указали?

      Только что проверил у себя. Выставил 5 мбит и на входящий и на исходящий. Режет.

      Удалить
  6. Сам лоханулся. в одной сети настраивать - в итоге от шлюза инета входящий шёл напрямую. Вроде как начал резать - буду мучить дальше. Спасибо.

    ОтветитьУдалить