pf + altq

hirnsaege

Member
Hallo miteinander!

In meiner WG teilen wir uns eine Internetleitung mit 2048/256.
Ich habe mich bereiterklärt einen Router aufzusetzen der gleichzeitig als Torrent-Box fungieren soll.

Soweit läuft das auch alles, die Platten sind mit GELI verschlüsselt, gebootet wird über einen USB Stick, NAT läuft auch, ich konnte also schon so einiges aus dem Projekt lernen.

Das Problem ist nun, dass der Router die Clients komplett ausbremst wenn Downloads laufen, ist ja auch irgendwie naheliegend. Also hab ich die Firewall von ipf auf pf umgestellt, um ALTQ verwenden zu können.

Das Ziel ist jetzt, jedem User und dem Router/Server bei voller Auslastung den gleichen Anteil an der Bandbreite zur Verfügung zu stellen. Ich möchte aber auch, dass, sollte die Leitung nicht ausgenutzt werden, im Extremfall bspw. ein User die volle Bandbreite beanspruchen kann.

Webbrowsing soll die höchste Priorität kriegen, dann die default queue jedes Users (für Instant Messenger o.ä.) und zuletzt eine kleine Range hoher Ports für Downloadprogramme o.ä.

Irgendwie steh ich jetzt auf der Leitung.

Hier erstmal meine pf.conf, ath0 is das LAN Interface, fxp0 hängt am Modem:
Ich hab rio beinahe für jede queue genommen, in der Hoffnung dass das bei so wenigen Clients keine negativen Auswirkungen auf die Performance haben wird..?

Code:
## ALTQ - Queues
	# outbound
altq on ath0 cbq bandwidth 2048Kb queue { server_in, user1, user2, user3, default_in }
	queue server_in on ath0 bandwidth 20% priority 1 cbq (borrow rio) { s_torrent, s_def }
		queue s_torrent bandwidth 50% priority 1 cbq (borrow rio)
		queue s_def bandwidth 50% priority 2 cbq (borrow)
	queue user1 on ath0 bandwidth 20% priority 1 cbq (borrow rio) { u1_http, u1_highport, u1_def }	# felix	
		queue u1_http bandwidth 33% priority 5 cbq (borrow rio)
		queue u1_highport bandwidth 33% priority 3 cbq (borrow rio)
		queue u1_def bandwidth 34% priority 4 cbq (borrow)
	queue user2 on ath0 bandwidth 20% priority 1 cbq (borrow rio) { u2_http, u2_highport, u2_def }	# robert
		queue u2_http bandwidth 33% priority 5 cbq (borrow rio)
		queue u2_highport bandwidth 33% priority 3 cbq (borrow rio)
		queue u2_def bandwidth 34% priority 4 cbq (borrow)
	queue user3 on ath0 bandwidth 20% priority 1 cbq (borrow rio) { u3_http, u3_highport, u3_def }	# thomas
		queue u3_http bandwidth 33% priority 5 cbq (borrow rio)
		queue u3_highport bandwidth 33% priority 3 cbq (borrow rio)
		queue u3_def bandwidth 34% priority 4 cbq (borrow)
	queue default_in on ath0 bandwidth 20% priority 0 cbq (borrow default)
	
	# inbound
altq on fxp0 cbq bandwidth 200Kb queue { server_out, ack_out, default_out }			# 256 k
	queue server_out bandwidth 33% priority 3 cbq (borrow rio)
	queue ack_out bandwidth 33% priority 6 cbq (borrow rio)
	queue default_out bandwidth 33% priority 4 cbq (default borrow rio)

## Nat
nat on ath0 inet from any to (fxp0) -> ath0:network
nat on fxp0 inet from ath0:network to any -> (fxp0)			#raus
	
## package filter
server = "192.168.0.1"
user1 = "192.168.0.21"
user2 = "192.168.0.20"
user3 = "192.168.0.19"
netzwerk = "192.168.0.0/24"

table <firewall> const { self }
	# loopback
pass in quick on lo0 all
pass out quick on lo0 all
set skip on lo0


