[OpenBSD]

[Zurück: Anker] [Inhalt] [Weiter: Adress-Pools und Load Balancing]

PF: Paket-Queueing und Priorisierung


Inhaltsverzeichnis


Queueing

Etwas einzureihen heißt, es in Reihe aufzubewahren, während es darauf wartet, verarbeitet zu werden. Wenn Daten-Pakete in einem Computer-Netzwerk von einem Host ausgesendet werden, treten sie eine Warteschlange ein, wo sie darauf warten, vom Betriebssystem verarbeitet zu werden. Das Betriebssystem entscheidet dann, welche Warteschlange und welche(e) Paket(e) von der Warteschlange verarbeitet werden sollten. Die Reihenfolge, in der das Betriebssystem die zu verarbeitenden Pakete auswählt, kann die Leistung vom Netzwerk beeinflussen. Stell dir zum Beispiel vor, ein Benutzer lässt zwei Netzwerk-Anwendungen laufen: SSH und FTP. Idealerweise sollten die SSH-Pakete vor den FTP-Paketen wegen der Zeit-sensiblen Natur von SSH verarbeitet werden; wenn eine Taste im SSH-Client gedrückt wird, wird eine unverzügliche Antwort erwartet, aber wenn eine FTP-Übertraung um ein paar Sekunden verzögert wird, wird es wohl kaum auffallen. Aber was passiert, wenn der Router, der diese Verbindungen handhabt, eine große Portion an Paketen von der FTP-Verbindung verarbeitet, bevor die SSH-Verbindung verarbeitet wird? Pakete von der SSH-Verbindung werden in der Warteschlange verweilen (oder vielleicht sogar vom Router fallengelassen, wenn die Warteschlange nicht groß genug ist, um alle Pakete zu beinhalten) und die SSH-Sitzung wirkt, als wenn sie ,laggt' oder verlangsamt ist. Durch das Modifizieren der Warteschlangen-Strategie, die verwendet wird, kann Netzwerk-Bandbreite gerecht zwischen unterschiedlichen Applikationen, Benutzern und Computern aufgeteilt werden.

Bedenke, dass das Einreihen nur nützlich für Pakete in die ausgehende Richtung ist. Sobald ein Paket auf dem Interface in einer eingehenden Richtung ankommt, ist es bereits zu spät, dieses einzureihen - es hat bereits Netzwerk-Bandbreite verbraucht, um auf dem Interface anzukommen, das es aufgenommen hat. Die einzige Lösung ist, das Einreihen auf dem angrenzenden Router zu aktivieren oder, wenn der Host, der das Paket erhalten hat, als Router fungiert, das Einreihen auf dem internen Interface zu aktiveren, von dem Pakete den Router verlassen.

Schedulers

Der ,scheduler' ist, wer entscheidet, welche Warteschlange verarbeitet werden soll und in welcher Reihenfolge. Standardmäßig verwendet OpenBSD einen ,First In First Out'- (FIFO) ,scheduler'. Eine FIFO-Warteschlange funktioniert wie das Anreihen an einer Kasse in einem Supermarkt - das erste Objekt in der Schlange wird zuerst verarbeitet. Wenn neue Pakete ankommen, werden sie an das Ende der Warteschlange angehängt. Wenn die Warteschlange voll wird, und hier endet die Analogie mit dem Supermarkt, werden neu ankommende Pakete fallen gelassen. Dies ist bekannt als ,tail-drop'.

OpenBSD unterstützt zwei zusätzliche ,scheduler':

Class Based Queueing

