Auto-hébergement et QOS 1/7 : comment télécharger comme un goret

(Et ainsi devenir la bête noire de votre FAI, mais c’est vous qui voyez)

Marre des débits qui s’effondrent au moindre upload ?

Alors toi aussi, rejoins le club très fermé des « ACKers1 » fous : tu pourras télécharger à bloc la dernière version de Debian (bien) tout en transférant tes photos de vacances sur Facebook (pas bien).

Si vous êtes auto-hébergé, prenez garde : le script qui suit permet simplement de ne pas être ralenti pendant vos pérégrinations sur le net. (Par contre vos visiteurs, eux, ils vont s’en prendre plein les dents)

Pour ceux qui souhaiteraient plutôt s’orienter vers du traffic shaping équitable afin d’assurer une qualité de service optimale pour leur blog/forum/site, pas de panique, cette problématique sera abordée dans la quatrième partie (pas encore écrite, loin de là d’ailleurs) : « Auto-hébergement et QOS 4/7 : exemple concret de traffic shaping »

Bon, alors, ça vient ce script miracle ?

Déjà, y’a rien de miraculeux et ensuite, suffit juste d’avoir un Linux sous la main. (Pour les geeks à poils durs qui préfèrent BSD, regardez du côté de Packet Filter pour arriver à vos fins)

Ensuite, pour que cela puisse fonctionner correctement, il faut que le traffic shaping soit appliqué sur l’interface réseau qui gère l’envoi des flux vers Internet. (Inutile d’avoir deux cartes réseau pour séparer le trafic)

En résumé, vous devez configurer vos équipements afin que Linux devienne l’unique passerelle (gateway) de votre réseau local : c’est lui qui va se charger de NATer (j’en vois déjà certains bondir mais tant pis, j’assume) l’ensemble du trafic provenant de vos PC/Macs/Smartphones/etc avant d’envoyer la purée vers votre machin-box.

Si vous n’avez strictement rien compris au paragraphe précédant, je vous invite à lire tranquillement à la seconde partie (quand elle sera terminée) : « Auto-hébergement et QOS 2/7 : centraliser et NATer les flux sortants« .

Les possesseurs d’un routeur WRT54GL vont être ravis car il semblerait bien que l’on puisse gérer directement la QOS avec un firmware adapté : SpeedMod with tc atm QoS patch for ADSL. (Je vais me pencher sur le sujet dès que possible)

Derniers réglages avant la mise à feu

« LAN_ETH » est le nom de l’interface réseau qui gère l’envoi des données vers votre machin-box et donc vers Internet.

« LAN_IP » est l’adresse IP du serveur Linux sur votre réseau local.

« LAN_NET » détermine votre réseau local afin de l’exclure : on veut juste optimiser le trafic vers Internet, pas celui du réseau interne.

« WAN_IP » est votre adresse IP publique mais vous pouvez utiliser directement un FQDN (voir le script).

« WAN_OVERHEAD » détermine le nombre d’octets perdus (ou gagnés) en fonction du protocole et de l’encapsulation utilisés par votre connexion à Internet :

  • IPoA VC/Mux : -6
  • IPoA LLC/SNAP : 2
  • Bridged VC/Mux : 10
  • Bridged LLC/SNAP : 18
  • PPPoA VC/Mux : -4
  • PPPoA LLC/SNAP : 0
  • PPPoE VC/Mux : 18
  • PPPoE LLC/SNAP : 26

Vous trouverez ces informations en vous connectant sur votre box ou votre modem ADSL.

Le calcul de l’overhead et du MTU sera traité en détail dans la troisième partie (en cours de gestation mais c’est pas gagné) : « Auto-hébergement et QOS 3/7 : déterminer l’overhead de sa ligne ADSL »

Pour plus de détails sur ces valeurs, je vous invite vivement à consulter la page concernant le patch ATM de Russell Stuart.

« WAN_MTU » détermine la taille maximale de chaque paquet envoyé. Vous trouverez ci-dessous les valeurs optimales (si bien sûr je ne me suis pas lamentablement vautré dans mes calculs) :

  • IPoA VC/Mux : 1480
  • IPoA LLC/SNAP : 1472
  • Bridged VC/Mux : 1464
  • Bridged LLC/SNAP : 1456
  • PPPoA VC/Mux : 1478
  • PPPoA LLC/SNAP : 1474
  • PPPoE VC/Mux : 1456
  • PPPoE LLC/SNAP : 1448

« WAN_MPU » indique la taille minimale d’un paquet Ethernet (64 octets), on n’y touche pas.

« WAN_RATE » est le débit en kilobit par seconde (kbit/s) de votre upload.

