Es gibt eine Vielzahl Spezialdistributionen für Linux, die für ein Unternehmen eine Fertiglösung quasi sind, CD einlegen, warten, Firewall konfigurieren über Web-Interface. So z.B. IPCop Firewall Was den meisten Firewalls fehlt, ist eine vernünftige Bandbreiten - Regelung, QoS (Quality of Service) genannt. Dasselbe gilt auch für einfache Linux Distributionen, die als DSL - Router aufgebaut werden. Immer wieder kommt es aufgrund zu massiven FTP - Downloads, oder bei VoIP über SIPGATE oder SKYPE z.B. zu "Verklemmungen". Dasselbe gilt auch für Webserver, die so massiv mit Mail-Traffic zu tun haben, daß keine Bandbreite mehr für das Ausliefern von Webseiten übrig ist. Das folgende Tutorial behandelt ausführlich diese beiden Fälle, und bietet Skripte an, welche sich auf jedem Linux - Rechner nachrüsten lassen.
Linux enthält seit Kernel 2.4.20 eine Bandbreitenregelung nach den Hierarchial Token Buckets (HTB). Im Gegensatz zu allen anderen Bandbreiten - Regelungen ist das HTB Verfahren sehr einfach zu verstehen und anzuwenden. Es basiert auf einem Baum, der die Bandbreiten auf die verschiedenen Protokolle (SMTP, WWW, TELNET, SSH, ...) aufteilt. Hierzu wird jedem Protokoll eine bestimmte Bandbreite garantiert. Wird diese nicht genutzt, so dürfen andere Protokolle, entsprechend der Aufteilung, proportional mehr Bandbreite nutzen. Es ist zwar ein starres Verfahren, jedoch sehr übersichtlich. Im Gegensatz hierzu sind die anderen Verfahren, z.B. CBQ (Class Based Queueing) zwar leistungsfähiger, jedoch viel schwieriger zu implementieren und zu überwachen. Angesichts der möglichen Wechselwirkungen der verschiedensten statistischen Verfahren (CBQ, CSZ, RED, GRED, SFQ, PRIO, TBF, BFIFO, PIFO, DSMARK, TEQL, HTB, WRR), die der Linux Kernel anbietet, ist dies eine Wissenschaft für sich. Tatsächlich wurden darüber schon Doktorarbeiten geschrieben, nach welchen die Linux Kernel - Module entworfen wurden. Diese sind jedoch nicht nur zur Bandbreitenregelung eines Interfaces gedacht, sondern in Verbindung mit dem Paket iproute, iproute2 zum Umschalten der Netzwerkrouten in Abhängigkeit vom Traffic, was z.B. für Ausfallrouten, für die Paketumsetzung zwischen Ethernet und ATM geeignet ist.
Daher zunächst einmal ein einfaches Beispiel mit HTB. Hierzu müssen die Toolkits tc und iproute2, welche die Bedienungswerkzeuge für die Kernel - Module darstellen, auf dem System vorhanden sein. Nun wird die Bandbreiten - Regelung (queuing discipline) aktiviert:
tc qdisc add dev eth0 root handle 1:0 htb default 10Hier wird für dem Interface eth0 ein root handle (Bezeichner) mit der Ziffer 1:0 (oft auch nur als 1: geschrieben) zugeordnet, auf welches im folgenden sich die (Traffic) - Klassen dann beziehen. Die root - Klasse aktiviert hierbei die Bandbreitenregelung nur. Löscht man diese, z.B. mit tc qdisc del dev eth0 root, so ist die Bandbreitenregelung wieder deaktiviert. htb gibt an, welches statistische Messverfahren zu verwenden ist (Kernel Modul), und default 10 gibt die Klasse an, in welche die Pakete umgeleitet werden, auf die die Bandbreitenreservierung nicht zutrifft, wie z.B. alle anderen Protokolle, die nicht explizit definiert wurden. So kann man z.B. Traffic für bestimmte Protokolle über andere Netzwerke übertragen lassen.
Nun müssen dem root - Handle Traffic-Klassen zugeordnet werden, beginnend mit der parent - Klasse 1:0, die die Wurzel des Baumes der weiteren Traffic - Klassen darstellt:
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 100mbit ceil 100 mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 80mbit ceil 100mbit tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10mbit ceil 100mbit tc class add dev eth0 parent 1:1 classid 1:12 htb rate 10mbit ceil 100mbitHier nun werden zuerst dem qdisc - root handle 1:0 Parent - Klassen zugeordnet, welche dann z.B. auch wieder ein parent 1:0 - Handle enthalten, welches sich auf das root handle bezieht.
1: root qdisc
|
1:1
/ | \
/ | \
/ | \
/ | \
1:10 1:11 1:12
| | |
| 11: |
| |
10: 12: qdisc
/ \ / \
10:1 10:2 12:1 12:2
Es ist möglich, weitere qdisc root handles an z.B. der
Klasse 1:12 anzufügen, um eine bestimmte Bandbreite, z.B. aus einem anderen
Subnetz stammend, nochmals nach Protokollen, wie SMTP, FTP, HTTP zu
unterteilen, z.B. auch mit SFQ:
tc qdisc add dev eth0 parent 1:10 handle 12: sfq perturb 10 tc qdisc add dev eth0 parent 1:12 handle 12: sfq perturb 10Die "Marker" (10,11,12) ist die Verbindung zum Linux Paketfilter der aus dem Datenstrom Pakete identifiziert und für QoS - Klassen markiert. Dies geschieht entweder durch das iptables - Kommando, oder mit ip:
iptables -A POSTROUTING -t mangle -o eth0 -p tcp --sport 80 -j MARK --set-mark 11Hierbei werden die Pakete, die vom Port 80 ausgehen (--sport 80) markiert (-j MARK), und für die Bandbreitenklasse 10 MBit reserviert (--set-mark 11).
-------------- -----------
| PREROUTING | Routing | QoS |
ppp0-->| Markierung |---------------> | |-->eth0, lokale Rechner
| ipchains | Netzwerkmasken | Klassen |
-------------- -----------
Die eigentliche Zuordnung der markierten Paketen zu den Klassen erfolgt erst
mit noch einem weiteren Kommando:
tc filter add dev eth0 parent 1: prio 0 protocol ip handle 11 fw flowid 1:11Hier erst werden die markierten Pakete aus dem Filter - Modul an die Bandbreitenregelung übergeben, bzw zugeordnet, wobei man noch verschiedene Prioritäten angeben kann. Da man ja mehrere Protokolle filtern lassen kann (IP, IPX, IPSec, ...), und einer Traffic - Klasse zuordnen können muß, ist dies notwendig. In dem Beispiel wird also das Protokoll ip mit dem Handle 11 der Klasse 1:11 zugeordnet. Nicht markierte Pakete landen dann automatisch in der Klasse 1:11 gebunden, an welche dann wieder zwei Unterklassen gebunden werden. Prinzipiell könnte man wohl den Traffic Port 80 an die Klasse 1:1 binden, was jedoch keinen Sinn macht. Man benötigt mindestens eine parent Klasse (1:1), die in zwei Unterklassen (1:10, 1:11) aufgeteilt ist, eine, für die iptables die Pakete aus dem Datenstrom herausfischt (1:11), und eine, die für den Rest der Pakete zuständig ist (1:10).
rate legt fest, wie die Bandbreite im Verhältnis aufgeteilt werden soll (90% zu 10%), wenn Vollast anliegt (100mbit). ceil definiert ein oberes, maximales Limit, welches genutzt werden darf, wenn kein anderer Traffic vorhanden ist.
Einen Überblick über die im Kernel aktivierten qdisc und ihre Klassen erhält man mit den verschiedenen tc - Kommandos:
tc qdisc show dev eth0 tc class show dev eth0 tc filter show dev eth0
Fassen wir zusammen: Das Kommando iptables... verwendet die Tabelle mangle, um eine bestimmte Klasse von Traffic zu filtern, dann zu markieren, und an die bereits aktivierte Bandbreitenregelung zu übergeben. Zuerst müssen die Klassen definiert werden, dann erst darf der gefilterte Traffic zugeordnet werden. Dem ausgehenden Traffic auf Port 80 des Webservers wird ein Marker 11 der Bandbreitenregelung zugeordnet, welche dafür sorgt, daß der Webserver auch dann, wenn z.B. SMTP oder FTP - Traffic den Server hoch belastet, mit mindestens 10mbit noch Webseiten ausliefert. Hier nun ein mit script /QoS-Protokoll mitgeschnittenes Beispiel, welches im Wechselspiel die Kommandos und das Ergebnis zeigt, nämlich das, was dann im Kernel angekommen ist:
[root]# tc qdisc del dev eth0 root [root]# tc class show dev eth0 [root]# tc qdisc show dev eth0 [root]# tc qdisc add dev eth0 root handle 1:0 htb default 10 [root]# tc qdisc show dev eth0 qdisc htb 1: r2q 10 default 10 direct_packets_stat 0 [root]# tc qdisc del dev eth0 root [root]# tc qdisc show dev eth0 [root]# tc qdisc show dev eth0 [root]# tc qdisc add dev eth0 root handle 1:0 htb default 10 [root]# tc qdisc show dev eth0 qdisc htb 1: r2q 10 default 10 direct_packets_stat 0 [root]# tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit [root]# tc qdisc show dev eth0 qdisc htb 1: r2q 10 default 10 direct_packets_stat 13 [root]# tc class show dev eth0 class htb 1:1 root prio 0 rate 100Mbit ceil 100Mbit burst 132644b cburst 132644b [root]# tc class add dev eth0 parent 1:1 classid 1:10 htb rate 90mbit ceil 100mbit [root]# tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10mbit ceil 100mbit [root]# tc class show dev eth0 class htb 1:11 parent 1:1 prio 0 rate 10Mbit ceil 100Mbit burst 14704b cburst 132644b class htb 1:1 root rate 100Mbit ceil 100Mbit burst 132644b cburst 132644b class htb 1:10 parent 1:1 prio 0 rate 90Mbit ceil 100Mbit burst 119545b cburst 132644b [root]# iptables -A POSTROUTING -t mangle -o eth0 -p tcp --sport 80 -j MARK --set-mark 11 [root]# iptables -t mangle -L Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination MARK tcp -- anywhere anywhere tcp spt:http MARK set 0xb [root]# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination [root]# tc filter add dev eth0 parent 1: prio 0 protocol ip handle 11 fw flowid 1:11 [root]# tc filter show dev eth0 filter parent 1: protocol ip pref 49152 fw filter parent 1: protocol ip pref 49152 fw handle 0xb classid 1:11Und wenn man alles wieder löschen will, kann man das mit folgenden Kommandos tun:
[root]# tc qdisc del dev eth0 root [root]# tc filter show dev eth0 [root]# tc class show dev eth0 [root]# tc qdisc show dev eth0 [root]#Und da noch eine Filterregel existiert, die auch noch gelöscht werden muß:
[root]# iptables -t mangle -F [root]# iptables -t mangle -L Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination [root]#
Ein weiteres Beispiel zeigt, wie man in einem Unternehmen, welches via Linux und DSL am Internet angeschlossen ist, verhindert, daß FTP Downloads die Bandbreite schlucken, sodaß es zu keinen Behinderungen kommt:
## Löschen aller Klassen für ppp0 und der Filterregeln tc qdisc del dev ppp0 root iptables -t mangle -F ## Wir aktivieren die Queueing DISCipline für ppp0 Device, die ## auf Klasse 1, Handle 12 (1:12) default-mäßig zeigt tc qdisc add dev ppp0 root handle 1:0 htb default 12 ## Nun richten wir Geschwindigkeits - Klassen ein: Zunächst die oberste, parent tc class add dev ppp0 parent 1: classid 1:1 htb rate 768kbit ceil 768kbit ## Klasse fuer kleine Pakete bis 64 Bytes (SYN/ACK, ACK) mit hoher Priorität tc class add dev ppp0 parent 1:1 classid 1:10 htb rate 68kbit ceil 100kbit prio 0 ## Klasse fuer VPN/SSH tc class add dev ppp0 parent 1:1 classid 1:11 htb rate 100kbit ceil 200kbit prio 1 ## Klasse fuer normalen Traffic tc class add dev ppp0 parent 1:1 classid 1:12 htb rate 300kbit ceil 700kbit prio 2 ## Klasse fuer Bulk tc class add dev ppp0 parent 1:1 classid 1:13 htb rate 300kbit ceil 700kbit prio 3 ## Nun der Filter für SYN/ACK, ACK Pakete iptables -A POSTROUTING -t mangle -o ppp0 -p tcp -m length --length :64 -j MARK --set-mark 10 ## Für VPN/IPsec iptables -A POSTROUTING -t mangle -o ppp0 -p 50 -j MARK --set-mark 11 ## Für SSH iptables -A POSTROUTING -t mangle -o ppp0 -p tcp --dport 22 -j MARK --set-mark 11 ## Für ausgehenden SMTP - Traffic iptables -A POSTROUTING -t mangle -o ppp0 -p tcp --dport 25 -j MARK --set-mark 13 ## Für eingehenden SMTP - Traffic iptables -A PREROUTING -t mangle -i ppp0 -p tcp --sport 25 -j MARK --set-mark 13 ## Und nun müssen die Filterregeln an die Klassen gebunden werden tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10 tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 11 fw flowid 1:11 tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 13 fw flowid 1:13 ## Und nun die Anzeige der Kernel - Parameter tc qdisc show dev ppp0 tc class show dev ppp0 tc filter show dev ppp0Die Ausgabe dieses Skriptes sollte folgendes zeigen:
qdisc htb 1: r2q 10 default 12 direct_packets_stat 0 class htb 1:11 parent 1:1 prio 1 rate 100Kbit ceil 200Kbit burst 1728b cburst 1856b class htb 1:1 root rate 768Kbit ceil 768Kbit burst 2582b cburst 2582b class htb 1:10 parent 1:1 prio 0 rate 68Kbit ceil 100Kbit burst 1686b cburst 1728b class htb 1:13 parent 1:1 prio 3 rate 300Kbit ceil 700Kbit burst 1983b cburst 2495b class htb 1:12 parent 1:1 prio 2 rate 300Kbit ceil 700Kbit burst 1983b cburst 2495b filter parent 1: protocol ip pref 49151 fw filter parent 1: protocol ip pref 49151 fw handle 0xd classid 1:13 filter parent 1: protocol ip pref 49151 fw filter parent 1: protocol ip pref 49151 fw handle 0xb classid 1:11 filter parent 1: protocol ip pref 49152 fw filter parent 1: protocol ip pref 49152 fw handle 0xa classid 1:10 Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination MARK tcp -- anywhere anywhere length 0:64 MARK set 0xa MARK ipv6-crypt-- anywhere anywhere MARK set 0xb MARK tcp -- anywhere anywhere tcp dpt:ssh MARK set 0xb MARK tcp -- anywhere anywhere tcp dpt:smtp MARK set 0xdWer detaillierte Statistiken über den Traffic im Linux Kernel benötigt, kann mit tc -s class ls dev ppp0 sich diese ausgeben lassen:
[root]# tc -s class ls dev ppp0 class htb 1:11 parent 1:1 prio 1 rate 100Kbit ceil 200Kbit burst 1728b cburst 1856b Sent 100 bytes 1 pkts (dropped 0, overlimits 0) lended: 1 borrowed: 0 giants: 0 tokens: 104448 ctokens: 56320 class htb 1:1 root rate 768Kbit ceil 768Kbit burst 2582b cburst 2582b Sent 179602 bytes 2358 pkts (dropped 0, overlimits 0) rate 4bps lended: 0 borrowed: 0 giants: 0 tokens: 21192 ctokens: 21192 class htb 1:10 parent 1:1 prio 0 rate 68Kbit ceil 100Kbit burst 1686b cburst 1728b Sent 110724 bytes 2163 pkts (dropped 0, overlimits 0) rate 3bps lended: 2163 borrowed: 0 giants: 0 tokens: 155011 ctokens: 108032 class htb 1:13 parent 1:1 prio 3 rate 300Kbit ceil 700Kbit burst 1983b cburst 2495b Sent 0 bytes 0 pkts (dropped 0, overlimits 0) lended: 0 borrowed: 0 giants: 0 tokens: 42324 ctokens: 22820 class htb 1:12 parent 1:1 prio 2 rate 300Kbit ceil 700Kbit burst 1983b cburst 2495b Sent 68778 bytes 194 pkts (dropped 0, overlimits 0) lended: 194 borrowed: 0 giants: 0 tokens: 40960 ctokens: 22236Abschließend bleibt noch zu sagen, daß mit Hilfe dieser Skripte jede beliebige Firewall nachgerüstet werden kann. Die Firewall - Regeln befinden sich in der Tabelle filter, wo sie mit den Kommandos iptables -t nat -L; iptables -t filter -L angeschaut werden können. Es ist möglich, je nach Distribution, daß beim Verändern der Filterregeln in der Firewall die Regeln in der Tabelle mangle mit verändert. In diesem Falle kommentiert man zu Beginn des Skriptes die Zeile iptables -t mangle -F einfach aus. Und damit diese QoS - Regeln reboot - fest sind, kann man diese entweder komplett in die Datei /etc/rc.local kopieren, oder aus /etc/rc.local ein weiteres Skript aufrufen lassen, welches diese Regeln enthält.
Weitere Dokumentation findet sich unter www.lartc.org und HTB Anleitung.
| Zurück | Inhaltsangabe | Weiter |
| Linux als Firewall fürs Internet | Nach oben | Bandbreiten messen |