9.6. Classifier des paquets avec des filtres

Pour déterminer quelle classe traitera un paquet, la « chaîne de classificateurs » est appelée chaque fois qu'un choix a besoin d'être fait. Cette chaîne est constituée de tous les filtres attachés aux gestionnaires de mise en file d'attente basés sur des classes qui doivent prendre une décision.

On reprend l'arbre qui n'est pas un arbre :

                   racine 1:
                      |
                    _1:1_
                   /  |  \
                  /   |   \
                 /    |    \
               10:   11:   12:
              /   \       /   \
           10:1  10:2   12:1  12:2

Quand un paquet est mis en file d'attente, l'instruction appropriée de la chaîne de filtre est consultée à chaque branche. Une configuration typique devrait avoir un filtre en 1:1 qui dirige le paquet vers 12: et un filtre en 12: qui l'envoie vers 12:2.

Vous pourriez également avoir ce dernier filtre en 1:1, mais vous pouvez gagner en efficacité en ayant des tests plus spécifiques plus bas dans la chaîne.

A ce propos, vous ne pouvez pas filtrer un paquet « vers le haut ». Donc, avec HTB, vous devrez attacher tous les filtres à la racine !

Encore une fois, les paquets ne sont mis en file d'attente que vers le bas ! Quand ils sont retirés de la file d'attente, ils montent de nouveau, vers l'interface. Ils ne tombent PAS vers l'extrémité de l'arbre en direction de l'adaptateur réseau !

9.6.1. Quelques exemples simples de filtrage

Comme expliqué dans le chapitre Filtres avancés pour la classification des paquets, vous pouvez vraiment analyser n'importe quoi en utilisant une syntaxe très compliquée. Pour commencer, nous allons montrer comment réaliser les choses évidentes, ce qui heureusement est plutôt facile.

Disons que nous avons un gestionnaire de mise en file d'attente PRIO appelé 10: qui contient trois classes, et que nous voulons assigner à la bande de plus haute priorité tout le trafic allant et venant du port 22. Les filtres seraient les suivants :

# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \
  ip dport 22 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \
  ip sport 80 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2

Qu'est-ce que cela signifie ? Cela dit : attacher à eth0, au nœud 10: un filtre u32 de priorité 1 qui analyse le port de destination ip 22 et qui l'envoie vers la bande 10:1. La même chose est répétée avec le port source 80. La dernière commande indique que si aucune correspondance n'est trouvée, alors le trafic devra aller vers la bande 10:2, la plus grande priorité suivante.

Vous devez ajouter eth0 ou n'importe laquelle de vos interfaces, car chaque interface possède un espace de nommage de ses descripteurs qui lui est propre.

Pour sélectionner une adresse IP, utilisez ceci :

# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
  match ip dst 4.3.2.1/32 flowid 10:1
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
  match ip src 1.2.3.4/32 flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2      \
  flowid 10:2

Ceci dirige le trafic allant vers 4.3.2.1 et venant de 1.2.3.4 vers la file d'attente de plus haute priorité, tandis que le reste ira vers la prochaine plus haute priorité.

Vous pouvez rassembler ces deux vérifications pour récupérer le trafic venant de 1.2.3.4 avec le port source 80 :

# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32
  match ip sport 80 0xffff flowid 10:1

9.6.2. Toutes les commandes de filtres dont vous aurez normalement besoin

La plupart des commandes présentées ici commencent avec le préambule suivant :

# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 ..

Ils sont appelés filtres u32 et analysent N'IMPORTE QUELLE partie d'un paquet.

Sur l'adresse source/destination

Masque pour la source match ip src 1.2.3.0/24 et masque pour la destination match ip dst 4.3.2.0/24. Pour analyser un hôte simple, employez /32 ou omettez le masque.

Sur le port source/destination, tous les protocoles IP

Source: match ip sport 80 0xffff et destination : match ip dport ?? 0xffff

Sur le protocole ip (tcp, udp, icmp, gre, ipsec)

Utilisez les nombres définis dans /etc/protocols, par exemple 1 pour icmp : match ip protocol 1 0xff.

Sur fwmark

Vous pouvez marquer les paquets avec ipchains ou iptables et voir cette marque préservée lors du routage à travers les interfaces. Ceci est vraiment utile pour mettre uniquement en forme le trafic sur eth1 et venant de eth0, par exemple. La syntaxe est la suivante :

# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1

Notez que ce n'est pas une correspondance u32 !

Vous pouvez positionner une marque comme ceci :

# iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6

Le nombre 6 est arbitraire.

Si vous ne voulez pas assimiler la syntaxe complète de tc filter, utilisez juste iptables et apprenez seulement la sélection basée sur fwmark.

Sur le champ TOS

Pour sélectionner le trafic interactif, délai minimum :

# tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff \
     flowid 1:4

Utilisez 0x08 0xff pour le trafic de masse.

Pour plus de commandes de filtrage, voir le chapitre Filtres avancés pour la classification des paquets.