,Class Based Queueing' (CBQ) ist ein Einreihe-Algorithmus, der die Bandbreite einer Netzwerkverbindung auf mehrere Warteschlangen oder Klassen aufteilt. Jeder Warteschlange wird Verkehr zugewiesen, basierend auf der Quell- oder Ziel-Adresse, Port-Nummer, Protokoll etc. Eine Warteschlange kann optional so konfiguriert werden, dass Bandbreite von seiner Eltern-Warteschlange ausgeliehen wird, wenn diese nicht voll ausgenutzt wird. Warteschlangen geben außerdem eine Priorität, sodass jene, die interaktiven Verkehr beinhalten, zum Beispiel SSH, ihre Pakete vor denen verarbeiten können, die ,bulk'-Verkehr, wie zum Beispiel FTP, beinhalten.

CBQ-Warteschlangen werden in einer hierarchischen Manier angeordnet. An oberster Stelle dieser Hierarchie ist die root-Warteschlange, welche die Gesamtgröße der verfügbaren Bandbreite angibt. ,Child'-Warteschlangen werden unter der root-Warteschlange angelegt, der jeder ein Teil der Bandbreite der root-Warteschlange zugewiesen werden kann. Zum Beispiel können Warteschlangen wie folgt definiert werden:

Root-Warteschlange (2 Mbps)
Warteschlange A (1 Mbps)
Warteschlange B (500 Kbps)
Warteschlange C (500 Kbps)

In diesem Fall wird die gesamt verfügbare Bandbreite auf 2 Megabits pro Sekunde (Mbps) gesetzt. Diese Bandbreite wird dann auf drei ,child'-Warteschlangen aufgeteilt.

Die Hierarchie kann weiter aufgegliedert werden, indem Warteschlangen in Warteschlangen definiert werden. Um die Bandbreite auf mehrere verschiedene Benutzer gleich aufzuteilen und ebenfalls ihren Verkehr zu klassifizieren, sodass bestimmte Protokolle anderen nicht Bandbreite wegnehmen, kann eine Warteschlangen-Struktur wie diese definiert werden:

Root-Warteschlange (2 Mbps)
BenutzerA (1 Mbps)
ssh (50 Kbps)
bulk (950 Kbps)
BenutzerB (1 Mbps)
audio (250 Kbps)
bulk (750 Kbps)
http (100 Kbps)
andere (650 Kbps)

Bedenke, dass die Summe der Bandbreite für jedes Level nicht höher ist, als was der Eltern-Warteschlange zugewiesen wurde.

Eine Warteschlange kann konfiguriert werden, um Bandbreite von seinen Eltern zu leihen, wenn die Eltern genügend Bandbreite zur Verfügung haben, wenn die ,child'-Warteschlangen diesen nicht verwenden. Siehe dir eine Warteschlangen-Einrichtung wie die folgende an:

Root-Warteschlange (2 Mbps)
BenutzerA (1 Mbps)
ssh (100 Kbps)
ftp (900 Kbps, leihen)
BenutzerB (1 Mbps)

Wenn Verkehr in der ftp-Warteschlange größer ist als 900 Kbps und Verkehr in der BenutzerA-Queue kleiner ist als 1 Mbps (weil die ssh-Warteschlange weniger als die zugewiesenen 100 Kbps verwendet), wird sich die ftp-Warteschlange die zusätzliche Bandbreite von BenutzerA ausleihen. Auf diesem Weg ist die ftp-Warteschlange in der Lage, mehr Bandbreite zu nutzen, als ihr zugewiesen wurde, wenn eine Überladung stattfindet. Wenn die ssh-Warteschlange nun ihre Last erhöht, wird die geliehene Bandbreite zurückgegeben.

CBQ weist jeder Warteschlange ein Prioritäts-Level zu. Warteschlangen mit einer höheren Priorität werden während der Anhäufung gegenüber den Warteschlangen mit einer geringen Priorität bevorzugt, so lange beide Warteschlangen die gleichen Eltern-Warteschlange haben (mit anderen Worten, so lange beide Warteschlangen im gleichen Zweig der Hierarchie sind). Warteschlangen mit der gleichen Priorität werden in einer ,round-robin'-Manier verarbeitet. Zum Beispiel:

Root-Warteschlange (2 Mbps)
BenutzerA (1 Mbps, Priorität 1)
ssh (100 Kbps, Priorität 5)
ftp (900 Kbps, Priorität 3)
BenutzerB (1 Mbps, Priorität 1)

CBQ wird die BenutzerA- und BenutzerB-Warteschlangen in einer ,round-robin'-Manier verarbeiten - keine Warteschlange wird der anderen bevorzugt. Während der Zeit, in der die BenutzerA-Warteschlange verarbeitet wird, wird CBQ ebenfalls die ,child'-Warteschlangen verarbeiten. In diesem Fall hat die ssh-Warteschlange eine höhere Priorität und wird gegenüber der ftp-Warteschlange somit bevorzugt behandelt, wenn das Netzwerk überladen ist. Bedenke, wie die ssh- und ftp-Warteschlangen ihre Prioritäten nicht mit den BenutzerA- und BenutzerB-Warteschlangen vergleichen, weil sie sich nicht auf dem gleichen Ast in der Hierarchie befinden.

Für eine detaillierte Betrachtung der Theorie hinter CBQ, siehe bitte Reference on CBQ.

Priority Queueing

,Priority Queuing' (PRIQ) weist mehreren Warteschlangen einem Interface zu, wobei jeder Warteschlange ein Prioritätslevel gegeben wird. Eine Warteschlange mit einer höheren Priorität wird immer vor einer Warteschlange mit einer geringeren Priorität verarbeitet. Wenn zwei oder noch mehr Schlangen auf gleichem Prioritätenlevel liegen, dann werden die Schlangen nach und nach abgearbeitet (in der so genannten Round-Robin-Manier).

Die Einreihe-Struktur in PRIQ ist flach - du kannst keine Warteschlangen in Warteschlangen definieren. Die root-Warteschlange, welche die Gesamtgröße der Bandbreite angibt, wird definiert und Unterwarteschlangen werden unter root definiert. Betrachte folgendes Beispiel:

Root-Warteschlange (2 Mbps)
Warteschlange A (Priorität 1)
Warteschlange B (Priorität 2)
Warteschlange C (Priorität 3)

Die root-Warteschlange wurde so definiert, dass ihr 2 Mbps der Bandbreite zur Verfügung stehen und drei Unterwarteschlangen wurden definiert. Die Warteschlange mit der höchsten Priorität (die höchste Prioritätennummer) wird zuerst bedient. Sobald alle Pakete in der Warteschlange verarbeitet wurden, oder wenn festgestellt wird, dass die Warteschlange leer ist, wird PRIQ zur nächsten Warteschlange mit der nächst höchsten Priorität gehen. Innerhalb einer gegebenen Warteschlange werden Pakete in einer ,First in First Out'- (FIFO) Manier verarbeitet.

Es ist wichtig, daran zu denken, dass du, wenn PRIQ verwendet wird, deine Warteschlangen sehr sorgfältig planen musst. Weil PRIQ immer eine höher priorisierte Warteschlange vor einer niedrigeren verarbeitet, ist es möglich für eine höher priorisierte Warteschlange, dazu zu führen, dass Pakete einer niedriger priorisierten Warteschlange verzögert oder fallen gelassen werden, wenn die höher priorisierte Warteschlange einen konstanten Fluss an Paketen erhält.

Random Early Detection

,Random Early Detection' (RED) ist ein Anhäufungg-vermeidender Algorithmus. Seine Aufgabe ist, Netzwerk-Anhäufungen zu vermeiden, indem sichergestellt wird, dass die Warteschlange nicht voll wird. Er macht das, indem durchgehend die durchschnittliche Länge (Größe) der Warteschlange berechnet wird und vergleicht sie mit zwei ,tresholds', einem minimalem ,treshold' und einem maximalen ,treshold'. Wenn die durchschnittliche Größe unterhalb des minimalem ,treshold' liegt, dann wird kein Paket fallen gelassen. Wenn der Durchschnitt oberhalb des maximalen ,tresholds' iegt, dann werden alle neu ankommenden Pakete fallengelassen. Wenn der Durchschnitt zwischen den ,treshold'-Werten liegt, dann werden Pakete basierend auf einer errechneten Wahrscheinlichkeit der durchschnittlichen Warteschlangen-Größe fallengelassen. Mit anderen Worten, je größer die durchschnittliche Warteschlangen-Größe wird, umso mehr Pakete werden fallengelassen. Wenn Pakete fallengelassen werden, wählt RED zufällig, von welchen Verbindungen Pakete fallengelassen werden sollen. Verbindungen, die mehr Bandbreite verwenden, haben eine höher Priorität beim Fallenlassen ihrer Pakete.