# lan
	# inbound
	block in on ath0 all
	pass in on ath0 proto {tcp, udp, icmp} from $netzwerk to any
	
	#outbound
	pass out on ath0 proto { tcp, udp, icmp } from any to $server queue server_in
	pass out on ath0 proto { tcp, udp } from any to $server port 50000:50100 queue s_torrent

	pass out quick on ath0 proto { tcp, udp } from any to $user1 port { 80, 443 } queue u1_http
	pass out quick on ath0 proto { tcp, udp } from any to $user1 port 51000:51250 queue u1_highport
	pass out on ath0 proto { tcp, udp, icmp } from any to $user1 queue u1_def

	pass out quick on ath0 proto { tcp, udp } from any to $user2 port { 80, 443 } queue u2_http
	pass out quick on ath0 proto { tcp, udp } from any to $user2 port 51251:51500 queue u2_highport
	pass out on ath0 proto { tcp, udp, icmp } from any to $user2 queue u2_def

	pass out quick on ath0 proto { tcp, udp } from any to $user3 port { 80, 443 } queue u3_http
	pass out quick on ath0 proto { tcp, udp } from any to $user3 port 51501:51750 queue u3_highport
	pass out on ath0 proto { tcp, udp, icmp } from any to $user3 queue u3_def
	
# internet
	# inbound
	pass in on fxp0 all  		# for testing purposes
	
	#outbound
	pass out quick on fxp0 proto { tcp, udp, icmp } from $server to any queue server_out
	pass out quick on fxp0 proto tcp from $netzwerk to any flags S/SA queue ack_out
	pass out on fxp0 proto { tcp, udp, icmp } from $netzwerk to any queue default_out

So, der Teil, den ich nicht verstehe, ist, wieso der ganze Traffic, wurscht ob In oder Out durch die jeweilige default queue geht.

Ich hab das Gefühl das ganze hängt mit dem NAT zusammen, aber ich weiß diesbezüglich nicht mehr weiter...

Für Anregungen wär ich sehr dankbar.

Achja: Hier läuft FreeBSD 7.1-Stable
 
Zuletzt bearbeitet:
Hey,
ich finde dein Posting gerade etwas Lustig. Habe gestern genau das gleiche Problem gehabt und den ganzen Tag damit verbracht es zu lösen. Ebenfalls für den WG-Server. :-)
Ich bin gestern zu folgender Lösung gekommen.

Alle Regeln die AltQ betreffen, müssen in deinem Fall auf pass in on ath0 konfiguriert werden, da Pf seit einiger Zeit automatisch "keep state" verwendet, wenn du das nicht willst musst du es explizit abschalten.
Mit Keep state wird, wenn das erste Paket einer TCP-Verbindung von deinem Lan reinkommt und passieren darf, eine Verbindung erstellt und die weiteren Pakete dieser Verbindung durchlaufen die Regeln nicht mehr sondern werden sofort durchgelassen.

Hier das entsprechende Zitat aus der OpenBSD pf FAQ
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.

Wünsche dir viel Spaß beim rumprobieren, ich hab auch ne Menge gelernt während der Sache
 
Ich war immer der Ansicht, mit altq könne man nur ausgehende Pakete priorisieren?

Hat das mit dieser Passage aus der pf.conf zu tun? Ich find das etwas verwirrend:

Note that queue designation can happen on an interface other than the one defined in the altq on directive:

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 is enabled on fxp0 but the designation takes place on dc0. If packets matching the pass rule exit from
interface fxp0, they will be queued in the ftp queue. This type of queueing can be very useful on routers.
 
Ich muss mich nochmal korrigieren:
Die Internet Outbound queues sind richtig, nur deine LAN Outbound queues musst du unter LAN inbound implementieren.

Has du pftop installiert?
Ich bin gestern durch Zufall darauf gestoßen, ist für Diagnosezwecke genial.
Dort kannst du übersichtlich sehen wie viel Traffic über welche Queues läuft.
 
Die von dir zitierte Passage finde ich auch verwirrend.
Auch in der Deutschen pf-FAQ wird das nicht deutlicher beschrieben.

Ja ALTQ kann man nur auf ausgehende Pakete anwenden, aber es werden die Ausgangsregeln in den meisten Fällen von deinem Paket gar nicht ausgewertet weil die Clients eine Verbindung beginnen und einen state erzeugen. Alle Pakete die zu diesem State gehören, also auch die Pakete Router->Client werden nicht mehr in überprüft und dürfen uneingeschränkt passieren.
pass in ... queue schickt keine input Pakete in die Warteschlange, es sagt der Firewall lediglich, dass du möchtest, dass wenn ein state erstellt wird, die ausgehenden Pakete die zu diesem State gehören über die Queue laufen sollen.

Diese FAQ ist recht informativ: http://www.openbsd.org/faq/pf/de/filter.html
 
Also pftop funktioniert sehr gut, danke für den Tip.

Die downstream queues über pass in ath0... zu definieren hat auch gut funktioniert, zumindest für die clients.

Ich bin draufgekommen, dass es ja garkeinen Sinn macht die Regeln für den Server über ath0 zu definieren, da dessen Pakete dieses Interface für den Internetzugang ja garnicht passieren müssen.

Ich hab also versucht die queues für den eingehenden Datentransfer zum Server über fxp0 in zu definieren, nur frag ich mich gerade, was das bringen soll:
Die Queue für den Downstream ist ja an ath0 gebunden, doch die Pakete für den Server müssen dieses Interface, wie gesagt, garnicht passieren. Vielleicht wäre es sinnvoller das Ganze einfach über die default queue laufen zu lassen? Dann muss ich bei svn, port updates etc. den rtorrent eben ausschalten... ein workaround sozusagen
 
Also der Begriff Torrent-Box sagt mir leider nichts.
Wer soll auf diesen Server zugreifen?
Soll der von außen Anfragen entgegen nehmen, also so ne Art Webserver?
 
Mit "Torrent-Box" mein ich nur, dass der Router halt einen Torrent-Client (rtorrent) laufen hat, auf den alle Clients aus dem internen Netzwerk per rtGUI (Web-Interface über apache) zugreifen können, sodass die Workstations ausgeschaltet werden können und die Downloads trotzdem laufen, da der Router ja 24/7 an is.
Der rtorrent hat eine Port Range von 50000-50100 für Verbindungen.

Zugriffe von außen sind nicht nötig, eher kontraproduktiv..
 
Zuletzt bearbeitet:
Mir fällt gerade auf dass du ja eine asymmetrische Verbindung hast. D.H. Wenn einer deiner User große uploads macht, könnte das dein Netz unter meiner folgenden Konfig lahmen. Aber ich weiß nicht wie man das im Moment beheben könnt außer keep state zu deaktivieren, würde ich aber für schlecht halten.

Bin mir überhaupt nicht sicher ob folgendes funktioniert:

altq on fxp0 cbq bandwidth 2MB queue {u1, u2, u3, srv}
queue srv bandwidth 25% cbq{borrow, default}
queue u1 bandwidth 25% cbq{borrow}
...
...

#ath0
pass in quick netzwerk to $Server #Lokaler verkehr braucht nicht gebremst zu werden
pass in user1 to any queue u1
pass in user2 to any queue u2

#fxp0
pass out $Server to any # Zunächst alles durch lassen
pass out $Server Port $torrentports to any queue srv # Server traffic verzögern
 
Also, ich bin jetzt dank deiner Hilfe mal bei folgender Konfiguration gelandet:

Code:
user1 = "192.168.0.21"
user2 = "192.168.0.20"
user3 = "192.168.0.19"
netzwerk = "192.168.0.0/24"
u1_ports = "51000:51250"
u2_ports = "51251:51501"
u3_ports = "51502:51752"

table <firewall> const { self }

scrub in on fxp0 all

## ALTQ - Queues
	# outbound
altq on ath0 cbq bandwidth 54Mb queue { users, lan_traffic }
	queue users on ath0 bandwidth 2048Kb priority 2 cbq (rio) { user1, user2, user3, default_in_lan }
		queue user1 on ath0 bandwidth 30% priority 2 cbq (borrow rio) { u1_http, u1_highport, u1_def }	# felix	
			queue u1_http bandwidth 33% priority 5 cbq (borrow rio)
			queue u1_highport bandwidth 33% priority 3 cbq (borrow rio)
			queue u1_def bandwidth 34% priority 4 cbq (borrow)
		queue user2 on ath0 bandwidth 30% priority 2 cbq (borrow rio) { u2_http, u2_highport, u2_def }	# robert
			queue u2_http bandwidth 33% priority 5 cbq (borrow rio)
			queue u2_highport bandwidth 33% priority 3 cbq (borrow rio)
			queue u2_def bandwidth 34% priority 4 cbq (borrow)
		queue user3 on ath0 bandwidth 30% priority 2 cbq (borrow rio) { u3_http, u3_highport, u3_def }	# thomas
			queue u3_http bandwidth 33% priority 5 cbq (borrow rio)
			queue u3_highport bandwidth 33% priority 3 cbq (borrow rio)
			queue u3_def bandwidth 34% priority 4 cbq (borrow)
		queue default_in_lan on ath0 bandwidth 10% priority 1 cbq (borrow default)
	queue lan_traffic on ath0 bandwidth 50Mb priority 1 cbq (rio)
	
	# inbound
altq on fxp0 cbq bandwidth 256Kb queue { server_out, ack_out, default_out_lan }			
	queue server_out bandwidth 40% priority 3 cbq (borrow rio)
	queue ack_out bandwidth 10% priority 6 cbq (borrow rio)
	queue default_out_lan bandwidth 40% priority 4 cbq (borrow rio default)



## Nat
no nat on ath0 inet from <firewall> to any
no nat on ath0 inet from any to <firewall>
nat on ath0 inet from any to (fxp0) -> ath0:network
nat on fxp0 inet from ath0:network to any -> (fxp0)			#raus
rdr on fxp0 proto udp from any to (fxp0) port 1165 -> 192.168.0.21
rdr on fxp0 proto {tcp, udp} from any to (fxp0) port $u1_ports -> $user1

## package filter
# loopback
	pass in quick on lo0 all
	pass out quick on lo0 all
	set skip on lo0

# lan
	# inbound
	block in on ath0 all
	pass in quick on ath0 proto {tcp, udp, icmp} from $netzwerk to <firewall> queue lan_traffic
	pass in on ath0 proto {tcp, udp, icmp} from $netzwerk to any

	pass in quick on ath0 proto { tcp, udp } from $user1 to any port { 80, 443 } queue u1_http
	pass in quick on ath0 proto { tcp, udp } from $user1 port $u1_ports to any port 51000:51250 queue u1_highport
	pass in on ath0 proto { tcp, udp, icmp } from $user1 to any queue u1_def

	pass in quick on ath0 proto { tcp, udp } from $user2 to any port { 80, 443 } queue u2_http
	pass in quick on ath0 proto { tcp, udp } from $user2 to any port $u2_ports queue u2_highport
	pass in on ath0 proto { tcp, udp, icmp } from $user2 to any queue u2_def

	pass in quick on ath0 proto { tcp, udp } from $user3 to any port { 80, 443 } queue u3_http
	pass in quick on ath0 proto { tcp, udp } from $user3 to any port $u3_ports queue u3_highport
	pass in on ath0 proto { tcp, udp, icmp } from $user3 to any queue u3_def
	
	pass out quick on ath0 proto {tcp, udp, icmp} from <firewall> to $netzwerk queue lan_traffic
	
# internet
	# inbound
	pass in on fxp0 proto {tcp, udp, icmp} from any to ! <firewall>
	pass in on fxp0 proto {tcp, udp} from any to <firewall> port 50000:50100
	#outbound
	pass out quick on fxp0 proto { tcp, udp, icmp } from <firewall> to any queue (server_out, ack_out)
	pass out quick on fxp0 proto tcp from $netzwerk to any flags S/SA queue ack_out
	pass out on fxp0 proto { tcp, udp, icmp } from ! <firewall> to any queue (default_out_lan, ack_out)

Für den Downstream ins Netzwerk, also die queue über ath0, funktioniert das soweit schon prächtig. Nur die Verbindungen auf den hohen Ports bringe ich nicht dazu, zu funktionieren, deshalb sind sie in der Konfiguration auch nicht definiert. Weder inbound auf ath0 noch in- oder outbound auf fxp0... bleibt wohl eh nurmehr eine Möglichkeit übrig wenn ich so drüber nachdenke :rolleyes:
Nur eine Verständnisfrage dazu: Verbindungen auf diese Ports werden ja von außen initiiert, oder?
edit: Ich merke gerade, dass die nat/rdr Regeln im Bezug auf die hohen Ports nicht funktionieren...
Code:
rdr pass on fxp0 proto {tcp, udp} from any to (fxp0) port $u1_ports -> 192.168.0.21
müsste doch reichen, oder?

Das Traffic Shaping betrifft eben nur die Netzwerkclients, nicht den Server/Router, soweit ich pf und altq jetzt verstanden hab, ist die Lösung, die ich angestrebt habe, technisch nicht möglich. Ich kann die Bandbreite, die der rtorrent für sich beansprucht allerdings manuell drosseln, es ist zwar nicht die schönste Lösung aber scheint zu funktionieren.

Die Pipe auf ath0 habe ich vergrößert, weil das Traffic Shaping auch den internen Datenverkehr vom/zum Router ausgebremst hat.

Die Queue server_out wird zwar in Anspruch genommen, aber soweit ich das gesehen habe, läuft der Löwenanteil des Traffics für den diese Pipe bestimmt ist immer noch über default_out_lan.

Ich hab trotzdem schonmal eine mords Freude dass es so funktioniert, wie es jetzt funktioniert.
 
Zuletzt bearbeitet:
Zurück
Oben