PF Logik

locutus

Member
Hallo!

Mal ne Frage zur pf Logik, die ich scheinbar nicht verstehe. Ausgangssituation ist ein Router mit drei Interfaces (extern, intern und DMZ). Folgende Regelscheint aus irgendwelchen Gründen nicht zu funktionieren:

$ext_if = "tun0"
$web = "{ 20,21, 22, 80 }"

pass out on $ext_if inet proto tcp from $int_lan to any port $web keep state

Port 80 geht nur wenn ich folgende Regel hinzufüge:

pass out on $ext_if inet proto tcp from $ext_if to any port $web keep state

Und jetzt wird die Konfusion noch ein wenig erhöht. Wenn ich die erste Regel lösche, komme ich vom internen Lan trotzdem auf externe Webseiten. Ich habe aus der pf.conf auch bereits alle pass - Regeln ausser DNS und EMail rausgenommen, um Flüchtigkeitsfehler auszuschließen. Es stehen also ansonsten nur noch block - Regeln drin und natürlich NAT.

Kann mir jemand ein Licht anzünden, damit ich diese Logik verstehe?
 
Die Ausgabe von pfctl -qsr bringt übrigens folgendes:

scrub in on tun0 all fragment reassemble
scrub in on int_if all fragment reassemble
scrub in on dmz_if all fragment reassemble
block drop out log on tun0 all
block drop in log on tun0 all
block return-rst out log on tun0 proto tcp all
block return-rst in log on tun0 proto tcp all
block return-icmp(port-unr, port-unr) out log on tun0 proto udp all
block return-icmp(port-unr, port-unr) in log on tun0 proto udp all
block drop in quick inet6 all
block drop out quick inet6 all
block drop in log quick on tun0 inet proto tcp all flags FPU/FPU
block drop in log quick on tun0 inet proto tcp all flags FS/FSRA
block drop in log quick on tun0 inet proto tcp all flags /FSRA
block drop in log quick on tun0 inet from 127.0.0.0/8 to any
block drop in log quick on tun0 inet from 192.168.0.0/16 to any
block drop in log quick on tun0 inet from 10.0.0.0/8 to any
block drop in log quick on tun0 inet from 255.255.255.255 to any
block drop out log quick on tun0 inet from any to 127.0.0.0/8
block drop out log quick on tun0 inet from any to 192.168.0.0/16
block drop out log quick on tun0 inet from any to 10.0.0.0/8
block drop out log quick on tun0 inet from any to 255.255.255.255
block drop in quick on tun0 inet from any to 255.255.255.255
pass in quick on lo0 all
pass out quick on lo0 all
pass in quick on tun0 inet proto tcp from any to any port = smtp keep state
pass out quick on tun0 inet proto tcp from 192.168.101.10 to any port = smtp keep state
pass out on tun0 inet proto tcp from 192.168.101.10 to any port = domain keep state
pass out on tun0 inet proto udp from 192.168.101.10 to any port = domain keep state
pass out on tun0 inet proto tcp from 82.139.212.120 to any port = domain keep state
pass out on tun0 inet proto udp from 82.139.212.120 to any port = domain keep state
pass out on xl1 inet proto tcp from 192.168.100.0/24 to 192.168.101.10 port = domain keep state
pass out on xl1 inet proto udp from 192.168.100.0/24 to 192.168.101.10 port = domain keep state
pass out on tun0 inet proto tcp from 192.168.101.0/24 to any port = ftp-data keep state
pass out on tun0 inet proto tcp from 192.168.101.0/24 to any port = ftp keep state
pass out on tun0 inet proto tcp from 192.168.101.0/24 to any port = ssh keep state
pass out on tun0 inet proto tcp from 192.168.101.0/24 to any port = www keep state
pass out on tun0 inet proto tcp from **ext_ip** to any port = ftp-data keep state
pass out on tun0 inet proto tcp from **ext_ip** to any port = ftp keep state
pass out on tun0 inet proto tcp from **ext_ip** to any port = ssh keep state
pass out on tun0 inet proto tcp from **ext_ip** to any port = www keep state
 
$ext_if = "tun0"
$web = "{ 20,21, 22, 80 }"

pass out on $ext_if inet proto tcp from $int_lan to any port $web keep state

Port 80 geht nur wenn ich folgende Regel hinzufüge:

pass out on $ext_if inet proto tcp from $ext_if to any port $web keep state

Vermutlich liegt hier der Hund begraben:

und natürlich NAT.