RED ist nützlich, da es eine Situation verhindert, die als globale Synchronisation bekannt ist, und ist in der Lage, das Anstürmen von Verkehr in Einklang zu bringen. Globale Synchronisation verweist auf den Verlust des gesamten Durchsatzes, weil Pakete von vielen Verbindungen zur gleichen Zeit fallengelassen werden. Wenn zum Beispiel eine Anhäufung auf einem Router eintritt, der den Verkehr für 10 FTP-Verbindungen trägt und Pakete von allen (oder fast allen) dieser Verbindungen fallengelassen werden (wie es der Fall in FIFO-Warteschlangen ist), wird der gesamte Durchsatz drastisch fallen. Dies ist keine ideale Situation, da es dazu führt, dass alle FTP-Verbindungen ihren Durchsatz reduzieren und das dann bedeutet, dass das Netzwerk nicht mehr länger völlig ausgereizt wird. RED verhindert dies, indem die Verbindung, von der Pakete fallengelassen werden sollen, zufällig auswählt, statt alle dafür auszuwählen. Verbindungen, die sehr viel der Bandbreite in Anspruch nehmen, werden wahrscheinlicher Pakete durch das Fallenlassen genommen. Auf diesem Weg werden Verbindungen mit hoher Bandbreite gedrosselt, Anhäufung wird verhindert und das rapide reduzieren des gesamten Durchsatzes wird nicht eintreten. Zusätzlich ist RED in der Lage, das Anstürmen von Verkehr handzuhaben, da er beginnt, Pakete fallenzulassen, bevor die Warteschlange voll wird. Wenn ein Ansturm an Verkehr durchkommt, wird dort genug Platz in der Warteschlange sein, um die neuen Pakete zu halten.

RED sollte nur benutzt werden, wenn das Transport-Protokoll in der Lage ist, auf Anhäufungs-Anzeichen vom Netzwerk zu antworten. In den meisten Fällen bedeutet das, dass RED nur in einer Warteschlange für TCP-Verkehr und nicht für UDP- oder ICMP-Verkehr genutzt werden sollte.

Für einen detaillierteren Blick auf die Theorie hinter RED, siehe bitte References on RED.

Explicit Congestion Notification

,Explicit Congestion Notification' (ECN) funktioniert in Verbindung mit RED, um zwei Hosts, die über ein Netzwerk miteinander kommunizieren, über Anhäufungen auf dem Verbindungsweg zu informieren. Es macht dies, indem RED aktiviert wird, um ein Flag im Paket-Header zu setzen, statt das Paket fallenzulassen. Angenommen, der sendende Host hat Unterstützung für ECN, dann kann er das Flag lesen und den Netzwerkverkehr dementsprechend drosseln.

Für weitere Informationen über ECN, lies bitte RFC 3168.

Queueing konfigurieren

Seit OpenBSD 3.0 ist die ,Alternate Queueing'- (ALTQ) Implementation Teil des Basis-Systems. Beginnend mit OpenBSD 3.3 wurde ALTQ in PF integriert. OpenBSDs ALTQ-Implementation unterstützt ,Class Based Queueing'- (CBQ) und ,Priority Queueing'- (PRIQ) ,schedulers'. Es unterstützt ebenfalls ,Random Early Detection' (RED) und ,Explicit Congestion Notification' (ECN).

