Router et partager équitablement une connexion ADSL avec un serveur Linux

Mon domicile est connecté à internet en ADSL avec des débits corrects (14Mbit/s descendant, 1Mbit/s remontant). Mais cela ne suffit pas à éviter d’avoir une liaison saturée lorsque l’un de mes adolescents décide de télécharger un nouveau jeu. Résultat : plus d’accès à internet, débranchement sauvage dudit PC et le ton qui monte…

Une solution plus intelligente était à trouver, d’autant que j’ai un serveur qui fait office de passerelle avec la box adsl. Ce serveur doit donc être capable d’optimiser les transferts et surtout de les partager équitablement, c’est ce qu’on appelle de la mise en forme de trafic, ou « Traffic shaping« .

Regardons tout d’abord la configuration des ports réseau de mon serveur :

root@hpserv:~#
iface out0 inet static
address 192.168.cc.dd
netmask 255.255.255.0
gateway 192.168.cc.dd
pre-up iptables-restore < /etc/iptables.up.rules
dns-nameservers 212.27.40.240 212.27.40.241 8.8.8.8 8.8.4.4
iface br0 inet static
address 192.168.cc.dd
netmask 255.255.255.0
post-up iptables-restore < /etc/iptables.up.rules

J’ai donc 2 interfaces réseau : out0 connecte le serveur à la box adsl, br0 connecte le serveur au switch gigabit du réseau local

Le noyau linux intègre nativement la gestion avancée des flux de donnée réseau ( netfilter ), et les outils nécessaires pour les gérer sont installés nativement sur ubuntu server ( iptables et tc ).
Petite subtilité dans mon cas, j’ai également Webmin qui est installé. Cet outil me permet de faire l’administration du serveur pour les tâches simples, je vais donc modifier le fichier iptables utilisé par webmin pour réaliser les modification (/etc/iptables.up.rules)
Première étape de la configuration : mettre des règles de priorisation des flux, sachant que ceux-ci ne peuvent être appliqués que sur des flux sortant (sur le principe que seul celui qui envoie est capable de moduler finement le débit). Voici le script qui me permet de régler ces paramètres :

#!/bin/bash
# Inspiré de ces pages :
# http://wiki.linuxwall.info/doku.php/fr:ressources:dossiers:networking:qos_traffic_control
# https://bbs.archlinux.org/viewtopic.php?id=153418
# https://wiki.gentoo.org/wiki/Traffic_shaping
# https://connect.ed-diamond.com/GNU-Linux-Magazine/GLMF-127/QoS-et-gestion-du-trafic-avec-Traffic-Control
tc qdisc del dev br0 root
tc qdisc del dev out0 root
# paramétrage de l'interface réseau local, flux descendant
tc qdisc add dev br0 root handle 1: htb default 23
tc class add dev br0 parent 1:0 classid 1:10 htb rate 13mbit ceil 13mbit
tc class add dev br0 parent 1:0 classid 1:20 htb rate 1gbit ceil 1gbit
tc class add dev br0 parent 1:10 classid 1:11 htb rate 7mbit ceil 13mbit prio 1 burst 10kbit
tc qdisc add dev br0 parent 1:11 handle 111: sfq perturb 10
tc class add dev br0 parent 1:10 classid 1:12 htb rate 3mbit ceil 13mbit prio 2 burst 10kbit
tc qdisc add dev br0 parent 1:12 handle 112: sfq perturb 10
tc class add dev br0 parent 1:10 classid 1:13 htb rate 3mbit ceil 13mbit prio 3 burst 10kbit
tc qdisc add dev br0 parent 1:13 handle 113: sfq perturb 10
tc class add dev br0 parent 1:20 classid 1:21 htb rate 400mbit ceil 1000mbit prio 4 burst 50kbit
tc qdisc add dev br0 parent 1:21 handle 121: sfq perturb 10
tc class add dev br0 parent 1:20 classid 1:22 htb rate 300mbit ceil 1000mbit prio 5 burst 50kbit
tc qdisc add dev br0 parent 1:22 handle 122: sfq perturb 10
tc class add dev br0 parent 1:20 classid 1:23 htb rate 300mbit ceil 1000mbit prio 6 burst 50kbit
tc qdisc add dev br0 parent 1:23 handle 123: sfq perturb 10
tc filter add dev br0 parent 1:0 protocol ip prio 1 handle 11 fw flowid 1:11
tc filter add dev br0 parent 1:0 protocol ip prio 2 handle 12 fw flowid 1:12
tc filter add dev br0 parent 1:0 protocol ip prio 3 handle 13 fw flowid 1:13
tc filter add dev br0 parent 1:0 protocol ip prio 4 handle 21 fw flowid 1:21
tc filter add dev br0 parent 1:0 protocol ip prio 5 handle 22 fw flowid 1:22
tc filter add dev br0 parent 1:0 protocol ip prio 6 handle 23 fw flowid 1:23
# paramétrage de l'interface ADSL, flux remontant
tc qdisc add dev out0 root handle 1: htb default 11
tc class add dev out0 parent 1: classid 1:1 htb rate 950kbit
tc class add dev out0 parent 1:1 classid 1:11 htb rate 950kbit prio 1
tc qdisc add dev out0 parent 1:11 fq_codel noecn

 