Durch NAT werden die Pakete vor dem abarbeiten der Filterregeln übersetzt. Das heißt, alle auf $ext_if ausgehenden Pakete haben dessen IP als Quelladresse.

Gruß
Baseballbatboy
 
Wenn dem so ist, wie will ich den dann in den Regeln unterscheiden zwischen Paketen aus der DMZ und dem internen LAN?

Angenommen du willst 25 nur aus der DMZ zulassen und 80 nur aus dem internen LAN. Würde nach deiner Aussage nicht funktionieren oder?
 
Dann darfst Du eben nicht auf $ext_if filtern:

Code:
block all

# port 25 ausgehend von DMZ zulassen
pass in on $dmz_if from any to any port 25

# dmz -> intern zulassen
pass in on $dmz_if from any to $int_lan

# port 80 ausgehend vom internen Netz zulassen
pass in on $int_if from any to any port 80

# alles auf $ext_if rauslassen
pass out on $ext_if all

Gruß
Baseballbatboy
 
Oh, kleines Missverständniss. Hatte da noch die iptables im Kopf, da dort eingehende Pakete für den lokalen Prozeß da sind, außer man packt diese in die forwarding chain.

Danke!
 
Oh, kleines Missverständniss. Hatte da noch die iptables im Kopf, da dort eingehende Pakete für den lokalen Prozeß da sind, außer man packt diese in die forwarding chain.

Danke!

Das klingt für meine Ohren aber auch nicht richtig... netfilter entscheidet selbst, ob ein eingehendes Paket das System selbst oder ein anderes als Ziel hat und leitet dann dieses Paket entweder durch die INPUT Chain oder die FORWARD Chain.

Ich kann ja mal ein paar grundsätzliche Unterschiede zwischen netfilter und pf aufzählen:

* netfilter pflegt bei aktiviertem connection tracking permanent einen globalen state-table für den kompletten Netzwerkverkehr (auslesbar via cat /proc/net/ip_conntrack), wohingegen pf nur states erzeugt, bei denen es durch Regeln explizit oder implizit dazu aufgefordert worden ist.

* Wenn bei pf bei Paketfilterregeln das Schlüsselwort "keep state" verwendet wird, wird das connection tracking für diese Pakete aktiviert und die initialen Pakete sowie alle weiteren, die zu einer bestehenden Verbindung gehören, werden automatisch akzeptiert, ohne dass die Paketfilterregeln noch einmal ausgewertet werden. Bei netfilter werden die Filterregeln hingegen immer ausgewertet, d.h. es muss explizit akzeptierende Regeln geben (man kann hierbei aber natürlich auf die State-Informationen des globalen State-Tables zurückgreifen).
Man kann das Verhalten von netfilter ein wenig an pf annähern, wenn man folgende Regeln verwendet:
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Damit werden alle Pakete akzeptiert, die zu bestehenden Verbindungen gehören. Dazu müssen dann noch entsprechende Regeln mit den Schlüsselwort "--state NEW" hinzugefügt werden, die die initialen Pakete akzeptieren.

* NAT- und Portforwarding-Regeln können mit dem "pass" Schlüsselwort versehen werden, so dass für diese Pakete implizit enstprechende states erzeugt werden, so dass sie nicht explizit von den Paketfilterregeln akzeptiert werden müssen. Bei netfilter müssen sowohl im Falle von SNAT als auch DNAT die Pakete in der FORWARD chain explizit akzeptiert werden (man kann hierbei aber natürlich auf die State-Informationen des globalen State-Tables zurückgreifen).

Das sind natürlich nicht alle Unterschiede, aber es sind erst einmal die wichtigsten, die Umsteiger wissen müssen.

Edit: Fehler korrigiert und Wortlaut verbessert.
 
Zuletzt bearbeitet:
Dann stellt sich für mich aber die Frage warum ein smtp redirect in die DMZ mit NAT, ohne die entsprechende "pass in" Regel nicht funktioniert!
 
Dann stellt sich für mich aber die Frage warum ein smtp redirect in die DMZ mit NAT, ohne die entsprechende "pass in" Regel nicht funktioniert!

Soweit ich sehe hast du hast keine nat oder rdr Regeln gepostet, oder?

Insofern kann ich nur vermuten, dass du dort nicht das "pass" Schlüsselwort verwendet hast. Ohne dieses Schlüsselwort müssen die entsprechenden Pakete tatsächlich durch die Filterregeln explizit akzeptiert werden.

Ich hatte da gar nicht dran gedacht, ich werde meine Liste entsprechend anpassen.
 
Zurück
Oben