Weil ALTQ mit PF verbunden wurde, muss PF aktiviert werden, damit ,queueing' funktioniert. Anweisungen, wie man PF aktiviert, können in den Ersten Schritten gefunden werden.

,Queueing' wird in pf.conf konfiguriert. Dort gibt es zwei Arten an Direktiven, die genutzt werden, um ,queueing' zu konfigurieren.

Die Syntax für die altq on-Direktive ist:

altq on interface scheduler bandwidth bw qlimit qlim \
   tbrsize size queue { queue_list }

Zum Beispiel:

altq on fxp0 cbq bandwidth 2Mb queue { std, ssh, ftp }
Dies aktiviert CBQ auf dem fxp0-Interface. Die gesamte verfügbare Bandbreite wird auf 2 Mbps gesetzt. Drei ,child'-Warteschlangen werden definiert: std, ssh und ftp.

Die Syntax für die queue-Direktive ist:

queue name [on interface] bandwidth bw [priority pri] [qlimit qlim] \
   scheduler ( sched_options ) { queue_list }

Das oben angegebene Beispiel weiterführend:

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)

Hier werden die Parameter der zuvor definierten ,child'-Warteschlangen gesetzt. Der std-Warteschlange wird eine Bandbreite von 50% der Bandbreite der root-Warteschlange (oder 1 Mbps) zugewiesen und als standardmäßige Warteschlange definiert. Der ssh-Warteschlange werden 25% der Bandbreite der ,root'-Warteschlange (500kb) zugewiesen und beinhaltet ebenfalls zwei ,child'-Warteschlangen, ssh_login und ssh_bulk. Der ssh_login-Warteschlange wird eine höhere Priorität als ssh_bulk gegeben und für beide ist ECN aktiv. Der ftp-Warteschlange wird eine Bandbreite von 500 Kbps zugewiesen und eine Priorität von 3. Sie kann ebenfalls Bandbreite leihen, wenn weitere verfügbar ist, und hat RED aktiviert.

HINWEIS: Jede ,child'-Warteschlange hat ihre eigene Bandbreite angegeben. Ohne Angabe der Bandbreite wird PF der Warteschlange 100% der Bandbreite der Eltern-Warteschlange zuweisen. In diesem Fall wird dies einen Fehler verursachen, wenn die Regeln geladen werden, da, falls eine Warteschlange existiert, die 100% der Bandbreite nutzt, keine weitere Warteschlange auf diesem Level angegeben werden kann, da keine weitere Bandbreite genutzt werden kann.

Verkehr einer ,Queue' zuweisen

Um Verkehr einer Warteschlange zuzuweisen, wird das queue-Schlüsselwort in Verbindung mit PFs Filterregeln verwendet. Siehe dir zum Beispiel einen Satz an Filterregeln an, der eine Zeile wie folgende beinhaltet:

pass out on fxp0 from any to any port 22

Pakete, die zu dieser Regel zutreffen, können einer bestimmten Warteschlange zugewiesen werden, unter Verwendung des queue-Schlüsselworts:

pass out on fxp0 from any to any port 22 queue ssh

Wenn das queue-Schlüsselwort mit block-Direktiven verwendet wird, werden jegliche resultierende ,TCP RST'- oder ,ICMP Unreachable'-Pakete dieser angegebenen Warteschlange zugewiesen.

Bedenke, dass das Bestimmen der Warteschlangen auf einem anderen Interface stattfinden kann als auf dem, auf dem die altq on-Direktive angegeben wurde:

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

,Queueing' wird auf fxp0 aktiviert, aber das Markieren findet auf dc0 statt. Wenn Pakete, die mit dieser pass-Regel übereinstimmten, vom Interface fxp0 aus hinausgehen, werden sie in der ftp-Warteschlange eingereiht. Diese Art von ,queueing' kann auf Routern sehr nützlich sein.