Les deux interfaces portent des règles de priorisation :

  • br0 : côté réseau local
    • la priorisation se fait suivant la méthode HTB (Hierarchical Token Bucket )
      Elle consiste, en 2 mots, à ranger les données  à envoyer dans des paniers qui sont vidés en fonction de leur priorité
    • Deux classes principales sont définies
      • la 1:10 gère les flux venant d’internet et une limite de vitesse est fixé à 90% de la vitesse maximum de mon adsl
        3 paniers y sont créés (1:11, 1:12, 1:13) avec des priorités décroissantes (priorité 1 étant la priorité la plus forte) et des débit assurés (rate) se réduisant
      • la 1:20 gère les flux locaux avec une limite de vitesse fixée au maximum du réseau (qui ne sature jamais en fait…)
        Idem 3 paniers y sont créés (1:21, 1:22, 1:23)
    • Enfin des filtres sont rajoutés permettant de ranger les paquets de données tagués dans les bons paniers
      Exemple : un panier tagué 11 (handle 11) ira dans le panier 1:11. Autant faire simple …
  • out0 : côté routeur adsl
    • Celui-ci est présenté comme utilisant une méthode HTB pour définir le débit de la ligne à 95% de son débit maximum.
    • Mais il n’y a en fait qu’un seul panier actif pour le moment (le numéro 1:11), la méthode HTB n’a pas d’effet.
    • C’est la dernière ligne qui est importante car elle remet un mode de routage de type fq_codel sur ce panier.
      La méthode fq_codel est préconisée dans ce type de liaison à faible débit avec un réseau supportant de multiples flux parallèles. Voir cet article pour plus de détails :  What_can_I_do_about_Bufferbloat

Maintenant qu’on a défini les règles de priorisation, il va falloir mettre des marques sur les paquets de données qui vont permettre de les mettre dans les bons paniers. Cela peut se faire en intégrant des règles ipfilter. Voici une partie de celles que j’ai posées dans la table mangle de iptables :

*mangle
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -p tcp -m tcp ! -s 192.168.cc.dd/24 -j MARK --set-mark 12
-A FORWARD -p udp -m udp ! -s 192.168.cc.dd/24 -j MARK --set-mark 12
-A FORWARD -p tcp -m tcp ! -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 13
-A FORWARD -p udp -m udp ! -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 13 
-A FORWARD -p tcp -m tcp ! -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 11 
-A FORWARD -p udp -m udp ! -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 11
-A OUTPUT -p tcp -m tcp -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 21
-A OUTPUT -p udp -m udp -s 192.168.cc.dd/24 -d 192.168.cc.dd -o br0 -j MARK --set-mark 21

Par défaut, tous les paquets tcp ou udp venant de l’extérieur du réseau local (! -s 192.168.cc.dd/24) et forwardés partiront dans le panier 1:12
En fonction de l’adresse IP de destination, par exemple mon PC ou la TV sur IP, ces données iront plutôt dans le panier 11 (+ prioritaire) ou 13 (- prioritaire)
En ce qui concerne les données émises par le serveur sur le réseau local, certains périphériques prioritaires (mon PC) seront priorisés en étant mis dans le panier 21, alors que ces données  vont par défaut dans le panier 22

Enfin pour vérifier que tout cela fonctionne, j’ai repris un script (d’ailleurs légèrement corrigé pour fonctionner en gbit et avec fq_codel) que vous pourrez trouver dans le fichier à télécharger ici. Il permet d’afficher les statistiques d’utilisation de ces niveaux de priorisation dans un format tabulaire facile à lire.

root@hpserv:~# ./qosstats br0
br0
Class Paren Prio Rate Ceil Burst     Sent Dropped   Backlog kbps Pps
==============================================================================
1:10  -      -     13   13 1599b   881829       0    0b/0p   -    -
1:11  1:10   4     7    13 1598b   164414       0    0b/0p   -    -
1:12  1:10   5     3    13 1599b    10613       0    0b/0p   -    -
1:13  1:10   6     3    13 1599b   706802       0    0b/0p   -    -
1:20  -      -     0     0 1375b  4815115       0    0b/0p   -    -
1:21  1:20   1   400     0 1600b  3580763       0    0b/0p   -    -
1:22  1:20   2   300     0 1537b  1234352       0    0b/0p   -    -
1:23  1:20   3   300     0 1537b        0       0    0b/0p   -    -

Vincent Recipon

Propriétaire de ce blog. Owner of this blog.

1 réponse

  1. lundi 16 août 2021

    […] 6. Router et partager équitablement une connexion ADSL avec … […]

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.