Pour trouver la bonne valeur, assurez-vous qu’aucune machine ne se connecte à Internet pendant le test, uploadez un bon gros fichier en FTP de manière à envoyer des paquets dont la taille sera celle du MTU et commencez avec une valeur de WAN_RATE inférieure au débit indiqué par la synchronisation de votre machin-box.

Lancez le script puis pingez les DNS de Google :

ping -c 20 -i 0.5 8.8.8.8

Ensuite, augmentez progressivement la valeur de WAN_RATE tant que le temps de réponse moyen du ping reste stable. Quand vous aurez atteint la limite, vous devriez constater une augmentation du ping d’au moins 20 ms (souvent bien plus) : revenez alors en arrière pour retrouver le temps de réponse initial et, par mesure de sécurité, soustrayez 8 ou 16 kbit à la valeur finale.

Vous pouvez également utiliser iftop : mesurez d’abord votre débit ascendant sans le script puis ajustez WAN_RATE pour que l’upload soit légèrement inférieur à la capacité réelle de votre ligne ADSL.

Voilà, c’est prêt !

Et un download de fou pour la 4, un !

Testé et approuvé sur une Debian (Squeeze) avec un noyau 2.6.32, aucune erreur ne doit apparaître lors de l’exécution du script.

Étant connecté en PPPOE/LLC, l’overhead est de 26 octets, le MTU optimal est de 1448 octets et, après pas mal de tests, il s’est avéré que 1008 kbit/s était la vitesse d’upload maximale avant détérioration du ping.

(Cliquez sur la première icône en haut à droite du script pour l’ouvrir dans une fenêtre séparée)

#!/bin/bash -eu

# --- Args

LAN_ETH="eth0"
LAN_IP="192.168.1.100"
LAN_NET="192.168.1.0/24"

WAN_IP="mon-server.dyndns-at-home.com"
WAN_OVERHEAD="26"
WAN_MTU="1448"
WAN_MPU="64"

WAN_RATE="1008"

# --- Reset

echo 1 > /proc/sys/net/ipv4/conf/all/forwarding

iptables -t mangle -F
iptables -t nat -F

if [ -z "`tc qdisc show dev $LAN_ETH | grep pfifo_fast`" ]; then
tc qdisc del dev $LAN_ETH root
fi

# --- NAT --- #

iptables -t nat -A POSTROUTING -o $LAN_ETH -s $LAN_NET ! -d $LAN_NET -j SNAT --to-source $LAN_IP

# --- MSS --- #

iptables -t mangle -A POSTROUTING -o $LAN_ETH   -s $LAN_NET ! -d $LAN_NET -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss $(($WAN_MTU - 39)): -j TCPMSS --set-mss $(($WAN_MTU - 40))
iptables -t mangle -A POSTROUTING -o $LAN_ETH ! -s $LAN_NET   -d $LAN_NET -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss $(($WAN_MTU - 39)): -j TCPMSS --set-mss $(($WAN_MTU - 40))

# --- Mark --- #

# ALL
iptables -t mangle -A POSTROUTING -o $LAN_ETH ! -d $LAN_NET -j MARK --set-mark 3

# ACK
iptables -t mangle -A POSTROUTING -o $LAN_ETH ! -d $LAN_NET -p tcp --tcp-flags ALL ACK -m length --length 40:64 -j MARK --set-mark 2

# ICMP & DNS
iptables -t mangle -A POSTROUTING -o $LAN_ETH ! -d $LAN_NET -p icmp -j MARK --set-mark 1
iptables -t mangle -A POSTROUTING -o $LAN_ETH ! -d $LAN_NET -p udp --dport 53 -j MARK --set-mark 1

# LAN & WAN_IP (Exclude)
iptables -t mangle -A POSTROUTING -o $LAN_ETH   -d $LAN_NET -j MARK --set-mark 99
iptables -t mangle -A POSTROUTING -o $LAN_ETH   -d $WAN_IP  -j MARK --set-mark 99

# --- Root --- #

tc qdisc add dev $LAN_ETH root stab linklayer atm overhead $WAN_OVERHEAD mtu $WAN_MTU mpu $WAN_MPU handle 1:0 htb

# --- HTB

tc class add dev $LAN_ETH parent  1:0 classid  1:1 htb rate ${WAN_RATE}kbit

# --- Prio

tc qdisc add dev $LAN_ETH parent  1:1 handle  10:0 prio

# --- Qdiscs

tc qdisc add dev $LAN_ETH parent 10:1 handle  11:0 pfifo limit 100        # ICMP & DNS
tc qdisc add dev $LAN_ETH parent 10:2 handle  12:0 pfifo limit 100        # ACK
tc qdisc add dev $LAN_ETH parent 10:3 handle  13:0 sfq   limit 127 perturb 10    # ALL