Normalerweise wird nur ein Warteschlangen-Name mit dem queue-Schlüsselwort angegeben, aber wenn ein zweiter Name angegeben wurde, dann wird diese Warteschlange für Pakete mit einem Type of Service (ToS) von ,low-delay' und für ,TCP ACK'-Pakete mit keinem Daten-,payload' verwendet. Ein gutes Beispiel hierfür kann in der Verwendung von SSH gefunden werden. SSH-Login-Sitzungen werden das ToS auf ,low-delay' setzen, während SCP- und SFTP-Sitzungen das nicht machen. PF kann diese Information verwenden, um Warteschlangen-Pakete, die zu einer Login-Verbindung gehören, in eine andere Warteschlange zu stecken, als sie für Nicht-Login-Verbindungen genutzt werden. Dies kann nützlich sein, um Login-Verbindungspakete gegenüber Dateitransfer-Paketen zu bevorzugen.

pass out on fxp0 from any to any port 22 queue(ssh_bulk, ssh_login)

Dies weist Pakete, die zu einer SSH-Login-Sitzung gehören, zu der ssh_login-Warteschlange zu und Pakete, die zu SCP- und SFTP-Sitzungen gehören, zu der ssh_bulk-Warteschlange. SSH-Login-Verbindungen werden dann ihre Pakete früher verarbeitet bekommen als SCP- und SFTP-Verbindungen, da die ssh_login-Warteschlange eine höhere Priorität hat.

,TCP ACK'-Pakete einer höher priorisierten Warteschlange hinzuzufügen ist sinnvoll, wenn man asymmetrische Verbindungen hat, das heißt, Verbindungen, die eine andere Upload- als Download-Bandbreite haben, wie zum Beispiel ADSL-Verbindungen. Wenn bei einer ADSL-Verbindung der Upload-Kanal ausgereizt ist und ein Download gestartet wird, wird der Download benachteiligt, da die ,TCP ACK'-Pakete, die gesendet werden müssen, in eine Anhäufung geraten, wenn sie durch den Upload-Kanal gelangen wollen. Tests haben gezeigt, dass das beste Resultat erzielt werden kann, wenn die Bandbreite für die Upload-Warteschlange auf einen kleineren Wert gesetzt wird, als die Verbindung hergeben könnte. Wenn zum Beispiel eine ADSL-Verbindung einen maximalen Upload von 640 Kbps hat, wird das Setzen von bandwith der root-Warteschlange auf einen Wert wie zum Beispiel 600 Kb bessere Leistung erbringen. Versuch und Irrtum werden die beste bandwith-Einstellung liefern.

Wenn das queue-Schlüsselwort mit Regeln genutzt wird, die keep state beinhalten, wie zum Beispiel:

pass in on fxp0 proto tcp from any to any port 22 flags S/SA \
   keep state queue ssh

wird PF die Warteschlange in dem ,state'-Tabelleneintrag halten, so dass Pakete, die zurück durch fxp0 kommen und mit der ,stateful' Verbindung übereinstimmen, in der ssh-Warteschlange enden. Bedenke, dass, obwohl das queue-Schlüsselwort mit einem Regelfilter für eingehenden Verkehr genutzt wird, das Ziel das Angeben einer Warteschlange für korrespondierenden ausgehenden Verkehr ist; die oben angegebene Regel reiht keine eingehenden Pakete ein.

Beispiel #1: kleines, Heim-Netzwerk

[ Alice ] [ Charlie ] | | ADSL ---+-----+-------+------ dc0 [ OpenBSD ] fxp0 -------- ( Internet ) | [ Bob ]

In diesem Beispiel wird OpenBSD auf einem Internet-Gateway für ein kleines Heim-Netzwerk mit drei Workstations verwendet. Das Gateway führt das Filtern von Paketen und NAT-Dienste aus. Die Internetverbindung ist ein ADSL-Anschluss, der mit 2 Mbps ,down' und 640 Kbps ,up' läuft.

Die ,queueing'-Richtlinie für dieses Netzwerk:

Weiter unten ist der Regelsatz, der dieser Netzwerk-Richtlinie entspricht. Bedenke, dass nur die pf.conf-Direktiven, die direkt für diese Richtlinie gelten, vorhanden sind; nat, rdr, Optionen etc. werden nicht gezeigt.

# aktiviere ,queueing' auf dem externen interface, um den verkehr, der # zum internet geht, zu kontrollieren. verwende den priq-,scheduler', # um nur prioritäten zu kontrollieren. setze die bandbreite auf 610 kbps, # um die beste leistung aus der ,tcp ack'-warteschlange zu bekommen. altq on fxp0 priq bandwidth 610Kb queue { std_out, ssh_im_out, dns_out, \ tcp_ack_out } # definiere die parameter für die ,child'-warteschlangen. # std_out - die standard-warteschlange. jegliche filterregel weiter # unten, die nicht explizit eine warteschlange angibt, # wird ihren verkehr zu dieser warteschlange hinzufügen. # ssh_im_out - interaktiver SSH- und etlicher ,instant message'-verkehr. # dns_out - DNS-anfragen. # tcp_ack_out - ,TCP ACK'-pakete mit keinem daten-,payload'. queue std_out priq(default) queue ssh_im_out priority 4 priq(red) queue dns_out priority 5 queue tcp_ack_out priority 6 # aktivere ,queueing' auf dem internen interface, um den verkehr zu # kontrollieren, der vom internet kommt. verwende den cbq-,scheduler' um # die bandbreite zu kontrollieren. max bandbreite ist 2 Mbps. altq on dc0 cbq bandwidth 2Mb queue { std_in, ssh_im_in, dns_in, bob_in } # definiere die parameter für die ,child'-warteschlangen. # std_in - die standard-warteschlange. jegliche filterregel weiter # unten, die nicht explizit eine warteschlange angibt, # wird ihren verkehr zu dieser warteschlange hinzufügen. # ssh_im_in - interaktiver SSH- und etlicher ,instant message'-verkehr. # dns_in - DNS-antworten. # bob_in - für bobs workstation reservierte bandbreite. erlaube ihm, # zu leihen. 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) # ... in der filter-sektion von 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 }" # filterregeln für fxp0-eingang block in on fxp0 all # filterregeln für fxp0-ausgang 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) # filterregeln für dc0-eingang block in on dc0 all pass in on dc0 from $local_net # filterregeln für dc0-ausgang 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

Beispiel #2: Firmen-Netzwerk

( IT Abt ) [ PC vom Chef ] | | T1 --+----+-----+---------- dc0 [ OpenBSD ] fxp0 -------- ( Internet ) | fxp1 [ COMP1 ] [ WWW ] / | / --+----------'

In diesem Beispiel fungiert der OpenBSD-Host als eine Firewall für ein Firmen-Netzwerk. Die Firma betreibt einen WWW-Server in dem DMZ-Bereich ihres Netzwerks, in dem Kunden ihre Webseiten per FTP hochladen können. Die IT-Abteilung hat ihr eigenes Subnetz zum Haupt-Netzwerk verbunden und der Chef hat einen PC auf seinem Schreibtisch, der für E-Mails und zum Surfen im Web verwendet wird. Die Verbindung zum Internet ist über einen T1-Anschluss realisiert, der mit 1.5 Mbps in beide Richtungen läuft. Alle anderen Netzwerksegmente verwenden Fast Ethernet (100 Mbps).

Der Netzwerkadministrator hat sich für die folgende Richtlinie entschieden:

Weiter unten ist der Regelsatz, der dieser Netzwerk-Richtlinie entspricht. Bedenke, dass nur die pf.conf-Direktiven, die direkt für diese Richtlinie gelten, vorhanden sind; nat, rdr, Optionen etc. werden nicht gezeigt.

# aktiviere ,queueing' auf dem externen interface um pakete einzureihen, # die ins internet hinaus gehen. verwende den ,cbq'-scheduler, sodass die # bandbreite, die für jede warteschlange genutzt wird, kontrolliert werden # kann. die max ausgehende bandbreite ist 1,5 Mbps. altq on fxp0 cbq bandwidth 1.5Mb queue { std_ext, www_ext, boss_ext } # definiere die parameter für die ,child'-warteschlangen. # std_ext - die standard-warteschlange. ebenfalls die # standardmäßige warteschlange für ausgehenden verkehr # auf fxp0. # www_ext - container-warteschlange für WWW-server-warteschlangen. # begrenzt für 500 Kbps. # www_ext_http - http-verkehr von dem WWW-server; höhere priorität. # www_ext_misc - jeder nicht-http-verkehr von dem WWW-server. # boss_ext - verkehr, der vom computer des chefs kommt. 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) # aktiviere ,queueing' auf dem internen interface, um verkehr zu # kontrollieren, der vom internet oder der DMZ kommt. verwende # den cbq-,scheduler' um die bandbreite für jede warteschlange zu # kontrollieren. bandbreite auf diesem interface ist auf das maximum # gesetzt. verkehr, der von der dmz kommt, wird in der lage sein, # die gesamte bandbreite zu nutzen, während verkehr, der vom internet # kommt, auf 1,0 Mbps (wegen 0,5 Mbps (500 Kbps) für fxp1 zugewiesen # wird) begrenzt wird. altq on dc0 cbq bandwidth 100% queue { net_int, www_int } # definiere die parameter für die ,child'-warteschlangen. # net_int - container-warteschlange für verkehr vom internet. # bandbreite ist 1,0 Mbps. # std_int - die standard-warteschlange. ebenfalls die # standard-warteschlange für ausgehenden verkehr auf dc0. # it_int - verkehr zum it-abt-netzwerk; reserviere ihnen 500 Kbps. # boss_int - verkehr zum PC des chefs, eine höhere Priorität zuweisen # www_int - verkehr vom WWW-server in die DMZ; volle Geschwindigkeit. 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) # aktivere ,queueing' auf dem DMZ-interface, um den verkehr, der für # den WWW-server bestimmt ist, zu kontrollieren. cbq wird auf diesem # interface verwendet, da detaillierte kontrolle der bandbreite notwendig # ist. bandbreite auf diesem interface ist auf das maximum gesetzt. # verkehr vom internen netzwerk wird in der lage sein, alles dieser # bandbreite nutzen zu können, während verkehr vom internet auf 500 Kbps # begrenzt wird. altq on fxp1 cbq bandwidth 100% queue { internal_dmz, net_dmz } # definiere die parameter für die ,child'-warteschlangen. # internal_dmz - verkehr vom internen netzwerk. # net_dmz - container-warteschlange für den verkehr vom internet. # net_dmz_http - http verkehr; höhere Priorität. # net_dmz_misc - der gesamte nicht-http-verkehr. dies ist ebenfalls die # standardmäßige warteschlange. 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) # ... in der filter-sektion von 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" # standardmäßiges blocken block on { fxp0, fxp1, dc0 } all # filterregeln für fxp0-eingang 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 # filterregeln für fxp0-ausgang pass out on fxp0 from $int_nets to any keep state pass out on fxp0 from $boss to any keep state queue boss_ext # filterregeln für dc0-eingang 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 # filterregeln für dc0-ausgang pass out on dc0 from dc0 to $int_nets # filterregeln für fxp1-eingang pass in on fxp1 proto { tcp, udp } from $wwwserv to any port 53 \ keep state # filterregeln für fxp1-ausgang 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

[Zurück: Anker] [Inhalt] [Weiter: Adress-Pools und Load Balancing]


[zurück] www@openbsd.org
$OpenBSD: queueing.html,v 1.25 2007/11/12 20:29:59 saad Exp $