#! /bin/bash # Firewall nove generace pro Czela Debian 3.0 # Autor: Mirek Slugen # Spoluatori: Michal Perlik, Michal Vondracek, Jan Chmelensky # Vytvoreno: 06.11.2006 # Naposledy zmeneno: 08.03.2009 # Tento skript muzete volne sirit a upravovat. # implementace QoSu qos_start() { # Před každým spuštěním QoSu musíme předchozí QoS ukončit, raději i pokud nebyl aktivní qos_stop echo "Starting QoS..." # lokální proměnné local I="" local J="" local QOS="" local DEV="" local DEV_2="" local RATE="" local DUPLEX="" local DIRECTION="" local COUNT="0" local DEVS="" local RATES="" local DUPLEXS="" local DIRECTIONS="" local CLASS="" local CLASS_DEV="" local CLASS_MIN="" local CLASS_MAX="" local CLASSES="" local RATE_MIN="" # Zjistime rozhrani, na kterych chceme mit spusteny QoS I="0" while [ "$I" -lt 20 ]; do DEV=DEV${I}_IFACE DEV=${!DEV} QOS=DEV${I}_QOS QOS=${!QOS} RATE=DEV${I}_QOS_RATE RATE=${!RATE} DUPLEX=DEV${I}_QOS_DUPLEX DUPLEX=${!DUPLEX} DIRECTION=DEV${I}_QOS_DIRECTION DIRECTION=${!DIRECTION} # inkrementujeme před continue ((I++)) [ "$DEV" == "" ] && continue [ "$QOS" != "yes" ] && continue [ "$RATE" == "" ] && continue [ "$DUPLEX" == "" ] && continue [ "$DIRECTION" == "" ] && continue DEVS[$COUNT]="$DEV" RATES[$COUNT]="$RATE" DUPLEXES[$COUNT]="$DUPLEX" DIRECTIONS[$COUNT]="$DIRECTION" ((COUNT++)) done # skončíme pokud nejsou rozhraní na kterých bychom QoS spustili if [ "$COUNT" -lt "1" ]; then echo "there is no QoS interface!" return 0 fi # Zavedeni modulu pro imq a ifb , v nové verzi už není třeba modul znovu zavádět, v kernelu 2.6.26 # a vyšším je problém s odstraněním modulu z paměti (rmmod), jednoduchý test problému: # modprobe imq # iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0 # ip link set imq0 up # sleep 5 # ping www.seznam.cz -c 2 # iptables -t mangle -F # ip link set imq0 down # sleep 0.5 # rmmod imq # # Proto zavedeme imq a ifb s maximálním množstvím zařízení abychom ho nemuseli při změně počtu # zařízení znovu zavádět. Nezavádíme imq modul, pokud už je zaveden! if [ "$QOS_DEVICE" == "imq" ]; then [ "`lsmod | awk '{print \$1}' | grep -x \"imq\"`" == "" ] && modprobe imq numdevs=16 &>/dev/null elif [ "$QOS_DEVICE" == "ifb" ]; then [ "`lsmod | awk '{print \$1}' | grep -x \"ifb\"`" == "" ] && modprobe ifb numifbs=16 &>/dev/null fi # Nahození příslušních rozhraní, pro fungovaní QoSu je potřeba rozhraní nahodit if [ "$QOS_DEVICE" == "imq" ] || [ "$QOS_DEVICE" == "ifb" ]; then I="0" while [ "$I" -lt "$COUNT" ]; do $IP link set ${QOS_DEVICE}$I up ((I++)) done fi # Na získaná rozhraní nasadíme QoS I="0" for DEV in ${DEVS[@]}; do RATE="${RATES[$I]}" DIRECTION="${DIRECTIONS[$I]}" DUPLEX="${DUPLEXES[$I]}" # Kontrola na minimální rychlost rozhraní if [ "$RATE" -lt 10 ]; then echo "Rate on $DEV is too small!" ((I++)) continue fi # Pro HTB vypočítáme R2Q if [ "$QOS_LIMIT_TYPE" == "htb" ]; then if [ "$RATE" -lt 20 ]; then echo "Rate on $DEV is too small for HTB R2Q, try set QOS_LIMIT_TYPE to HFSC!" R2Q="1" elif [ "$RATE" -lt 100 ]; then R2Q="1" else R2Q="$[$RATE/100]" fi fi # speciální garantované třídy CLASSES="" RATE_MIN="0" J="1" while true; do CLASS_DEV=CLASS_${J}_DEV CLASS_DEV=${!CLASS_DEV} [ "$CLASS_DEV" == "" ] && break if [ "$CLASS_DEV" != "$DEV" ] && [ "$CLASS_DEV" != "all" ]; then ((J++)) continue fi CLASS_MIN=CLASS_${J}_MIN CLASS_MIN=${!CLASS_MIN} CLASS_MAX=CLASS_${J}_MAX CLASS_MAX=${!CLASS_MAX} # garantovaná rychlost nemůže být větší než maximální rychlost na rozhraní if [ "$CLASS_MIN" -ge "$RATE" ]; then ((J++)) continue fi CLASSES=$CLASSES"$J $CLASS_MIN $CLASS_MAX " RATE_MIN=$(($RATE_MIN + $CLASS_MIN)) ((J++)) done # kontrola na překročení maximální rychlosti rozhraní, potřebujeme alespoň 10 kbitů navíc if [ "$(($RATE - $RATE_MIN))" -lt "10" ]; then echo "Byla vypoctena pozadovana garantovana rychlost $RATE_MIN, garantovana rychlost na" echo "rozhrani $DEV muze byt maximalne $(($RATE - 10)), snizte garantovane rychlosti," echo "nebo nastavte garantovane tridy na konkretni rozhrani, misto rozhrani \"all\"." echo "" echo "Garantovane tridy pro rozhrani $DEV budou vynechany!" echo "" CLASSES="" fi # Pomocná rozhraní jako IFB a IMQ if [ "$QOS_DEVICE" != "" ]; then DEV_2="${QOS_DEVICE}$I" echo " $DEV rate ${RATE} kbit/s with $DEV_2 type $DUPLEX" if [ "$QOS_DEVICE" == "imq" ]; then if [ "$DUPLEX" == "HD" ]; then if [ "$DUMMY_IFACE" != "" ]; then [ "$DUMMY_IP" == "" ] && DUMMY_IP="`$IP addr show $DUMMY_IFACE | grep inet | grep -v inet6 | awk '{print \$2}' | cut -d \"/\" -f1`" $IPTABLES -t mangle -A POSTROUTING -o $DEV -s ! $DUMMY_IP -j IMQ --todev $I else $IPTABLES -t mangle -A POSTROUTING -o $DEV -j IMQ --todev $I fi $IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I DEV="" else $IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I fi elif [ "$QOS_DEVICE" == "ifb" ]; then # IFB neumí poloviční duplex [ "$DUPLEX" == "HD" ] && echo "IFB does not support HD (half duplex), using FD (full duplex)!" # Kontrola na název rozhraní ath, které indikuje atheros kartu, ta má problémy s IFB if [ "${DEV:0:3}" == "ath" ]; then # Test, jestli dojde ke kernel panicu na atheros kartách: #modprobe ifb #ip link set ifb0 up #tc qdisc add dev ath0 ingress #tc filter add dev ath0 parent ffff: protocol ip prio 10 u32 match u32 0 0 flowid 1:0 action mirred egress redirect dev ifb0 echo "IFB on atheros (madwifi) cards could cause kernel panic, try to use IMQ, or" echo "disable QoS on atheros cards!" DEV_2="" else $TC qdisc add dev $DEV ingress $TC filter add dev $DEV parent ffff: protocol ip prio 10 u32 match u32 0 0 flowid 1:0 action mirred egress redirect dev $DEV_2 fi fi else echo " $DEV rate ${RATE} kbit/s without ifb or imq" DEV_2="" fi # Na základním i pomocném rozhraní nasadíme QoS for DEV in $DEV $DEV_2; do # QoS pro esfq, nebo sfq if [ "$QOS_TYPE" == "esfq" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then # Pro ESFQ musíme určit na základě typu rozhraní hash if [ "$DIRECTION" == "WAN" ]; then if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then SFQ="esfq perturb 10 hash src" else SFQ="esfq perturb 10 hash dst" fi elif [ "$DIRECTION" == "NAT" ]; then if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then SFQ="esfq perturb 10 hash ctnatchg" else SFQ="esfq perturb 10 hash dst" fi else if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then SFQ="esfq perturb 10 hash dst" else SFQ="esfq perturb 10 hash src" fi fi else SFQ="sfq perturb 10" fi # Základní nasazení tříd je pro všechny typy QoSu stejné # Vytvoříme root qdisc $TC qdisc add dev $DEV root handle 1:0 prio bands 3 priomap 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 # V prvních dvou třídách nebudeme limitovat, pouze budeme rozdělovat pásmo pomocí sfq $TC qdisc add dev $DEV parent 1:1 handle 11:0 $SFQ $TC qdisc add dev $DEV parent 1:2 handle 12:0 $SFQ # Omarkované pakety roztřídíme do jednotlivých tříd, první třída bude mít prioritu 1, # tj. cokoliv co do ní přejde už nezávisle na dalších pravidlech zpracuje, ostatní # nemají prioritu udanou, tím se řadí na konec až za všechna ostatní pravidla. $TC filter add dev $DEV parent 1:0 protocol ip prio 1 handle 1 fw flowid 1:1 $TC filter add dev $DEV parent 1:0 protocol ip handle 2 fw flowid 1:2 # 3. třída je určena pro datového omezení if [ "$QOS_LIMIT_TYPE" == "htb" ]; then $TC qdisc add dev $DEV parent 1:3 handle 13:0 htb r2q $R2Q default 111 # Zakladni htb tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++, $TC class add dev $DEV parent 13:0 classid 13:1 htb rate ${RATE}kbit else $TC qdisc add dev $DEV parent 1:3 handle 13:0 hfsc default 111 # Zakladni hfsc tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++, $TC class add dev $DEV parent 13:0 classid 13:1 hfsc ls m2 ${RATE}kbit ul m2 ${RATE}kbit fi # Pokročilé nasazení tříd podle typu if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then if [ "$QOS_LIMIT_TYPE" == "htb" ]; then $TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[5*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit $TC class add dev $DEV parent 13:1 classid 13:112 htb rate $[3*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit $TC class add dev $DEV parent 13:1 classid 13:113 htb rate $[2*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit else $TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[5*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit $TC class add dev $DEV parent 13:1 classid 13:112 hfsc ls m2 $[3*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit $TC class add dev $DEV parent 13:1 classid 13:113 hfsc ls m2 $[2*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit fi # V kazde tride jeste pouziji sfq $TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ $TC qdisc add dev $DEV parent 13:112 handle 112:0 $SFQ $TC qdisc add dev $DEV parent 13:113 handle 113:0 $SFQ # Další třídy zpracovávající pravidla z iptables $TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111 $TC filter add dev $DEV parent 13:0 protocol ip handle 4 fw flowid 13:112 $TC filter add dev $DEV parent 13:0 protocol ip handle 5 fw flowid 13:113 else # Nastavime maximalni ryhlost pro vse co jde do tridy 2 (3. skupina) if [ "$QOS_LIMIT_TYPE" == "htb" ]; then $TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[($RATE - $RATE_MIN)]kbit ceil ${RATE}kbit else # Zakladni hfsc tride dame plnou rychlost $TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[($RATE - $RATE_MIN)]kbit ul m2 ${RATE}kbit fi # V kazde tride jeste pouziji sfq $TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ # I pokud nepoužíváme layer7, můžeme využít markování pomocí iptables $TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111 fi # speciální třídy IFS=$'\t\n' for CLASS in $CLASSES; do IFS=$' \t\n' CLASS=( $CLASS ) # garantovaná rychlost nemůže být větší než maximální rychlost na rozhraní [ "${CLASS[1]}" -ge "$RATE" ] && continue # pokud není zadaná maximální rychlost, tak je maximum celkový rychlost rozhraní [ "${CLASS[2]}" == "" ] && CLASS[2]=$RATE # pokud je maximální rychlost menší než minimální, tak je maximum rychlost rozhraní [ "${CLASS[2]}" -lt "${CLASS[1]}" ] && CLASS[2]=$RATE # pokud je maximální rychlost větší, než maximální rychlost rozhraní, tak je maximum rychlost rozhraní [ "${CLASS[2]}" -gt "$RATE" ] && CLASS[2]=$RATE if [ "$QOS_LIMIT_TYPE" == "htb" ]; then $TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) htb rate ${CLASS[1]}kbit ceil ${CLASS[2]}kbit else $TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) hfsc ls m2 ${CLASS[1]}kbit ul m2 ${CLASS[2]}kbit fi # Nasadíme sfq na dané třídy $TC qdisc add dev $DEV parent 13:$((113 + ${CLASS[0]})) handle $((113 + ${CLASS[0]})):0 $SFQ # Garantované třídy nepotřebují speciální třídu, protože se markují jen pomocí tc rovnou do dané třídy #$TC filter add dev $DEV parent 1:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]})) #$TC filter add dev $DEV parent 13:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]})) done IFS=$' \t\n' done ((I++)) done # Protože markování na každém zařízení zvlášť by bylo velmi mnoho pravidel pro iptables, # tak použijeme markování na všech zařízeních, i tak zavedení pravidel trvá cca 6 vteřin. if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then # Markování musíme provádět již v preroutingu, jinak nejsme schopni označit všechny pakety. # ICMP - vzdy $IPTABLES -t mangle -I PREROUTING -p icmp -j MARK --set-mark 1 # OSPF - vzdy $IPTABLES -t mangle -I PREROUTING -p ospf -j MARK --set-mark 1 # UDP - vzdy $IPTABLES -t mangle -I PREROUTING -p UDP -j MARK --set-mark 2 # HTML - jiny nekorektni zpusob markovani http, ale mnohem mene narocny #$IPTABLES -t mangle -I PREROUTING -p TCP --dport 80 -j MARK --set-mark 3 # Označení paketů pomocí layer7 filtru, detekce některých protokolů zvyšuje odezvy # 8.3.2009 - vyřazeny protokoly, které po cca 30 dnech měly nulové čítače qos_mark_layer7 1 "bgp dhcp dns irc jabber snmp whois" qos_mark_layer7 2 "quake-halflife worldofwarcraft" # Do třídy 3 jdou všechna nezařazená data, takže jí není třeba označovat qos_mark_layer7 3 "" qos_mark_layer7 4 "ftp cvs biff h323 imap live365 pop3 rtsp shoutcast smtp ssl tftp" qos_mark_layer7 5 "bittorrent directconnect edonkey http-itunes soulseek" fi echo "done." # Označíme jednotlivé počítače v třídách qos_guaranted_classes } qos_stop() { echo -n "Stopping QoS..." local I="" local DEV="" # Smažeme všechna pravidla v iptables for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do $IPTABLES -t mangle -D POSTROUTING $I done for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do $IPTABLES -t mangle -D PREROUTING $I done for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do $IPTABLES -t mangle -D POSTROUTING $I done for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do $IPTABLES -t mangle -D PREROUTING $I done # Smažeme všechny root qdisky while true; do DEV="`$TC qdisc | grep -v 0: | awk '{print \$5}' | sort -u | sed -n 1p`" [ "$DEV" == "" ] && break $TC qdisc del dev "$DEV" root &>/dev/null $TC qdisc del dev "$DEV" ingress &>/dev/null done # Deaktivujeme všechna ifb zařízení while true; do DEV="`$IP link show | grep ifb | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`" [ "$DEV" == "" ] && break DEV="${DEV//:/}" $IP link set "$DEV" down done # Odstraníme ifb modul z paměti #rmmod -f ifb &>/dev/null # Deaktivujeme všechna imq zařízení while true; do DEV="`$IP link show | grep imq | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`" [ "$DEV" == "" ] && break DEV="${DEV//:/}" $IP link set "$DEV" down done # Odstraníme imq modul z paměti #rmmod -f imq &>/dev/null echo "done." } qos_stats() { $TC -s qdisc } # speciální garantované třídy qos_guaranted_classes() { [ "${#CLASS_1[*]}" -lt "1" ] && return 0 echo "Starting QoS guaranted classes..." # lokální proměnné local I="" local J="" local CLASS_DEV="" local CLASS_MIN="" local CLASS_MAX="" local CLASS_USERS="" local CLASSES="" local RATE_MIN="0" local USER="" J="1" while true; do CLASS_DEV=CLASS_${J}_DEV CLASS_DEV=${!CLASS_DEV} [ "$CLASS_DEV" == "" ] && break CLASS_MIN=CLASS_${J}_MIN CLASS_MIN=${!CLASS_MIN} CLASS_MAX=CLASS_${J}_MAX CLASS_MAX=${!CLASS_MAX} # klasické přiřazení nelze použít na pole CLASS_USERS="CLASS_${J}[@]" CLASS_USERS=( "${!CLASS_USERS}" ) # Přeskočíme prázdné třídy if [ "${#CLASS_USERS[*]}" -lt "1" ]; then ((J++)) continue fi # Pokud není zadána maximální rychlost třídy [ "$CLASS_MAX" == "" ] && CLASS_MAX="interface maximum" echo "QoS class $J (dev: $CLASS_DEV, min: $CLASS_MIN kbit/s, max: $CLASS_MAX kbit/s):" IFS=$'\t\n' for USER in ${CLASS_USERS[@]}; do IFS=$' \t\n' USER=( $USER ) I="2" while [ "${USER[$I]}" != "" ]; do if [ "${USER[$I]:2:1}" == ":" ]; then echo -e " user ${USER[1]}\twith mac ${USER[$I]}\ton ${USER[0]}\tlimited!" else echo -e " user ${USER[1]}\twith ip ${USER[$I]}\t\ton ${USER[0]}\tlimited!" fi qos_guaranted_class_add_user "$J" "${USER[$I]}" "${USER[0]}" ((I++)) done done IFS=$' \t\n' ((J++)) done echo "done." } # formát: "třída" "ip, nebo mac" "rozhraní - nepovinné" qos_guaranted_class_add_user() { ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0 # rozhraní na kterých je aktivní qos, vždy používáme alespoň sfq local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u` # další lokální proměnné local I="" local DEV="" local TC_DEV="" local TC_DEVS_POM="" local IMQ_DEV="" local IFB_DEV="" local DATA="" local LINE="" local IP="$2" local MAC="`echo $2 | tr [:upper:] [:lower:]`" local TC_NUM="" local CLASS="" # pokud ip, nebo mac už je zadaná, tak jí smažeme na všech rozhraních qos_guaranted_class_del_user "$2" # zjistíme jestli jde o MAC, nebo IP adresu IFS=$'./\t\n' IP=( $IP ) IFS=$':\t\n' MAC=( $MAC ) IFS=$' \t\n' # Je-li zadané rozhraní, tak musíme najít přidružené IMQ, nebo IFB if [ "$3" != "" ] && [ "$3" != "all" ]; then # IMQ z PREROUTINGu, musíme použít awk, protože iptables posílá * a ta se nedá převést do pole! DATA=`$IPTABLES -t mangle -L PREROUTING -n -v | grep todev | awk '{print $6" "$12}'` IFS=$'\t\n' for LINE in $DATA; do IFS=$' \t\n' LINE=( ${LINE} ) if [ "${LINE[0]}" == "$3" ] && [ "${LINE[1]}" != "" ]; then IMQ_DEV="imq${LINE[1]}" break fi done IFS=$' \t\n' # ifb získáme z tc IFB_DEV="`$TC filter list dev $3 parent ffff: | grep ifb | awk '{print \$9}'`" IFB_DEV="${IFB_DEV//)/}" for I in $TC_DEVS; do [ "$3" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $I" [ "$IFB_DEV" != "" ] && [ "$IFB_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IFB_DEV" [ "$IMQ_DEV" != "" ] && [ "$IMQ_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IMQ_DEV" done [ "$TC_DEVS_POM" == "" ] && return 0 # Musíme odstranit první prázdný znak TC_DEVS="${TC_DEVS_POM:1}" fi # samotné zařazení do třídy for DEV in $TC_DEVS; do # smažeme nejprve třídy 1:0 a pak 13:0 for CLASS in "1:0" "13:0"; do # musíme najít další číslo kam budeme přidávat záznam TC_NUM=$((`$TC filter list dev $DEV parent $CLASS | awk '{print $5}' | grep -v "4915" | sort -ug | tail -n 1` + 1)) if [ "${IP[3]}" != "" ]; then $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip src $2 flowid 13:$((113 + $1)) $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip dst $2 flowid 13:$((113 + $1)) elif [ "${MAC[5]}" != "" ]; then $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match u16 0x0800 0xffff at -2 match u32 0x${MAC[2]}${MAC[3]}${MAC[4]}${MAC[5]} 0xffffffff at -12 match u16 0x${MAC[0]}${MAC[1]} 0xffff at -14 flowid 13:$((113 + $1)) $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match u16 0x0800 0xffff at -2 match u16 0x${MAC[4]}${MAC[5]} 0xffff at -4 match u32 0x${MAC[0]}${MAC[1]}${MAC[2]}${MAC[3]} 0xffffffff at -8 flowid 13:$((113 + $1)) else # nejedná se ani o ip ani o mac adresu return 0 fi done done return 0 } # Pro mazání není třeba znát třídu ze které mažeme, protože by jedna ip, nebo mac # neměla být ve více třídách. # # formát: "ip, nebo mac" qos_guaranted_class_del_user() { [ "$1" == "" ] && return 0 # Mažeme na všech rozhraních, kde je QoS local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u` # lokální proměnné local I="" local DEV="" local DATA="" local LINE="" local LINE_1="" local LINE_2="" local IP="$1" local MAC="`echo $1 | tr [:upper:] [:lower:]`" local IP_HEX="" local MAC_1="" local MAC_2="" local MAC_3="" local CLASS="" local PRIO="" local PRIO_PREV="" # zjistíme jestli jde o MAC, nebo IP adresu, pro mac musíme převést velká písmena na malá IFS=$'./\t\n' IP=( $IP ) IFS=$':\t\n' MAC=( $MAC ) IFS=$' \t\n' if [ "${IP[3]}" != "" ]; then # převedeme ip do formátu, který používá tc IP_HEX=`printf '%02x%02x%02x%02x\n' ${IP[0]} ${IP[1]} ${IP[2]} ${IP[3]}` elif [ "${MAC[5]}" != "" ]; then MAC_1="00000800" MAC_2="${MAC[2]}${MAC[3]}${MAC[4]}${MAC[5]}" MAC_3="0000${MAC[0]}${MAC[1]}" else # Nejedná se ani o ip ani o mac adresu return 0 fi # zkontrolujeme všechna rozhraní for DEV in $TC_DEVS; do # smažeme nejprve třídy 1:0 a pak 13:0 for CLASS in "1:0" "13:0"; do # načteme data z tc, kde jsou uloženy všechny zadané mac i ip adresy IFS=$'\t\n' DATA=( `$TC filter list dev $DEV parent $CLASS` ) IFS=$' \t\n' I="0" PRIO="" PRIO_PREV="" IFS=$'\t\n' for LINE in ${DATA[@]}; do # pro matchování nás nezajímá maska, proto masku oddělíme, platí jen v případě ip IFS=$' /\t\n' LINE=( $LINE ) IFS=$' \t\n' # inkrementovat musíme ještě před continue ((I++)) if [ "${LINE[3]}" == "pref" ]; then PRIO=${LINE[4]} continue fi # dále nás zajímá jen match [ "${LINE[0]}" != "match" ] && continue # pokud neznáme prioritu, tak pokračujeme [ "$PRIO" == "" ] && continue # pokud jsme již jednou tuto prioritu mazali, tak pokračujeme [ "$PRIO" == "$PRIO_PREV" ] && continue # rozdělení podle ip, nebo mac if [ "${IP[3]}" != "" ]; then # pokud ip neodpovídá, tak pokračujeme [ "${LINE[1]}" != "$IP_HEX" ] && continue elif [ "${MAC[5]}" != "" ]; then # jednotný match pro všechny mac adresy [ "${LINE[1]}/${LINE[2]}" != "$MAC_1/0000ffff" ] && continue # následující řádek musí obsahovat druhou část mac adresy, už nepoužíváme jako delimiter / LINE_1=( ${DATA[$I]} ) [ "${LINE_1[1]}" != "$MAC_2/ffffffff" ] && continue # další řádek musí obsahovat poslední část mac adresy LINE_2=( ${DATA[$(($I + 1))]} ) [ "${LINE_2[1]}" != "$MAC_3/0000ffff" ] && continue fi # Daná ip už je matchovaná, proto pravidla smažeme $TC filter del dev $DEV parent $CLASS protocol ip prio $PRIO 2>/dev/null PRIO_PREV="$PRIO" done IFS=$' \t\n' done done return 0 } qos_mark_layer7() { ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0 # Lokální proměnné local I="" local O_DEV="" local I_DEV="" [ "$3" != "" ] && O_DEV="-o $3" [ "$4" != "" ] && I_DEV="-i $4" for I in $2; do $IPTABLES -t mangle -I PREROUTING $O_DEV $I_DEV -m layer7 --l7proto $I -j MARK --set-mark $1 done return 0 } WebSVN - freenet-router - Blame - Rev 2 - /trunk/freenet-router/etc/firewall/qos
  jablonka.czprosek.czf

freenet-router

Subversion Repositories:
[/] [trunk/] [freenet-router/] [etc/] [firewall/] [qos] - Blame information for rev 2

 

Line No. Rev Author Line

Powered by WebSVN 2.2.1