# --- Filters

tc filter add dev $LAN_ETH parent  1:0 protocol ip prio 1 handle 1 fw flowid  1:1
tc filter add dev $LAN_ETH parent  1:0 protocol ip prio 2 handle 2 fw flowid  1:1
tc filter add dev $LAN_ETH parent  1:0 protocol ip prio 3 handle 3 fw flowid  1:1

tc filter add dev $LAN_ETH parent 10:0 protocol ip prio 1 handle 1 fw flowid 10:1
tc filter add dev $LAN_ETH parent 10:0 protocol ip prio 2 handle 2 fw flowid 10:2
tc filter add dev $LAN_ETH parent 10:0 protocol ip prio 3 handle 3 fw flowid 10:3

# --- End

echo 'The end : "Je vous le dit tout net : Je suis très déprimé." (Marvin)'

Ok, c’est bien joli tout ça mais elle est où l’arnACK2 ?

Le script est volontairement basique et fixe « violemment » (qdisc PRIO) les priorités de la manière suivante :

  1. les paquets ICMP (typiquement le ping) et les requêtes DNS sont traités en priorité absolue
  2. les paquets d’acquittement (ACK) qui permettent d’obtenir un bon débit descendant sont traités ensuite
  3. enfin, tous les autres flux sont gérés avec la priorité la plus faible, ce qui peut conduire à un phénomène de « famine »

En d’autres termes, si vous envoyez un mail de 250 Mo (si, si, c’est possible) tout en téléchargeant la dernière version d’Ubuntu, les paquets ACK liés à votre téléchargement seront traités en priorité tandis que l’envoi de votre mail se fera au gré de la bande passante restante. Ce qui veut dire que si les paquets ICMP, DNS et ACK vous bouffent toute votre capacité d’upload, l’envoi du mail sera quasi impossible vu que le débit restant sera nul.

Les paquets ACK c’est nul, ça fait rien qu’à niquer mon upload

Pour la petite histoire, un paquet ACK ne contient aucune donnée utile (pas de payload) et pèse au départ 40 octets : 20 octets pour l’entête TCP et 20 autres pour l’entête IP. Sauf que, dans les faits et à cause de l’overhead lié à votre connexion ADSL, une fois qu’il se retrouve encapsulé les couches inférieures, il occupe au final deux cellules ATM3.

Vous pensiez envoyer 40 octets (IP), raté, votre modem ADSL crache en réalité 106 octets (ATM), soit un gâchis d’environ 62% pour chaque paquet ACK émis.

Pour vous donner un ordre d’idée, quand je télécharge comme un sauvage et que ma ligne ADSL est synchronisée à 1020 kbit/s (ATM) en émission, ce ne sont pas moins de 729 paquets ACK qui sont envoyés par seconde. Cela représente un débit IP de 233 kbit/s mais, à la sortie du modem, le débit ATM réel est bien de 601 kbit/s.

Donc, sur les 1020 kbit/s (ATM) dont je dispose en émission (au grand maximum car il s’agit de la vitesse de synchro), il ne me reste en fait que 419 kbit/s, soit un débit IP de 51 Ko/s pour gérer tout le reste.

Conclusion : quand vous téléchargez comme un goret des vidéos de chatons sur Mega-share-truc-upload, vous perdez jusqu’à 60% de votre capacité d’émission.

Un auto-hébergé averti en valant deux, nous verrons dans le quatrième partie comment mettre en place du traffic shaping « sympa » afin de ne pas (trop) pénaliser vos visiteurs lorsque vous aurez la bonne idée de télécharger le dernier tube de philippe risoli. (Ou l’intégrale d’Hervé Villard, c’est selon)

Résultats des courses en images

Bon, déjà, je vous vois ricaner au fond de la salle. Alors oui, les screenshots sont issues d’un système d’exploitation fermé et propriétaire (mais, rassurez-vous, il y a pire). Tout simplement parce que la dernière fois où j’ai installé une interface graphique sur un serveur Linux, ça doit bien remonter à 8 ou 10 ans. (WindowMaker pour être précis, un peu spartiate mais très utile)

La ligne violette sur les graphs représente le débit maximum de ma connexion ADSL, la courbe jaune indique le débit descendant et enfin, la courbe rouge correspond au débit ascendant.

(La connexion ADSL utilisée était celle d’Orange lors de l’écriture de ce billet mais comme j’ai changé de FAI entre-temps, je mettrai à jour les screenshots afin que l’on puisse comparer les deux FAI)

