9.6. Klassifizieren von Paketen mittels Filter

Zur Bestimmung welche Klasse ein Paket verarbeiten soll, wird jedes Mal die so genannte Klassifikatorkette 'classifier chain' benutzt, sobald eine Entscheidung getätigt werdem muss. Diese Kette beinhaltet alle Filter der classful qdisc für die Entscheidung.

Zur Wiederholung, der Baum, der kein Baum ist:

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

Sobald ein Paket ansteht, wird an jeder Abzweigung der Filterkette die entsprechende Anweisung zu Rate gezogen. Ein typischer Aufbau könnte ein 1:1 Filter sein, der ein Paket zu 12: lenkt und der Filter auf 12: sendet das Paket zu 12:2.

Du könntest auch diese letzte Regel bei 1:1 festlegen, aber es wird Effizienter, wenn du spezifische Tests weiter unten in der Kette durchführst.

Nebenbei bemerkt: du kannst kein Paket 'nach oben' filtern. Auch bei HTB solltest du alle Filter an der Wurzel befestigen!

Und noch mal - Pakete werden nur nach unten in die Warteschlange gestellt! Werden sie aus der Warteschlange entfernt, gehen sie wieder hinauf, wo die Schnittstelle beginnt. Sie fallen nicht am Ende des Baumes zurück zum Netzwerk-Adapter!

9.6.1. Einige einfache Filter-Beispiele

Wie bereits im Kapitel Classifier erläutert, kannst du buchstäblich bei allem einen sehr komplizierten Syntax benutzen. Zum Beginn zeigen wir wie die offensichtlichsten Dinge erledigt werden, was zum Glück ganz einfach ist.

Sagen wir, wir haben eine PRIO qdisc namens '10:' mit drei Klassen und wir wollen den gesamten Datenverkehr von und nach Port 22 auf die höchste Bandpriorität zuweisen, die Filter wären dann:

# 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

Was bedeutet das? Es heißt dort: angeheftet an eth0, Knoten 10: mit Priorität 1 u32-Filter, der dem IP-Zielport 22 *genau* entspricht und sende es zum Band 10:1. Und das wiederholt sich dann für den Quell-Port 80. Der letzte Befehl sagt, dass alles was nicht passt bis zum Band 10:2 gehen soll, der nächst höheren Priorität.

Du mußt 'eth0' hinzufügen, oder wie auch immer deine Schnittstelle aufgerufen wird, weil jede Schnittstelle einen eindeutigen Namensraum zum benutzen haben muss.

Zum Auswählen einer IP-Adresse benutzt du dieses:

# 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

Dies weist Traffic auf 4.3.2.1 und Traffic von 1.2.3.4 auf die Warteschlange mit höchster Priorität, und den Rest auf die Nächsthöhere zu.

Du kannst Regeln verketteten, wenn es passt auf den Traffic von 1.2.3.4 und von Port 80, dann mach dies:

# 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. Alle Filterkommandos die man normalerweise braucht

Die meisten hier vorgestellten shaping-Befehle beginnen mit dieser Präambel:

# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 ..
Dies sind die so genannten 'u32'-Matches, die auf jeden Teil eines Pakets passen können.

Auf Quell-/Zieladresse

Quellmaske 'match ip src 1.2.3.0/24', Zielmaske 'match ip dst 4.3.2.0/24'. Für einen einzelnen Host benutze /32 oder lass die Maske weg.

Auf Quell-/Zielport, für alle IP-Protokolle

Quelle: 'match ip sport 80 0xffff', Ziel: 'match ip dport 80 0xffff'

Auf IP-Protokoll (tcp, udp, icmp, gre, ipsec)

Benutze die Ziffern aus /etc/protocols, Beispielweise ist icmp 1: 'match ip protocol 1 0xff'.

Auf fwmark

Du kannst entweder mit ipchains oder iptables Pakete markieren und hast eine Markierung die das Routing über Schnittstellen überlebt. Das ist sehr nützlich, um zum Beispiel nur den Verkehr auf eth1 zu beinflussen, der von eth0 kam. Syntax:

# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
Beachte, dass dies kein u32-Match ist!

Du kannst einen Marker wie folgt platzieren:

# iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
Die Zahl 6 ist eine Beliebige.

Wenn du dich nicht in den vollen tc-Filtersyntax einarbeiten willst, und nur iptables verwendest, lerne nur die Auswahl von fwmark. Du kannst auch iptables benutzen um Basisstatistiken auszugeben, die dir beim debuggen deiner Regeln hilft. Der folgende Befehl zeigt dir alle Regeln, welche Pakete in der mangle-Tabelle markiert sind, wie viele Pakete und Bytes angepasst wurden.

# iptables -L -t mangle -n -v

Auf dem TOS-Feld

Wählen von interaktiven, minimal verzögerten Traffic:

# tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff \
     flowid 1:4
Benutze 0x08 0xff für Massentraffic.

Weitere Filterbefehle findest du im Kapitel erweiterte Filter (Advanced Filters).