Advertisement
Guest User

rc.tc

a guest
Sep 7th, 2014
505
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 17.71 KB | None | 0 0
  1. #!/bin/bash
  2. # vim: sw=4 ts=4 expandtab ai
  3. TC="/sbin/tc"
  4. IPTABLES="/usr/sbin/iptables"
  5. IPROUTE="/sbin/ip"
  6. USAGE="Usage: $0 {start|stop|restart|status} output_interface"
  7. # Это сделано для запуска из ip-up/ip-down скрипта ppp.
  8.  
  9. # Каталог со списками пользователей
  10. LDIR="/etc/iplist"
  11.  
  12. # Если скрипт запустили вручную то нужно проверить наличие параметров DEV_OUT.
  13. if [ -z "$2" ] ; then
  14.     # Интерфейс, для подколючения к интернету, указываем обязательно.
  15.     echo "Not present output_interface"
  16.     echo $USAGE
  17.     exit 1
  18. else
  19.     DEV_OUT=$2
  20. fi
  21. ################################################################################
  22. # Настройки шейпинга
  23. #
  24. # xxx_OUT - относится к adsl интерфейсу, исходящему потоку.
  25. # xxx_IN - относится к интерфейсу локальной сети, но входящему
  26. # на adsl модем потоку :).
  27. # Длина очереди fifo на выходном интерфейсе.
  28. QLEN_OUT=10
  29. # Ограничение исходящей скорости,  кбит/с.
  30. # Рассчитывается на основании фактической исходящей скорости минус 15-20% в
  31. # зависимости от того, как плавает скорость при ADSL соединении.
  32. # Если скорость постоянна, можно снижать от фактической на 10%.
  33. RATE_OUT=10000
  34. # Размер MTU на выходном интерфейсе. В настройке указано для ADSL.
  35. MTU_OUT=1492
  36. # Интерфейс внутренней сети.
  37. DEV_IN=eth0
  38. # Ограничение входящей скорости.
  39. # Рассчитывается на основании фактической входящей скорости минус 10-15%.
  40. RATE_IN=7000
  41. # Длина очереди fifo на входном интерфейсе
  42. # (сетевой карте сервера, обращенной в локалку).
  43. QLEN_IN=1000
  44. # Скорость внутреннего интерфейса (сетевой карты сервера, обращенной в локалку).
  45. RATE_LOCAL=10mbit
  46. # Адрес самого сервера в локальной сети.
  47. IP_LOCAL="192.168.1.22"
  48. IP2_LOCAL="192.168.2.22"
  49. # Переменные, сокращающие длины команд и облегчающие их понимание.
  50. # Может используются не очень часто :) - но вдруг кому пригодится.
  51. TCP="match ip protocol 6 0xff"
  52. UDP="match ip protocol 17 0xff"
  53. DPORT="match ip dport"
  54. SPORT="match ip sport"
  55. SRC="match ip src"
  56. DST="match ip dst"
  57. MRK="match mark"
  58. U32="protocol ip u32"
  59. ################################################################################
  60.  
  61. ################################################################################
  62. # Настройки пользователей
  63. # Массив содержит информацию о пользователях сервера из локальной сети
  64. # Адреса пользователей принадлежат локальной сети. Формат записи:
  65. # [Порядк_ном]="IP Приоритет Мин_канала Макс_канала", где
  66. # Порядк_ном      - Номер строки по порядку. Повторение не допускается;
  67. # IP              - IP адрес пользователя;
  68. # Приоритет       - Приоритет пользователя, чем меньше значение тем лучше;
  69. # Мин_канала      - Число обозначающее сколько частей пропускной способности
  70. #                   канала нужно гарантировано выделить пользователю, например
  71. #                   есть Вася с 2, Петя с 1 и Коля с 1, тогда канал распреде-
  72. #                   литься так - Васе достанется 2/(2+1+1)=0,5 канала,
  73. #                   Пете - 1/(2+1+1)=0,25 и Коле тоже 0,25;
  74. # Макс_канала     - Число от 1 до 100, показывающее какую часть общего канала
  75. #                   можно выделить пользователю, если канал свободен. Значение
  76. #                   1 будет равно 0,01 канала, 100 соответствует каналу целиком;
  77. # Для временного отключения клиентов допускается комментировать строки.
  78. LOCAL_IPS=( $(cat ${LDIR}/ipmac.lst ${LDIR}/nedobooks.lst ${LDIR}/volonteers.lst | cut -f1 -d'#' | grep 192.168 | cut -f1 -d',') )
  79. for i in $(seq $(echo ${#LOCAL_IPS[@]})); do
  80.     if [ "a$(echo ${LOCAL_IPS[$((i - 1))]} | cut -f3 -d'.')" == "a1" ]; then
  81.         LOCAL_IPS[$((i - 1))]="${LOCAL_IPS[$((i - 1))]} 1 4 85"
  82.     else
  83.         LOCAL_IPS[$((i - 1))]="${LOCAL_IPS[$((i - 1))]} 1 9 55"
  84.     fi
  85. done
  86. #echo ${LOCAL_IPS[@]}
  87. ################################################################################
  88. # Шейпер подразумевает разбиение выделенной полосы пропускания на конечное
  89. # число полос. Каждая полоса обеспечивает гарантированный трафик в выделенных
  90. # пределах. Чем больше полос, тем меньший гарантированный трафик приходится на
  91. # одну. Расчет общего количества полос производится так:
  92. # Количество полоc = Cпециальные полосы + Общее количество полос пользователей
  93.  
  94. # Спец полосы - по ним пойдет общий для всех пользователей трафик по UDP и ASK
  95. # пакеты, но с наивысшим приоритетом, а так же прочий неклассифицированный
  96. # трафик, с низким приоритетом.
  97. # Число меняется только при изменении в программе.
  98. NNN=$((count+3))
  99.  
  100. # Общее количество полос.
  101. # Получается сложением полос для всех пользователей, и спец полос.
  102. #for client in "${LOCAL_IPS[@]}"; do
  103. #    if [ -z "$client" ]; then continue; fi
  104. #    let "NNN += `echo $client | awk '{print $3}'`"
  105. #done
  106.  
  107. ShaperStatus(){
  108.     # Показываем настройки шэйпера.
  109.     echo "SHAPER SETTINGS"
  110.     echo
  111.     echo "[qdisc out]"
  112.     $TC -s -d qdisc show dev $DEV_OUT
  113.     echo
  114.     echo "[class out]"
  115.     $TC -s -d class show dev $DEV_OUT
  116.     echo
  117.     echo "[filter out]"
  118.     $TC -s filter show dev $DEV_OUT
  119.     echo
  120.     echo "-----------------------------------------------------------------"
  121.     echo "[qdisc in]"
  122.     $TC -s -d qdisc show dev $DEV_IN
  123.     echo
  124.     echo "[class in]"
  125.     $TC -s -d class show dev $DEV_IN
  126.     echo
  127.     echo "[filter in]"
  128.     $TC -s filter show dev $DEV_IN
  129.     echo
  130. }
  131.  
  132. ShaperStopAll(){
  133.     # Удаляем все настройки шэйпинга. Используется для остановки
  134.     # или перезапуска.
  135.     $TC qdisc del dev $DEV_OUT ingress 2> /dev/null > /dev/null
  136.     $TC qdisc del dev $DEV_OUT root 2> /dev/null > /dev/null
  137.     $TC qdisc del dev $DEV_IN ingress 2> /dev/null > /dev/null
  138.     $TC qdisc del dev $DEV_IN root 2> /dev/null > /dev/null
  139.     echo "Shaping removed on $DEV_OUT/$DEV_IN."
  140. }
  141.  
  142. ShaperStartOut(){
  143.     ############################################################################
  144.     # Ограничение скорости для SYN пакетов. Закомментировать если не требуется
  145.     # ограничить скорость создания новых подключений.
  146.     # На входном интерфейсе используется для защиты от SYN-атаки из интернета.
  147.     # Актуально, если разрешены любые входящие подключения из интернета.
  148. #    $TC qdisc add dev $DEV_OUT handle ffff: ingress
  149. #    $TC filter add dev $DEV_OUT parent ffff: protocol ip prio 0 handle 1 fw police rate 100kbit burst 1500 mtu 9k drop flowid :1
  150.     ############################################################################
  151.  
  152.     $TC qdisc add dev $DEV_OUT root handle 1: htb default 17
  153.  
  154.     $TC class add dev $DEV_OUT parent 1: classid 1:1 htb rate $[$RATE_OUT]kbit
  155.     # Специальным видам трафика выделяем по одной полосе.
  156.     $TC class add dev $DEV_OUT parent 1:1 classid 1:10 htb rate $[$RATE_OUT/$NNN]kbit ceil $[$RATE_OUT/20]kbit prio 1
  157.     $TC class add dev $DEV_OUT parent 1:1 classid 1:12 htb rate $[$RATE_OUT/$NNN]kbit ceil $[$RATE_OUT/4]kbit prio 2
  158.     $TC class add dev $DEV_OUT parent 1:1 classid 1:17 htb rate $[$RATE_OUT/$NNN]kbit ceil $[$RATE_OUT/4]kbit prio 7
  159.  
  160.     # DNS запросы самые приоритетные.
  161.     $TC filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $SPORT 53 0xffff classid 1:10
  162.     $TC filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $DPORT 53 0xffff classid 1:10
  163.  
  164.     ############################################################################
  165.     # Короткие SYN пакеты, для установки соединения, отправляем в ту же полосу.
  166.     # Это увеличит скорость установления новых соединий, что при сильной загрузке
  167.     # канала обеспечит сохранение минимальной паузы при открытии новой Web страницы.
  168.     # Закоментировать, если используется очередь ingress на входном интерфейсе
  169.     # и Вы не доверяете локальной сети.
  170.     $TC filter add dev $DEV_OUT parent 1:0 protocol ip prio 3 handle 1 fw flowid 1:10
  171.     ############################################################################
  172.  
  173.     # Все прочие udp пакеты. Возможно, некоторые пиринговые сети будут жить в
  174.     # этой полосе. Но в основном для игрушек, которые не попали в более
  175.     # приоритетную полосу.
  176.     $TC filter add dev $DEV_OUT parent 1:0 prio 4 $U32 $UDP classid 1:12
  177.  
  178.     #Организуем очереди для специальных полос.
  179.     $TC qdisc add dev $DEV_OUT parent 1:10 handle 10: sfq perturb 5
  180.     $TC qdisc add dev $DEV_OUT parent 1:12 handle 12: sfq perturb 5
  181.  
  182.     # Это прочий (неклассифицированный) трафик.
  183.     $TC qdisc add dev $DEV_OUT parent 1:17 handle 17: sfq perturb 10
  184.  
  185.     # Классы клиентов.
  186.     j=21
  187.     for client in "${LOCAL_IPS[@]}"; do
  188.         if [ -z "$client" ]; then continue; fi
  189.         # Это определяются переменные для выражения.
  190.         prio=`echo $client | awk '{print $2}'`
  191.         let "rate= $RATE_OUT / $NNN * `echo $client | awk '{print $3}'`"
  192.         let "cell= $RATE_OUT / 100 * `echo $client | awk '{print $4}'`"
  193.         # Создаем полосы для клиентов.
  194.         $TC class add dev $DEV_OUT parent 1:1 classid 1:$j htb rate $[$rate]kbit ceil $[cell]kbit prio $prio
  195.         # Создаем фильтры для машин сети.
  196.         $TC filter add dev $DEV_OUT parent 1:0 protocol ip prio $j handle $j fw flowid 1:$j
  197.         # Теперь создаем очереди для машин сети.
  198.         $TC qdisc add dev $DEV_OUT parent 1:$j handle $j: sfq perturb 5
  199.         let "j += 1"
  200.     done
  201.     echo "Outbound shaping added to $DEV_OUT.  Rate: ${RATE_OUT}Kbit/sec."
  202. }
  203.  
  204. ShaperStartIn(){
  205.     # Это шейпер на внутреннюю сеть, то есть на входящий трафик.
  206.     $IPROUTE link set dev $DEV_IN qlen $QLEN_IN
  207.  
  208.     ############################################################################
  209.     # Добавляем особый тип очереди - ingress, что контролирует вход интерфейса.
  210.     # Собственно, ограничиваем количество входящих! коннектов в секунду.
  211.     # Раскомментировать, если Вы не доверяете локальной сети.
  212.     #$TC qdisc add dev $DEV_IN handle ffff: ingress
  213.     #$TC filter add dev $DEV_IN parent ffff: protocol ip prio 0 handle 1 fw  police rate 200kbit burst 1500 mtu 9k drop flowid :1
  214.     ############################################################################
  215.  
  216.     $TC qdisc add dev $DEV_IN root handle 1: htb default 17
  217.     $TC class add dev $DEV_IN parent 1: classid 1:1 htb rate ${RATE_IN}kbit
  218.     $TC class add dev $DEV_IN parent 1:1 classid 1:10 htb rate $[$RATE_IN/$NNN]kbit ceil $[$RATE_IN/20]kbit prio 0
  219.     $TC class add dev $DEV_IN parent 1:1 classid 1:12 htb rate $[$RATE_IN/$NNN]kbit ceil $[$RATE_IN/4]kbit prio 2
  220.  
  221.     # Полоса для неопределенного трафика.
  222.     $TC class add dev $DEV_IN parent 1:1 classid 1:17 htb rate $[$RATE_IN/$NNN]kbit ceil $[$RATE_IN/4]kbit prio 7
  223.  
  224.     # Примерно тоже самое, только этот интерфейс работает с локальной сетью.
  225.     $TC class add dev $DEV_IN parent 1: classid 1:2 htb rate $RATE_LOCAL prio 7
  226.  
  227.     # Через этот класс пропускается не транзитный с adsl модема трафик, а
  228.     # исходящий с роутера, поэтому используется другой, более высокий rate,
  229.     # а это фильтр для него.
  230.     $TC filter add dev $DEV_IN parent 1:0 prio 1 $U32 $SRC $IP_LOCAL classid 1:2
  231.     #  это фильтр для DNS.
  232.     $TC filter add dev $DEV_IN parent 1:0 prio 2 $U32 $SPORT 53 0xffff classid 1:10
  233.     $TC filter add dev $DEV_IN parent 1:0 prio 3 $U32 $DPORT 53 0xffff classid 1:10
  234.     ############################################################################
  235.     # Короткие SYN  пакеты, для установки соединения, отправляем в ту же полосу.
  236.     # Раскоментировать, если не используется (закоментирована) очередь ingress
  237.     # на исходящем интерфейсе.
  238.     $TC filter add dev $DEV_IN parent 1:0 protocol ip prio 4 handle 1 fw flowid 1:10
  239.     ############################################################################
  240.     # Это фильтр для прочих UDP соединений.
  241.     $TC filter add dev $DEV_IN parent 1:0 prio 5 $U32 $UDP classid 1:12
  242.  
  243.     # Использую самую простую и легкую для процессора очередь pfifo для
  244.     # исходящего с роутера трафика (не транзитный!).
  245.     $TC qdisc add dev $DEV_IN parent 1:2 handle 2: pfifo
  246.     # Очереди для DNS и UDP.
  247.     $TC qdisc add dev $DEV_IN parent 1:10 handle 10: sfq perturb 5
  248.     $TC qdisc add dev $DEV_IN parent 1:12 handle 12: sfq perturb 5
  249.  
  250.     # Это прочий неклассифицированный трафик.
  251.     $TC qdisc add dev $DEV_IN parent 1:17 handle 17: sfq perturb 15
  252.  
  253.     # Полосы для клиентских машин.
  254.     j=21
  255.     for client in "${LOCAL_IPS[@]}"; do
  256.          if [ -z "$client" ]; then continue; fi
  257.          # Это определяются переменные для выражения.
  258.          ip=`echo $client | awk '{print $1}'`
  259.          prio=`echo $client | awk '{print $2}'`
  260.          let "rate= $RATE_IN / $NNN * `echo $client | awk '{print $3}'`"
  261.          let "cell= $RATE_IN / 100 * `echo $client | awk '{print $4}'`"
  262.          # Создаем полосы для клиентов.
  263.          $TC class add dev $DEV_IN  parent 1:1 classid 1:$j htb rate $[$rate]kbit  ceil $[cell]kbit prio $prio
  264.          # Фильтры для них же.
  265.          $TC filter add dev $DEV_IN parent 1:0 prio $j $U32 $DST $ip classid 1:$j
  266.          # Очереди.
  267.          $TC qdisc add dev $DEV_IN parent 1:$j handle $j: sfq perturb 5
  268.          let "j += 1"
  269.     done
  270.     echo "Outbound shaping added to $DEV_IN.  Rate: ${RATE_IN}Kbit/sec."
  271. }
  272.  
  273. Marking(){
  274.     action=$1
  275.     j=21
  276. #    echo ${LOCAL_IPS[@]}
  277.     for client in "${LOCAL_IPS[@]}"; do
  278.         if [ -z "$client" ]; then continue; fi
  279.         ip=`echo $client | awk '{print $1}'`
  280.         # Маркируем пакеты для клиентов.
  281.         # Это действие требуется для распределения клиентов по полосам.
  282.         $IPTABLES $action PREROUTING -t mangle -s $ip -j MARK --set-mark $j
  283.         let "j += 1"
  284.     done
  285.     # Маркируем syn пакеты.
  286.     $IPTABLES $action PREROUTING -t mangle -p tcp --syn -j MARK --set-mark 1
  287.     # Назначаем одинаковое время жизни для пакетов.
  288. #    $IPTABLES $action PREROUTING -t mangle -i $DEV_IN -j TTL --ttl-set 64
  289. }
  290.  
  291. case "$1" in
  292. start)
  293.     Marking "-A"
  294.     ShaperStartIn
  295.     ShaperStartOut
  296.     ;;
  297. stop)
  298.     ShaperStopAll
  299.     Marking "-D"
  300.     ;;
  301. status)
  302.     ShaperStatus
  303.     ;;
  304. restart)
  305.     ShaperStopAll
  306.     Marking "-D"
  307.     Marking "-A"
  308.     ShaperStartIn
  309.     ShaperStartOut
  310.     ;;
  311. *)
  312.     echo $USAGE
  313. esac
  314.  
  315. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement