Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- # vim: sw=4 ts=4 expandtab ai
- TC=`which tc`
- IPTABLES=`which iptables`
- IPROUTE=`which ip`
- USAGE="Usage: $0 {start|stop|restart|status} output_interface"
- CAT=`which cat`
- CUT=`which cut`
- WC=`which wc`
- # Это сделано для запуска из ip-up/ip-down скрипта ppp.
- # Каталог со списками пользователей
- LDIR="/etc/iplist"
- # Если скрипт запустили вручную то нужно проверить наличие параметров DEV_OUT.
- if [ -z "$2" ] ; then
- # Интерфейс, для подколючения к интернету, указываем обязательно.
- echo "Not present output_interface"
- echo $USAGE
- exit 1
- else
- DEV_OUT=$2
- fi
- ################################################################################
- # Настройки шейпинга
- #
- # xxx_OUT - относится к adsl интерфейсу, исходящему потоку.
- # xxx_IN - относится к интерфейсу локальной сети, но входящему
- # на adsl модем потоку :).
- # Длина очереди fifo на выходном интерфейсе.
- QLEN_OUT=10
- # Ограничение исходящей скорости, кбит/с.
- # Рассчитывается на основании фактической исходящей скорости минус 15-20% в
- # зависимости от того, как плавает скорость при ADSL соединении.
- # Если скорость постоянна, можно снижать от фактической на 10%.
- RATE_OUT=100000
- # Размер MTU на выходном интерфейсе. В настройке указано для ADSL.
- MTU_OUT=1492
- # Интерфейс внутренней сети.
- DEV_IN=eth0
- # Ограничение входящей скорости.
- # Рассчитывается на основании фактической входящей скорости минус 10-15%.
- RATE_IN=80000
- # Длина очереди fifo на входном интерфейсе
- # (сетевой карте сервера, обращенной в локалку).
- QLEN_IN=1000
- # Скорость внутреннего интерфейса (сетевой карты сервера, обращенной в локалку).
- RATE_LOCAL=100mbit
- # Адрес самого сервера в локальной сети.
- IP_LOCAL="192.168.1.33"
- IP2_LOCAL="192.168.2.33"
- # Переменные, сокращающие длины команд и облегчающие их понимание.
- # Может используются не очень часто :) - но вдруг кому пригодится.
- TCP="match ip protocol 6 0xff"
- UDP="match ip protocol 17 0xff"
- DPORT="match ip dport"
- SPORT="match ip sport"
- SRC="match ip src"
- DST="match ip dst"
- MRK="match mark"
- U32="protocol ip u32"
- ################################################################################
- ################################################################################
- # Настройки пользователей
- # Массив содержит информацию о пользователях сервера из локальной сети
- # Адреса пользователей принадлежат локальной сети. Формат записи:
- # [Порядк_ном]="IP Приоритет Мин_канала Макс_канала", где
- # Порядк_ном - Номер строки по порядку. Повторение не допускается;
- # IP - IP адрес пользователя;
- # Приоритет - Приоритет пользователя, чем меньше значение тем лучше;
- # Мин_канала - Число обозначающее сколько частей пропускной способности
- # канала нужно гарантировано выделить пользователю, например
- # есть Вася с 2, Петя с 1 и Коля с 1, тогда канал распреде-
- # литься так - Васе достанется 2/(2+1+1)=0,5 канала,
- # Пете - 1/(2+1+1)=0,25 и Коле тоже 0,25;
- # Макс_канала - Число от 1 до 100, показывающее какую часть общего канала
- # можно выделить пользователю, если канал свободен. Значение
- # 1 будет равно 0,01 канала, 100 соответствует каналу целиком;
- # Для временного отключения клиентов допускается комментировать строки.
- IPS=( $($CAT ${LDIR}/dhcpd.lst) )
- for i in $(seq $(echo ${#IPS[@]}) ); do
- if [ "a$(echo ${IPS[$((i - 1))]} | $CUT -f2 -d';')" = "agw33-100mbit" ]; then
- LOCAL_IPS[${i}]="$(echo ${IPS[$((i - 1 ))]} | $CUT -f1 -d',') 1 4 85"
- elif [ "a$(echo ${IPS[$((i - 1))]} | $CUT -f2 -d';')" = "agw33-limited" ]; then
- LOCAL_IPS[${i}]="$(echo ${IPS[$((i - 1))]} | $CUT -f1 -d',') 9 1 2"
- elif [ "a$(echo ${IPS[$((i - 1))]} | $CUT -f2 -d';')" = "agw33-2-limited" ]; then
- LOCAL_IPS[${i}]="$(echo ${IPS[$((i - 1))]} | $CUT -f1 -d',') 9 1 2"
- elif [ "a$(echo ${IPS[$((i - 1))]} | $CUT -f2 -d';')" = "ablock" ]; then
- : # LOCAL_IPS[${i}]="$(echo ${IPS[$((i - 1))]} | $CUT -f1 -d',') 10 1 0"
- else
- : #LOCAL_IPS[${i}]="$(echo ${IPS[$(( i -1 ))]} | $CUT -f1 -d',') 10 1 0"
- fi
- # echo ${LOCAL_IPS[${i}]}
- done
- #echo ${LOCAL_IPS[@]}
- ################################################################################
- # Шейпер подразумевает разбиение выделенной полосы пропускания на конечное
- # число полос. Каждая полоса обеспечивает гарантированный трафик в выделенных
- # пределах. Чем больше полос, тем меньший гарантированный трафик приходится на
- # одну. Расчет общего количества полос производится так:
- # Количество полоc = Cпециальные полосы + Общее количество полос пользователей
- # Спец полосы - по ним пойдет общий для всех пользователей трафик по UDP и ASK
- # пакеты, но с наивысшим приоритетом, а так же прочий неклассифицированный
- # трафик, с низким приоритетом.
- # Число меняется только при изменении в программе.
- NNN=$((count+3))
- # Общее количество полос.
- # Получается сложением полос для всех пользователей, и спец полос.
- #for client in "${LOCAL_IPS[@]}"; do
- # if [ -z "$client" ]; then continue; fi
- # let "NNN += `echo $client | awk '{print $3}'`"
- #done
- ShaperStatus(){
- # Показываем настройки шэйпера.
- echo "SHAPER SETTINGS"
- echo
- echo "[qdisc out]"
- $TC -s -d qdisc show dev $DEV_OUT
- echo
- echo "[class out]"
- $TC -s -d class show dev $DEV_OUT
- echo
- echo "[filter out]"
- $TC -s filter show dev $DEV_OUT
- echo
- echo "-----------------------------------------------------------------"
- echo "[qdisc in]"
- $TC -s -d qdisc show dev $DEV_IN
- echo
- echo "[class in]"
- $TC -s -d class show dev $DEV_IN
- echo
- echo "[filter in]"
- $TC -s filter show dev $DEV_IN
- echo
- }
- ShaperStopAll(){
- # Удаляем все настройки шэйпинга. Используется для остановки
- # или перезапуска.
- $TC qdisc del dev $DEV_OUT ingress 2> /dev/null > /dev/null
- $TC qdisc del dev $DEV_OUT root 2> /dev/null > /dev/null
- $TC qdisc del dev $DEV_IN ingress 2> /dev/null > /dev/null
- $TC qdisc del dev $DEV_IN root 2> /dev/null > /dev/null
- echo "Shaping removed on $DEV_OUT/$DEV_IN."
- }
- ShaperStartOut(){
- ############################################################################
- # Ограничение скорости для SYN пакетов. Закомментировать если не требуется
- # ограничить скорость создания новых подключений.
- # На входном интерфейсе используется для защиты от SYN-атаки из интернета.
- # Актуально, если разрешены любые входящие подключения из интернета.
- # $TC qdisc add dev $DEV_OUT handle ffff: ingress
- # $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
- ############################################################################
- $TC qdisc add dev $DEV_OUT root handle 1: htb default 17
- $TC class add dev $DEV_OUT parent 1: classid 1:1 htb rate $[$RATE_OUT]kbit
- # Специальным видам трафика выделяем по одной полосе.
- $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
- $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
- $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
- # DNS запросы самые приоритетные.
- $TC filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $SPORT 53 0xffff classid 1:10
- $TC filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $DPORT 53 0xffff classid 1:10
- ############################################################################
- # Короткие SYN пакеты, для установки соединения, отправляем в ту же полосу.
- # Это увеличит скорость установления новых соединий, что при сильной загрузке
- # канала обеспечит сохранение минимальной паузы при открытии новой Web страницы.
- # Закоментировать, если используется очередь ingress на входном интерфейсе
- # и Вы не доверяете локальной сети.
- $TC filter add dev $DEV_OUT parent 1:0 protocol ip prio 3 handle 1 fw flowid 1:10
- ############################################################################
- # Все прочие udp пакеты. Возможно, некоторые пиринговые сети будут жить в
- # этой полосе. Но в основном для игрушек, которые не попали в более
- # приоритетную полосу.
- $TC filter add dev $DEV_OUT parent 1:0 prio 4 $U32 $UDP classid 1:12
- #Организуем очереди для специальных полос.
- $TC qdisc add dev $DEV_OUT parent 1:10 handle 10: sfq perturb 5
- $TC qdisc add dev $DEV_OUT parent 1:12 handle 12: sfq perturb 5
- # Это прочий (неклассифицированный) трафик.
- $TC qdisc add dev $DEV_OUT parent 1:17 handle 17: sfq perturb 10
- # Классы клиентов.
- j=21
- for client in "${LOCAL_IPS[@]}"; do
- if [ -z "$client" ]; then continue; fi
- # Это определяются переменные для выражения.
- prio=`echo $client | awk '{print $2}'`
- let "rate= $RATE_OUT / $NNN * `echo $client | awk '{print $3}'`"
- let "cell= $RATE_OUT / 100 * `echo $client | awk '{print $4}'`"
- # Создаем полосы для клиентов.
- $TC class add dev $DEV_OUT parent 1:1 classid 1:$j htb rate $[$rate]kbit ceil $[cell]kbit prio $prio
- # Создаем фильтры для машин сети.
- $TC filter add dev $DEV_OUT parent 1:0 protocol ip prio $j handle $j fw flowid 1:$j
- # Теперь создаем очереди для машин сети.
- $TC qdisc add dev $DEV_OUT parent 1:$j handle $j: sfq perturb 5
- let "j += 1"
- done
- echo "Outbound shaping added to $DEV_OUT. Rate: ${RATE_OUT}Kbit/sec."
- }
- ShaperStartIn(){
- # Это шейпер на внутреннюю сеть, то есть на входящий трафик.
- $IPROUTE link set dev $DEV_IN qlen $QLEN_IN
- ############################################################################
- # Добавляем особый тип очереди - ingress, что контролирует вход интерфейса.
- # Собственно, ограничиваем количество входящих! коннектов в секунду.
- # Раскомментировать, если Вы не доверяете локальной сети.
- #$TC qdisc add dev $DEV_IN handle ffff: ingress
- #$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
- ############################################################################
- $TC qdisc add dev $DEV_IN root handle 1: htb default 17
- $TC class add dev $DEV_IN parent 1: classid 1:1 htb rate ${RATE_IN}kbit
- $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
- $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
- # Полоса для неопределенного трафика.
- $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
- # Примерно тоже самое, только этот интерфейс работает с локальной сетью.
- $TC class add dev $DEV_IN parent 1: classid 1:2 htb rate $RATE_LOCAL prio 7
- # Через этот класс пропускается не транзитный с adsl модема трафик, а
- # исходящий с роутера, поэтому используется другой, более высокий rate,
- # а это фильтр для него.
- $TC filter add dev $DEV_IN parent 1:0 prio 1 $U32 $SRC $IP_LOCAL classid 1:2
- # это фильтр для DNS.
- $TC filter add dev $DEV_IN parent 1:0 prio 2 $U32 $SPORT 53 0xffff classid 1:10
- $TC filter add dev $DEV_IN parent 1:0 prio 3 $U32 $DPORT 53 0xffff classid 1:10
- ############################################################################
- # Короткие SYN пакеты, для установки соединения, отправляем в ту же полосу.
- # Раскоментировать, если не используется (закоментирована) очередь ingress
- # на исходящем интерфейсе.
- $TC filter add dev $DEV_IN parent 1:0 protocol ip prio 4 handle 1 fw flowid 1:10
- ############################################################################
- # Это фильтр для прочих UDP соединений.
- $TC filter add dev $DEV_IN parent 1:0 prio 5 $U32 $UDP classid 1:12
- # Использую самую простую и легкую для процессора очередь pfifo для
- # исходящего с роутера трафика (не транзитный!).
- $TC qdisc add dev $DEV_IN parent 1:2 handle 2: pfifo
- # Очереди для DNS и UDP.
- $TC qdisc add dev $DEV_IN parent 1:10 handle 10: sfq perturb 5
- $TC qdisc add dev $DEV_IN parent 1:12 handle 12: sfq perturb 5
- # Это прочий неклассифицированный трафик.
- $TC qdisc add dev $DEV_IN parent 1:17 handle 17: sfq perturb 15
- # Полосы для клиентских машин.
- j=21
- for client in "${LOCAL_IPS[@]}"; do
- if [ -z "$client" ]; then continue; fi
- # Это определяются переменные для выражения.
- ip=`echo $client | awk '{print $1}'`
- prio=`echo $client | awk '{print $2}'`
- let "rate= $RATE_IN / $NNN * `echo $client | awk '{print $3}'`"
- let "cell= $RATE_IN / 100 * `echo $client | awk '{print $4}'`"
- # Создаем полосы для клиентов.
- $TC class add dev $DEV_IN parent 1:1 classid 1:$j htb rate $[$rate]kbit ceil $[cell]kbit prio $prio
- # Фильтры для них же.
- $TC filter add dev $DEV_IN parent 1:0 prio $j $U32 $DST $ip classid 1:$j
- # Очереди.
- $TC qdisc add dev $DEV_IN parent 1:$j handle $j: sfq perturb 5
- let "j += 1"
- done
- echo "Outbound shaping added to $DEV_IN. Rate: ${RATE_IN}Kbit/sec."
- }
- Marking(){
- action=$1
- j=21
- for client in "${LOCAL_IPS[@]}"; do
- if [ -z "$client" ]; then continue; fi
- ip=`echo $client | awk '{print $1}'`
- # Маркируем пакеты для клиентов.
- # Это действие требуется для распределения клиентов по полосам.
- $IPTABLES $action PREROUTING -t mangle -s $ip -j MARK --set-mark $j
- let "j += 1"
- done
- # Маркируем syn пакеты.
- $IPTABLES $action PREROUTING -t mangle -p tcp --syn -j MARK --set-mark 1
- # Назначаем одинаковое время жизни для пакетов.
- # $IPTABLES $action PREROUTING -t mangle -i $DEV_IN -j TTL --ttl-set 64
- }
- case "$1" in
- start)
- Marking "-A"
- ShaperStartIn
- ShaperStartOut
- ;;
- stop)
- ShaperStopAll
- Marking "-D"
- ;;
- status)
- ShaperStatus
- ;;
- restart)
- ShaperStopAll
- Marking "-D"
- Marking "-A"
- ShaperStartIn
- ShaperStartOut
- ;;
- *)
- echo $USAGE
- esac
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement