#!/bin/bash
#                 Limiteur de bande passante inspiré du travail de
#                 Dan Singletary lui meme inspiré de
#                 Inspiré de WonderShaper (www.lartc.org)
#                 François Boisson (3 Avril 2003)
# 
# Remarque - ce script suppose que le noyau a été patché avec les files
#             HTB et IMQ disponibles ici (les noyaux à venir ne demanderont
#             pas forcément l'application d'un correctif):
#       http://luxik.cdi.cz/~devik/qos/htb/
#       http://luxik.cdi.cz/~patrick/imq/
#
# 
#  DEV ---> périphérique de sortie
#
#  RATEUP ---> Bande passante maximale en upload
#
#
DEV=eth1
# variante speciale serveur de Counter Strike
# une bande passante est a l'usage exclusif du serveur
#
# prévoir un nombre divisible par N et valant en gros 80% de la bande maximum
# donnée lors de la connexion ADSL en upload (chiffre ici pour 160Kbits/s)
# les rapports RATEUP?/PART doit être entier
# Serveur
P0=40
#le reste
P1=10
P2=5
P3=5
P4=2
P5=1
PART=$[$P1+$P2+$P3+$P4+$P5]
UNITE=8
RATEUP1=$[$P0*$UNITE]
echo Taux1: $RATEUP1
RATEUP2=$[$PART*$UNITE]
echo Taux2: $RATEUP2
# 0: Ping
# 1: DNS, petits paquets de longueurs < 64, BattleNet, CS, UDP
# 2: telnet, ssh, X, VNC
#    Edonkey reception (port perso 3662) et serveur
# 3: Traffic sur les ports bas,messagerie AOL et MSN
# 4: FTP-DATA
# 5: WWW, Edonkey upload, reste
#
# proportions des bandes passantes sur les 7 files de priorités
# elles valent Pi/PART donc Somme(Pi,i=0..6)=PART
#
# Fin des options de configuration
#
affecte()
# affecte nom sens port protocole categorie
# sens = s ou d, protocole = udp ou tcp categorie = 0->?
#
{
        echo [$1 : $5]
        # shell s	curis	
        iptables -t mangle -A MONLIMITEUR-OUT -p $4 --$2port $3 -j MARK --set-mark 2$5
}
#

if [ "$1" = "status" ]
then
        echo "[qdisc]"
        tc -s qdisc show dev $DEV
        echo "[class]"
        tc -s class show dev $DEV
        echo "[filter]"
        tc -s filter show dev $DEV
        echo "[iptables]"
        iptables -t mangle -L MONLIMITEUR-OUT -v -x 2> /dev/null
        exit
fi

# Remise à zéro
tc qdisc del dev $DEV root    2> /dev/null > /dev/null
iptables -t mangle -D POSTROUTING -o $DEV -j MONLIMITEUR-OUT 2> /dev/null > /dev/null
iptables -t mangle -F MONLIMITEUR-OUT 2> /dev/null > /dev/null
iptables -t mangle -X MONLIMITEUR-OUT 2> /dev/null > /dev/null

if [ "$1" = "stop" ]
then
        echo "Limitation de débit désactivée sur $DEV."
        exit
fi

###########################################################
#
# Limitation de trafic sortant (limite supérieure à RATEUP)

# positionnement de la taille de la file d'émission pour obtenir
# une latence d'environ 2 secondes pour les paquets de la file
# de faible priorité.
ip link set dev $DEV qlen 30
#
# modification de MTU du périphérique sortant.
# - Diminuer la MTU abaisse la latence mais dégrade le débit en raison de
#   la surcharge IP et TCP.
# ip link set dev $DEV mtu 1000
# que dalle, ne pas trop diminuer les performances, personnellement
# je ne le fais pas

# ajout de la stratégie HTB
# les noms des queues sont de 20 à 26, je les conserve
#
tc qdisc add dev $DEV root handle 1: htb default 25

# 2 classes meres differentes
tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP1}kbit
tc class add dev $DEV parent 1: classid 1:2 htb rate ${RATEUP2}kbit

# ajout des classes filles:
# - chaque classe dispose AU MOINS de son quota de bande passante. Aucune
#   classe n'est donc étouffée par les autres. Chaque classe peut également
#   consommer toute la bande passante si aucune autre classe ne l'emploie.
# poids différents pour les classes
# C'est l'intéret des classes filles si j'ai bien compris, les classes mères
# ne partage pas leur part de bande passante
#
# Le serveur et les pings
tc class add dev $DEV parent 1:1 classid 1:20 htb \
	rate $[($RATEUP1*$P0)/$PART]kbit \
	ceil ${RATEUP1}kbit prio 0
# Les autres classes
tc class add dev $DEV parent 1:2 classid 1:21 htb \
	rate $[($RATEUP2*$P1)/$PART]kbit \
	ceil ${RATEUP2}kbit prio 0
# telnet, ssh,X
tc class add dev $DEV parent 1:2 classid 1:22 htb \
	rate $[($RATEUP2*$P2)/$PART]kbit \
	ceil ${RATEUP2}kbit prio 1
# ports bas, messagerie AOL, MSN
tc class add dev $DEV parent 1:2 classid 1:23 htb \
	rate $[($RATEUP2*$P3)/$PART]kbit \
	ceil ${RATEUP2}kbit prio 2
# WWW
tc class add dev $DEV parent 1:2 classid 1:24 htb \
	rate $[($RATEUP2*$P4)/$PART]kbit \
	ceil ${RATEUP2}kbit prio 3