Petite précision à tout hasard

Les tests ont été fait avec un noyau Débian 2.6.32-5-amd64 (Squeeze) légèrement modifié :

  • CONFIG_MATOM=y
  • CONFIG_X86_USE_PPRO_CHECKSUM=y
  • CONFIG_PREEMPT=y
  • CONFIG_HZ_1000=y
  • CONFIG_HZ=1000
  • CONFIG_DEBUG_PREEMPT=y

Mais, en faisant les mêmes essais avec le noyau standard, je n’ai vu aucune différence (ou alors je suis miro). Et si je ne dis pas de bêtise, un noyau 1000 hertz n’est utile que pour contrôler les gros débits, ce qui n’est pas le cas ici.

Test (1/5) : download puis upload – sans QOS

Auto-hébergement et QOS - Test (1/5) : download puis upload – sans QOS

  1. début du téléchargement (4 fichiers)
  2. début de l’upload (2 fichiers)
  3. fin de l’upload
  4. fin du téléchargement

On peut clairement constater que le débit descendant prend une grosse claque dès que l’on envoie des fichiers par FTP.

Test (2/5) : download puis upload – avec QOS

Auto-hébergement et QOS - Test (2/5) : download puis upload – avec QOS

  1. début du téléchargement (4 fichiers)
  2. début de l’upload (2 fichiers)
  3. fin de l’upload
  4. fin du téléchargement

Ô joie, bonheur, avec un zeste de traffic shaping notre débit descendant n’est que très peu affecté par l’envoi des fichiers.

Test (3/5) : upload puis download – sans QOS

Auto-hébergement et QOS - Test (3/5) : upload puis download – sans QOS

  1. début de l’upload (2 fichiers)
  2. début du téléchargement (4 fichiers)
  3. fin du téléchargement
  4. fin de l’upload

Scénario inverse, on commence d’abord par uploader des fichiers et ensuite on lance les téléchargements. Impossible d’atteindre le débit descendant maximum.

Test (4/5) : upload puis download – avec QOS

Auto-hébergement et QOS - Test (4/5) : upload puis download – avec QOS

  1. début de l’upload (2 fichiers)
  2. début du téléchargement (4 fichiers)
  3. fin du téléchargement
  4. fin de l’upload

Même cas de figure mais cette fois le débit descendant atteint presque sa valeur maximale.

Test (5/5) : pour le fun

Auto-hébergement et QOS - Test (5/5) : pour le fun

  1. QOS activée
  2. QOS désactivée
  3. QOS activée
  4. QOS désactivée
  5. QOS activée
  6. fin des téléchargements

Ouf, c’est fini.

Et mon ping dans tout ça ?

Les valeurs vont forcément varier en fonction de votre connexion mais les résultats ci-dessous donnent un ordre de grandeur.

ping -c 20 -v -i 0.5 8.8.8.8

Au repos

20 packets transmitted, 20 received, 0% packet loss, time 9517ms
rtt min/avg/max/mdev = 34.646/35.383/36.119/0.426 ms

Upload avec QOS

20 packets transmitted, 20 received, 0% packet loss, time 9514ms
rtt min/avg/max/mdev = 35.873/41.599/47.784/3.893 ms

Upload et download avec QOS

20 packets transmitted, 20 received, 0% packet loss, time 9508ms
rtt min/avg/max/mdev = 35.922/47.706/57.337/5.166 ms

Upload sans QOS

20 packets transmitted, 20 received, 0% packet loss, time 9517ms
rtt min/avg/max/mdev = 63.818/85.772/368.325/64.940 ms

Upload et download sans QOS

20 packets transmitted, 19 received, 5% packet loss, time 9517ms
rtt min/avg/max/mdev = 67.071/109.234/359.556/60.252 ms

Si vous êtes arrivés jusqu’ici c’est que vous aimez forcément la lecture

(Par contre, si vous êtes allergique à la langue de Shakespeare, ça va être un poil tendu)

Ce n’est pas de la mauvaise volonté, c’est juste qu’on ne trouve pas grand chose sur le sujet en français alors si vous avez des liens sympathiques, n’hésitez pas à les poster.

The end

Voilà ! Suite au prochain épisode. 😀

  1. Oui, je sais, elle est nulle mais fallait bien que je la place
  2. Promis, demain j’arrête
  3. Sauf pour IPoA VC/Mux mais il faut que je vérifie

Il y a 4 commentaires de gens bizarres, ce sont sûrement des drogués

Oui Jean-Pierre, je souhaite publier un commentaire assassin sur ce blog minable

(Votre adresse email ne sera jamais publiée, divulguée, revendue, broyée, atomisée, etc.)