[Précédent : Ancres] [Sommaire] [Suivant : Ensembles d'adresses ("Pools") et Partage de Charge]
Mettre en queue quelque chose signifie stocker, de manière ordonnée, cette chose pendant qu'elle attend un traitement. Dans un réseau informatique, quand les paquets de données sont envoyés à l'extérieur de l'hôte, ils entrent dans une queue où ils attendent un traitement par le système d'exploitation. Celui-ci décide ensuite quelle queue et quel(s) paquet(s) de cette queue doivent être traités. L'ordre dans lequel le système d'exploitation sélectionne les paquets à traiter peut affecter les performances du réseau. Par exemple, imaginez un utilisateur lançant deux applications réseau : SSH et FTP. Idéalement, les paquets SSH devraient être traités avant les paquets FTP à cause de la sensibilité au temps de SSH; quand une clef est entrée dans le client SSH, une réponse immédiate est attendue, mais un transfert FTP retardé de quelques secondes n'attirera pratiquement pas l'attention. Mais que se passe-t-il si le routeur manipulant ces connexions traite un grand nombre de paquets provenant de la connexion FTP avant de traiter la connexion SSH ? Les paquets de la connexion SSH resteront dans la queue (ou seront rejetés par le routeur si la queue n'est pas assez grande pour accueillir tous les paquets) et la session SSH apparaitra certainement comme ralentie ou haletante. En modifiant la stratégie de mise en queue utilisée, la bande passante du réseau peut être partagée de façon juste entre les différents applications, utilisateurs et ordinateurs.
Notez que la mise en queue est utile uniquement pour les paquets sortant ("outbound"). Une fois qu'un paquet arrive sur une interface dans la direction entrante il est déjà trop tard pour le mettre en queue -- la bande passante a déjà été consommée et l'interface le reçoit simplement. La seule solution est d'activer la mise en queue sur un routeur adjacent ou, si l'hôte recevant le paquet agit comme un routeur, d'activer la mise en queue sur l'interface interne sur laquelle les paquets quittent le routeur.
OpenBSD supporte deux algorithmes additionnels :
Les queues CBQ sont ordonnées de manière hiérarchique. Au sommet de la hiérarchie se trouve la queue "root" qui définit la totalité de la bande passante disponible. Les queues enfant sont crées sous la queue "root", chacune d'elle peut se voir assigner une partie de la bande passante de la queue "root". Par exemple, les queues peuvent être définies comme suit :
Dans ce cas, la totalité de la bande passante est fixée à 2 megabits par seconde (Mbps). Cette bande passante est ensuite subdivisée en trois queues enfant.
La hiérarchie peut encore être approfondie en définissant des queues dans les queues. Pour subdiviser équitablement la bande passante entre les différents utilisateurs et aussi classer leur trafic pour éviter que certains protocoles ne privent de bande passante d'autres protocoles, une structure de mise en queue comme celle-ci peut être définie :
Notez qu' à chaque niveau, la somme des bandes passantes assignées à chaque queue ne doit pas être supérieure à celle assignée à la queue parent.
Une queue peut être configurée pour emprunter de la bande passante aux queues parent si ces dernières en ont en excès suite à la non-utilisation par d'autres queues enfant. Considérez le réglage de mise en queue suivant :
Si le trafic dans la queue ftp excède 900Kbps et le trafic dans la queue UserA est inférieur à 1Mbps (parce que la queue ssh utilise moins que les 100Kbps qu'elle dispose), la queue ftp empruntera l'excès de bande passante de UserA. Dans cette optique la queue ftp est en mesure d'utiliser davantage de bande passante que ce qui lui est assigné quand elle fait face à une surcharge. Quand la queue ssh verra sa charge augmenter, la bande passante empruntée sera restituée.
CBQ assigne une priorité à chaque queue. Les queues avec une priorité élevée sont préférées aux queues avec une priorité inférieure pendant une congestion tant que les deux queues partagent le même parent (en d'autres termes, tant que les deux queues appartiennent à une même branche de la hiérarchie). Les queues avec une même priorité sont traitées dans un mode "round-robin". Par exemple :
CBQ traitera les queues UserA et UserB dans un mode "round-robin" -- aucune queue ne sera préférée à une autre. Pendant le temps ou la queue UserA est traitée, CBQ traitera aussi les queues enfant. Dans ce cas, la queue ssh a une priorité plus élevée et aura un traitement préférentiel vis à vis de la queue ftp si le réseau est congestionné. Notez que les queues ssh et ftp n'ont pas leurs priorités comparées à celles de UserA et UserB à cause du fait qu'elles ne sont pas dans une même branche de la hiérarchie.
Pour un regard plus détaillé sur la théorie du fonctionnement de CBQ, veuillez consulter les Références sur CBQ.
La structure des queues de PRIQ est plate -- vous ne pouvez pas définir de queue au sein d'une autre queue. La queue "root" est définie et possède la totalité de la bande passante disponible, et les sous-queues sont définies ensuite en aval. Considérez l'exemple suivant :
La queue "root" est définie comme ayant 2Mbps de bande passante disponible et trois sous-queues sont définies. La queue avec la plus haute priorité (le nombre priorité le plus grand) est servie en premier. Une fois que tous les paquets dans cette queue ont été traités, ou si la queue est vide, PRIQ s'occupe de la queue avec la priorité suivante. Au sein d'une queue donnée, les paquets sont traités selon la manière "First In First Out" (FIFO).
Il est important de noter que si vous utilisez PRIQ, vous devez créer vos queues très prudemment. A cause du fait que PRIQ traite toujours une queue avec une grande priorité avant une queue avec une priorité basse, il est possible qu'une queue avec une priorité élevée cause la suppression ou la disparition des paquets d'une queue avec une priorité basse si la queue avec la priorité élevée reçoit un flux constant de paquets.
RED est utile car il évite la situation connue sous le nom de synchronisation globale et il peut s'adapter à des bonds du trafic. La synchronisation globale se réfère à une perte totale des données sortantes due à la suppression simultanée de paquets de plusieurs connexions. Par exemple, si la congestion apparait sur un routeur supportant le trafic de 10 connexions FTP et tous les paquets de ces connexions sont rejetés (comme c'est le cas avec une mise en queue FIFO), la totalité du trafic sortant sera rejeté; brusquement. Ce n'est pas une situation idéale car elle entraîne une réduction du trafic de toutes les connexions FTP ce qui signifie que le réseau n'est plus utilisé avec son potentiel maximum. RED évite cela en choisissant aléatoirement une de ces connexions plutôt que de choisir toutes les connexions. Les connexions utilisant une large partie de la bande passante ont une probabilité supérieure de voir leurs paquets rejetés. Dans cette optique, les connexions avec une haute bande passante seront étranglées, la congestion sera évitée, et les pertes violentes de trafic de sortie n'auront pas lieu. De plus, RED est capable de supporter des explosions du trafic car il commence la suppression des paquets avant que la queue ne devienne pleine. Si une explosion du trafic se produit, il y aura assez d'espace pour mémoriser les nouveaux paquets.
RED ne devrait être utilisé que quand le protocole est capable de répondre aux indicateurs de congestion du réseau. Dans beaucoup de cas cela signifie que RED devrait être utilisé pour mettre en queue du trafic TCP et non du trafic UDP ou ICMP.
Pour un regard plus détaillé sur la théorie derrière RED, veuillez consulter References on RED.
Pour plus d'informations sur ECN, veuillez consulter RFC 3168.
Parce que ALTQ a été fusionnée avec PF, ce dernier doit être activé pour que la mise en queue fonctionne. Les instructions sur la procédure d'activation de PF peuvent être trouvées dans les Principes de base.
La Mise en queue est configurée dans pf.conf. Il y a deux types de directives utilisées pour configurer la Mise en Queue :
La syntaxe de la directive altq on est :
altq on interface scheduler bandwidth bw qlimit qlim \
tbrsize size queue { queue_list }
Par exemple :
altq on fxp0 cbq bandwidth 2Mb queue { std, ssh, ftp }Ceci active CBQ sur l'interface fxp0. La totalité de la bande passante disponible est fixée à 2Mbps. Trois queues enfant sont définies : std, ssh et ftp.
La syntaxe pour la directive queue est :
queue name [on interface] bandwidth bw [priority pri] [qlimit qlim] \
scheduler ( sched_options ) { queue_list }
Suite de l'exemple ci-dessus :
queue std bandwidth 50% cbq(default)
queue ssh bandwidth 25% { ssh_login, ssh_bulk }
queue ssh_login bandwidth 25% priority 4 cbq(ecn)
queue ssh_bulk bandwidth 75% cbq(ecn)
queue ftp bandwidth 500Kb priority 3 cbq(borrow red)
Ici, les paramètres des queues enfant définies précédemment sont définis. La queue std se voit attribuer une bande passante correspondant à 50% de celle de la queue "root" (1 Mbps) et est définie comme queue par défaut. La queue ssh se voit assigner 25% de la bande passante de la queue racine (500kb) et contient également deux autres queues, ssh_login et ssh_bulk. La queue ssh_login a une priorité plus élevée que ssh_bulk et les deux ont ECN activé. La queue ftp obtient une bande passante de 500Kbps et obtient une priorité de 3. Elle peut aussi emprunter de la bande passante quand une quantité supplémentaire est disponible et RED est activé.
REMARQUE : Chaque définition de queue enfant a sa bande passante spécifiée. Sans spécifier la bande passante, PF donnera 100% de la bande passante de la queue parente. Dans cette situation, ceci causera une erreur lors du chargement des règles sauf s'il y a une queue avec 100% de la bande passante, aucune autre queue ne peut être déclarée à ce niveau, car il n'y a plus de bande passante à allouer.
Pour assigner du trafic à une queue, le mot-clé queue est utilisé en conjonction avec les règles de filtrage de PF. Par exemple, considérons un jeu de règles de filtrage contenant une ligne comme :
pass out on fxp0 from any to any port 22
Les paquets répondant à cette règle peuvent être assignés à une queue spécifique en utilisant le mot-clé queue :
pass out on fxp0 from any to any port 22 queue ssh
Lorsque l'on utilise le mot-clé queue avec les directives block, les paquets TCP RST ou ICMP Unreachable résultants sont assignés dans la queue spécifiée.
Notez que la désignation des queues est possible sur une interface différente de celle définie dans la directive altq on :
altq on fxp0 cbq bandwidth 2Mb queue { std, ftp }
queue std bandwidth 500Kb cbq(default)
queue ftp bandwidth 1.5Mb
pass in on dc0 from any to any port 21 queue ftp
La Mise en queue est activée sur fxp0 mais la désignation concerne dc0. Si les paquets répondant à la règle pass sortent de l'interface fxp0, ils seront mis en queue dans ftp. Ce type de mise en queue peut être très pratique sur les routeurs.
Normalement, un seul nom de queue est donné avec le mot-clé queue, mais si un deuxième nom est spécifié cette queue sera utilisée pour les paquets avec un Type de Service (ToS) "low-delay" et pour les paquets TCP ACK sans donnée. Un bon exemple de ceci est l'utilisation de SSH. Les connexions de sessions SSH mettent le ToS en "low-delay" contrairement aux sessions SCP et SFTP. PF peut utiliser cette information pour mettre les paquets correspondant à une connexion dans une queue différente que celles pour les connexions sans ouverture de session. Ceci peut être utile pour donner la priorité aux connexions avec ouverture de session sur les paquets de transfert de fichiers.
pass out on fxp0 from any to any port 22 queue(ssh_bulk, ssh_login)
Ceci assigne les paquets correspondant aux connexions d'ouverture de session SSH à la queue ssh_login et les paquets correspondant aux connexions SCP et SFTP dans la queue ssh_bulk. Les connexions d'ouverture de session auront leurs paquets traités avant ceux des connexions SCP et SFTP car la queue ssh_login a une priorité plus élevée.
L'assignation des paquets TCP ACK à une queue ayant une priorité élevée est utile pour les connexions asymétriques, c'est à dire les connexions qui ont des bandes passantes différentes en envoi et en réception, comme les lignes ADSL. Avec une ligne ADSL, si le canal d'envoi est utilisé à son maximum et si un téléchargement est lancé, le téléchargement en souffrira car les paquets TCP ACK devant être envoyés seront congestionnés quand ils essaieront de traverser le canal d'envoi. Des tests ont montré que pour réaliser les meilleurs résultats, la bande passante de la queue d'envoi doit être inférieure à la capacité maximale. Par exemple, si une ligne ADSL a un envoi maximum de 640Kbps, le fait de régler la bande passante de la queue "root" sur une valeur comme 600Kb entraînera de meilleures performances. C'est après des essais et des erreurs que vous obtiendrez les meilleurs réglages de bande passante.
Quand on utilise le mot-clé queue avec des règles qui gardent l'état comme :
pass in on fxp0 proto tcp from any to any port 22 flags S/SA \
keep state queue ssh
PF enregistrera la queue dans la table d'états ce qui entraînera que les paquets traversant fxp0 au retour et répondant à la connexion "stateful" termineront dans la queue ssh. Notez que même si le mot-clé queue est utilisé dans une règle filtrant le trafic entrant, le but est de spécifier une queue pour le trafic sortant correspondant; la règle ci-dessus ne mettra pas en queue les paquets entrants.
[ Alice ] [ Charlie ]
| | ADSL
---+-----+-------+------ dc0 [ OpenBSD ] fxp0 -------- ( Internet )
|
[ Bob ]
Dans cet exemple, OpenBSD est utilisé sur une passerelle Internet pour un petit réseau à domicile avec trois stations de travail. La passerelle réalise le filtrage de paquets et la NAT. La connexion Internet via une ligne ADSL possède une bande passante descendante de 2MBps et montante de 640Kbps.
La politique de mise en queue pour ce réseau :
Le jeu de règles ci-dessous permet cette politique réseau. Notez que seules les directives de pf.conf qui concernent directement la politique ci-dessus sont présentes; nat, rdr, options, etc... ne sont pas montrées.
# active la mise en queue sur l'interface externe pour contrôler
# le trafic allant sur Internet. utilise l'algorithme priq pour
# contrôler uniquement les priorités.
# fixe la bande passante à 610Kbps pour avoir les meilleures
# performances à la sortie de la queue TCP ACK.
altq on fxp0 priq bandwidth 610Kb queue { std_out, ssh_im_out, dns_out, \
tcp_ack_out }
# définit les paramètres pour les queues enfant.
# std_out - la queue standard. toute règle de filtrage ci-dessous
# qui ne spécifie pas explicitement une queue aura
# son trafic ajouté à cette queue.
# ssh_im_out - trafic généré par le SSH interactif et
# la messagerie instantanée
# variés.
# dns_out - requêtes DNS.
# tcp_ack_out - paquets TCP ACK sans donnée.
queue std_out priq(default)
queue ssh_im_out priority 4 priq(red)
queue dns_out priority 5
queue tcp_ack_out priority 6
# active la mise en queue sur l'interface interne en vue de contrôler
# le trafic provenant d'Internet. utilise l'algorithme cbq pour
# contrôler la bande passante. la bande passante maximale est de
# 2Mbps.
altq on dc0 cbq bandwidth 2Mb queue { std_in, ssh_im_in, dns_in, bob_in }
# définit les paramètres pour les queues enfant.
# std_in - la queue standard. toute règle de filtrage ci-dessous
# qui ne spécifie pas explicitement une queue aura
# son trafic ajouté à cette queue.
# ssh_im_in - trafic généré par le SSH interactif et
# par la messagerie instantanée.
# dns_in - réponses DNS.
# bob_in - bande passante réservée à la station
# de travail de Bob. l'autorise à emprunter.
queue std_in bandwidth 1.6Mb cbq(default)
queue ssh_im_in bandwidth 200Kb priority 4
queue dns_in bandwidth 120Kb priority 5
queue bob_in bandwidth 80Kb cbq(borrow)
# ... dans la section filtrage de pf.conf ...
alice = "192.168.0.2"
bob = "192.168.0.3"
charlie = "192.168.0.4"
local_net = "192.168.0.0/24"
ssh_ports = "{ 22 2022 }"
im_ports = "{ 1863 5190 5222 }"
# règles de filtrage pour l'entrée en fxp0
block in on fxp0 all
# règles de filtrage pour la sortie en fxp0
block out on fxp0 all
pass out on fxp0 inet proto tcp from (fxp0) to any flags S/SA \
keep state queue(std_out, tcp_ack_out)
pass out on fxp0 inet proto { udp icmp } from (fxp0) to any keep state
pass out on fxp0 inet proto { tcp udp } from (fxp0) to any port domain \
keep state queue dns_out
pass out on fxp0 inet proto tcp from (fxp0) to any port $ssh_ports \
flags S/SA keep state queue(std_out, ssh_im_out)
pass out on fxp0 inet proto tcp from (fxp0) to any port $im_ports \
flags S/SA keep state queue(ssh_im_out, tcp_ack_out)
# règles de filtrage pour l'entrée en dc0
block in on dc0 all
pass in on dc0 from $local_net
# règles de filtrage pour la sortie en dc0
block out on dc0 all
pass out on dc0 from any to $local_net
pass out on dc0 proto { tcp udp } from any port domain to $local_net \
queue dns_in
pass out on dc0 proto tcp from any port $ssh_ports to $local_net \
queue(std_in, ssh_im_in)
pass out on dc0 proto tcp from any port $im_ports to $local_net \
queue ssh_im_in
pass out on dc0 from any to $bob queue bob_in
|
( IT Dept ) [ Boss's PC ]
| | T1
--+----+-----+---------- dc0 [ OpenBSD ] fxp0 -------- ( Internet )
| fxp1
[ COMP1 ] [ WWW ] /
| /
--+----------'
Dans cet exemple, l'hôte OpenBSD agit en pare-feu pour le réseau d'une entreprise. L'entreprise utilise un serveur WWW dans la partie DMZ de son réseau où les clients envoient leurs sites via FTP. Le département IT a son propre sous-réseau connecté au réseau principal, et le directeur a un PC sur son bureau utilisé pour les emails et le surf sur Internet. La connexion à Internet se fait via une ligne T1 avec une bande passante de 1.5Mbps dans les deux directions. Tous les autres segments du réseau utilisent Fast Ethernet (100Mbps).
L'administrateur réseau a décidé de la politique suivante :
Le jeu de règles ci-dessous permet cette politique réseau. Notez que seul les directives de pf.conf qui concernent directement la politique ci-dessus sont présentes; nat, rdr, options, etc... ne sont pas montrées.
# active la mise en queue sur l'interface externe pour les paquets sortant sur
# Internet. utilise l'algorithme cbq, afin que la bande passante de chaque
# queue puisse être contrôlée. la bande passante sortante
# maximale est de 1.5Mbps.
altq on fxp0 cbq bandwidth 1.5Mb queue { std_ext, www_ext, boss_ext }
# définit les paramètres pour les queues enfant.
# std_ext - la queue standard. également queue par défaut
# pour le trafic sortant sur fxp0.
# www_ext - queue contenant les queues du serveur WWW. limitée à
# 500Kbps.
# www_ext_http - trafic http du serveur WWW; plus haute priorité.
# www_ext_misc - tout le trafic non-http du serveur WWW.
# boss_ext - trafic venant de l'ordinateur du patron.
queue std_ext bandwidth 500Kb cbq(default borrow)
queue www_ext bandwidth 500Kb { www_ext_http, www_ext_misc }
queue www_ext_http bandwidth 50% priority 3 cbq(red borrow)
queue www_ext_misc bandwidth 50% priority 1 cbq(borrow)
queue boss_ext bandwidth 500Kb priority 3 cbq(borrow)
# active la mise en queue sur l'interface interne pour contrôler le trafic
# venant d'Internet ou de la DMZ. utilise l'algorithme cbq pour contrôler
# la bande passante de chaque queue. la bande passante sur cette interface
# est fixée au maximum. le trafic venant de la DMZ sera en mesure
# d'utiliser la totalité de cette bande passante alors que le trafic
# venant de l'Internet sera limité à 1.0Mbps (car 0.5Mbps
# (500Kbps) sont alloués à fxp1).
altq on dc0 cbq bandwidth 100% queue { net_int, www_int }
# définit les paramètres pour les queues enfant.
# net_int - queue contenant le trafic provenant de Internet. la bande
# passante est de 1.0Mbps.
# std_int - la queue standard. également queue par défaut pour
# le trafic sortant en dc0.
# it_int - trafic vers le réseau du département informatique;
# réserver 500Kbps.
# boss_int - trafic vers le PC du patron; assigner la plus haute
# priorité.
# www_int - trafic du serveur WWW de la DMZ; vitesse maximale.
queue net_int bandwidth 1.0Mb { std_int, it_int, boss_int }
queue std_int bandwidth 250Kb cbq(default borrow)
queue it_int bandwidth 500Kb cbq(borrow)
queue boss_int bandwidth 250Kb priority 3 cbq(borrow)
queue www_int bandwidth 99Mb cbq(red borrow)
# active la mise en queue sur l'interface de la DMZ pour contrôler
# le trafic destiné au serveur WWW. cbq sera utilisé
# sur cette interface tant que le contrôle détaillé de la bande
# passante sera nécessaire. la bande passante sur cette interface
# est fixée au maximum. le trafic provenant du réseau
# interne sera en mesure d'utiliser la totalité de la bande passante
# alors que le trafic provenant d'Internet sera limité à 500Kbps.
altq on fxp1 cbq bandwidth 100% queue { internal_dmz, net_dmz }
# définit les paramètres pour les queues enfant.
# internal_dmz - trafic provenant du réseau interne.
# net_dmz - queue contenant le trafic provenant de Internet.
# net_dmz_http - trafic http; plus haute priorité.
# net_dmz_misc - tout autre trafic. c'est aussi la queue par défaut.
queue internal_dmz bandwidth 99Mb cbq(borrow)
queue net_dmz bandwidth 500Kb { net_dmz_http, net_dmz_misc }
queue net_dmz_http bandwidth 50% priority 3 cbq(red borrow)
queue net_dmz_misc bandwidth 50% priority 1 cbq(default borrow)
# ... dans la section filtrage du pf.conf ...
main_net = "192.168.0.0/24"
it_net = "192.168.1.0/24"
int_nets = "{ 192.168.0.0/24, 192.168.1.0/24 }"
dmz_net = "10.0.0.0/24"
boss = "192.168.0.200"
wwwserv = "10.0.0.100"
# refus par défaut
block on { fxp0, fxp1, dc0 } all
# règles de filtrage pour l'entrée de fxp0
pass in on fxp0 proto tcp from any to $wwwserv port { 21, \
> 49151 } flags S/SA keep state queue www_ext_misc
pass in on fxp0 proto tcp from any to $wwwserv port 80 \
flags S/SA keep state queue www_ext_http
# règles de filtrage pour la sortie de fxp0
pass out on fxp0 from $int_nets to any keep state
pass out on fxp0 from $boss to any keep state queue boss_ext
# règles de filtrage pour l'entrée de dc0
pass in on dc0 from $int_nets to any keep state
pass in on dc0 from $it_net to any queue it_int
pass in on dc0 from $boss to any queue boss_int
pass in on dc0 proto tcp from $int_nets to $wwwserv port { 21, 80, \
> 49151 } flags S/SA keep state queue www_int
# règles de filtrage pour la sortie de dc0
pass out on dc0 from dc0 to $int_nets
# règles de filtrage pour l'entrée de fxp1
pass in on fxp1 proto { tcp, udp } from $wwwserv to any port 53 \
keep state
# règles de filtrages pour la sortie de fxp1
pass out on fxp1 proto tcp from any to $wwwserv port { 21, \
> 49151 } flags S/SA keep state queue net_dmz_misc
pass out on fxp1 proto tcp from any to $wwwserv port 80 \
flags S/SA keep state queue net_dmz_http
pass out on fxp1 proto tcp from $int_nets to $wwwserv port { 80, \
21, > 49151 } flags S/SA keep state queue internal_dmz
|
[Précédent : Ancres] [Index] [Suivant : Ensembles d'adresses ("Pools") et Partage de Charge]