# Edonkey (à l'origine)
tc class add dev $DEV parent 1:2 classid 1:25 htb \
	rate $[($RATEUP2*$P5)/$PART]kbit \
	ceil ${RATEUP2}kbit prio 4

# ajout de la stratégie aux classes filles
# - SFQ offre un traitement sensiblement équitable de chaque classe.
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev $DEV parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev $DEV parent 1:25 handle 25: sfq perturb 10

# répartition du trafic en classe via fwmark
# - le trafic est réparti en classes de priorité suivant l'indicateur
#   fwmark des paquets (ceux-ci sont positionnés avec iptables un peu plus
#   loin). La classe de priorité par défaut a été mise à 1:26 de telle sorte
#   que les paquets qui ne sont pas marqués se retrouvent dans la classe de
#   priorité la plus faible.
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
#
# ajout de MONLIMITEUR-OUT à la table de modification des paquets d'iptables
# - ceci déclare la table employée pour filtrer et classer les paquets
iptables -t mangle -N MONLIMITEUR-OUT
iptables -t mangle -I POSTROUTING -o $DEV -j MONLIMITEUR-OUT

# ajout de fwmark pour classer les différents types de trafic
# - fwmark est positionné de 20 à 25 suivant la classe. 20 correspond à la
#   priorité la plus forte.
# 
# Ici mettre les règles personnelles ici, cela dépend de la configuration
# personnelle

# Ici mettre les règles personnelles ici, cela dépend de la configuration
# personnelle
# tout ce qui vient de FON, priorite 6

iptables -t mangle -A MONLIMITEUR-OUT -s 192.168.1.240 -j MARK \
	--set-mark 26


# ICMP (ping) - forte priorité (impressionnez vos amis)
#echo "[ping : 0]"

iptables -t mangle -A MONLIMITEUR-OUT -p icmp -j MARK \
	--set-mark 20
#
# free player
iptables -t mangle -A MONLIMITEUR-OUT -p tcp  -d 212.27.38.253 -j MARK --set-mark 22
# CS
affecte "CounterStrike" d 27000:27045 udp 0
affecte "CounterStrike" s 27000:27030 udp 0
# quake3
affecte "Quake3" d 27960 udp 1
affecte "Quake3" s 27960 udp 1
# a priori pas de TCP
# DNS (petits paquets)
affecte "DNS" d 53 udp 1
# BattleNet
affecte "BattleNet" d 6112:6119 tcp 1
affecte "BattleNet" d 6112:6119 udp 1
affecte "BattleNet" s 6112:6119 tcp 1
affecte "BattleNet" s 6112:6119 udp 1
affecte "BattleNet" s 4000 tcp 1
affecte "BattleNet" d 4000 tcp 1
affecte "BattleNet" d 4000 udp 1
affecte "BattleNet" s 4000 udp 1
#
#World of Warcraft
#
affecte "WoW" d 3724 tcp 1

	# shell sécurisé
affecte "SSH" d ssh tcp 2
affecte "SSH" s ssh tcp 2
	# telnet 
affecte "telnet" d telnet tcp 2
affecte "telnet" s telnet tcp 2
#
# X
affecte "X11" d 6000 tcp 2
affecte "X11" d 6000 udp 2
# VNC
affecte "VNC" s 5901:5905 tcp 2
affecte "VNC" s 5901:5905 udp 2

	# Trafic sur les ports bas
affecte "port bas" s 0:1024 tcp 3
affecte "port bas" d 0:1024 tcp 3

	# Port ftp-data, faible priorité
affecte "FTP data" s 20 tcp 4
affecte "FTP data" d 20 tcp 4
affecte "FTP" s 21 tcp 3
affecte "FTP" d 21 tcp 3
	# Serveur WWW local
affecte "Apache https" s 443 tcp 3

	# Messagerie Immédiate AOL
affecte AOL d 5190 tcp 3
	# Messagerie Immédiate MSN

affecte "MSN" d 1863 tcp 3
affecte "MSN" d 6891 udp 4
affecte "MSN" d 6891 tcp 4
affecte "MSN" s 1863 tcp 3
affecte "MSN" s 6891 udp 4
affecte "MSN" s 6891 tcp 4

	# Serveur WWW local
affecte "Apache" s http tcp 5

# Xmule
affecte "Xmule" s 3662 tcp 6
affecte "Xmule" s 3672 udp 6
affecte "Xmule" d 5259 udp 2
#
#
# les paquets udp sont des paquets de jeu
iptables -t mangle -A MONLIMITEUR-OUT -p udp -j MARK --set-mark 21
# Petits paquets (des ACK probablement)
#echo [petits paquets: 1]
iptables -t mangle -A MONLIMITEUR-OUT -p tcp -m length --length :64 -j MARK \
	--set-mark 21
iptables -t mangle -A MONLIMITEUR-OUT -p tcp -m length --length 65:128 \
	-j MARK --set-mark 22


# Répétition - on marque les paquets restants à 26 (faible priorité)
iptables -t mangle -A MONLIMITEUR-OUT -m mark --mark 0 -j MARK \
	--set-mark 26

#
# Fin de la limitation sortante
#
echo "Limitation de trafic sortant activé sur $DEV.  Débit: ${RATEUP}kbit/sec."


#
# Fin de la limitation sortante
#
echo "Limitation de trafic sortant activé sur $DEV.  Débit: $[$RATEUP1+$RATEUP2]kbit/sec."
