pf / rdr / transparenter Proxy

Errorsmith

Kompiliertier
'nabend

Ich habe dieses Setup:
Code:
                             Proxy
                                |
                                |
                                |
Internet------Firewall-------Server------Clients

Die Clients sollen nicht direkt auf das Web zugreifen können, sondern über den Proxy (Squid) gehen, dieser ist aus verschiedenen Gründen als transparenter Proxy konfiguriert. Ich ärgere mich nun mit der pf Konfiguration dafür herum.
Eine einfache Regel im Stil von
Code:
rdr on $intif from $clients to any port 80 -> $proxy port 3128
nat on $extif from $proxy to any port 80 -> ($extif)
[...]
pass quick proto tcp from $proxy to any port 80 keep state

auf der Firewall bringt leider nicht den gewünschten Erfolg. Wo ist hier mein Problem?

Grüße,
errorsmith
 
kann ich verstehen. Die genannten Beispiele kannte ich ja schon, ich Google das Problem schon eine Weile. Sie beziehen sich auf Konfigurationen bei denen pf auf der selben Maschine läuft wie der squid. Das ist bei mir jedoch nicht der Fall und auch mein Problem soweit ich das verstanden habe. Ich weiß nur nicht wie ich das lösen kann.
 
kann ich verstehen. Die genannten Beispiele kannte ich ja schon, ich Google das Problem schon eine Weile. Sie beziehen sich auf Konfigurationen bei denen pf auf der selben Maschine läuft wie der squid. Das ist bei mir jedoch nicht der Fall und auch mein Problem soweit ich das verstanden habe. Ich weiß nur nicht wie ich das lösen kann.

$proxy ist aber keine Untermenge von $clients (selbe Netz, IP Überschneidungen o.ä.)? ansonsten mal das Logging für pf hoch drehen und per tcpdump schauen, was er mit den Paketen macht und wo diese überall rumfahren (werden sie an den Proxy umgeleitet, kommen Pakete vom Proxy wieder bei der Firewall an und verlassen sie auf dem externen interface etc.)
 
Nein, $proxy ist auf 192.168.20.10 und die Clients auf 192.168.23.0/24
Werde mal ein wenig mit dem logging rumbasteln. :rolleyes:

Grüße,
errorsmith
 
Hi

Das möchte ich nächste Woche auch machen. Ich habe die Beispiele kurz überflogen. Das heisst das ich Squid auf einem BSD zwingend laufen haben muss? Derzeit habe ich einen Squid auf Debian (Linux) mit SquidClamAv

Wie baut man dann am besten eine Ausname ein? Ich will jeden HTTP Traffic umleiten ausser der geht in das Netz 192.168.0.0/24
 
Moin

ich bin da mittlerweile etwas weiter. Ich habe das so verstanden, das es im wesentlichen um folgendes Problem geht:
Client stellt Anfrage -> Firewall lenkt auf Proxy um -> Proxy versucht seine DatenPakete direkt an den Client zu schicken der als Absender in der Anfrage stand (rdr ändert ja nur die Zieladresse) -> Client akzeptiert die Datenpakete nicht, da er keine aktive Verbindung mit dem Proxy hatte.

Daher geht es also um drei Optionen (Es gibt noch eine mit WCCP die ich aber unberücksichtig lassen muss, da ich die Hardware dafür nicht habe):

1. Proxie läuft auf der Firewall / Gateway Maschine, der redirect geht auf lo0. Der Proxy kommuniziert über devices in /dev mit der Firewall um die "richtigen" Pakete zu versenden(?)

2. Die Firewall macht zunächst ein redirect auf den Proxy und natt'ed den Traffic dann auf ihr eigenes $intif

3. auf der Firewall läuft ein (minimaler) Proxy der den "richtigen" Proxy als Parent definiert hat.

Option 1 setzt voraus das die Firewall ordentlich Power hat um einen vollwertigen Proxy laufen zu lassen, bei den Optionen 2 & 3 habe ich das Problem das der Proxy als "Absender" nur die Firewall "sieht" und daher alle Client/IP basierten Filter nicht greifen. Irgendwie die Wahl zwischen Pest & Cholera glaube ich.

Ich lasse mich da aber gern eines besseren belehren falls ich was übersehen habe.

Grüße,
errorsmith
 
Hi

Wie baut man dann am besten eine Ausname ein? Ich will jeden HTTP Traffic umleiten ausser der geht in das Netz 192.168.0.0/24
Du kannst Ausnahmen in den Ziel / Quell definitionen setzen (z.B: 192.1680.0.1/24 !192.168.0.54 ) oder mit "no rdr" arbeiten:
um alles ausser meinem rechner und den lokalen webserver auf den proxy umzuleiten.
Code:
no rdr on $int_if proto { tcp, udp } from any to $server port 80
no rdr on $int_if proto { tcp, udp } from $meinrechner to any port 80
rdr on $int_if proto { tcp, udp } from any to any port 80 -> 127.0.0.1 port 80

Grüße,
errorsmith
 
Sowas funktioniert, ich hab das vor einigen Jahren mal bei einem Arbeitgeber in Betrieb. pf lief auf einem OpenBSD und hat den Traffic in der DMZ auf einen transparenten Proxy umgeleitet. Allerdings ist das auch nur bedingt sinnvoll, da die Clients sich unter Umständen anders verhalten, wenn sie wissen, dass ein Proxy dazwischen hängt und es evtl. im Fehlerfall dann auch einfacher zu debuggen ist.

Die Konfiguration hab ich im Moment leider nicht, aber im Grunde funktionierte das "damals" ;). Der Proxy muss allerdings auch entsprechend konfiguriert werden, damit er den Hostnamen aus der Anfrage extrahiert bekommt, da der Client nicht weiss, dass er das einem evtl. Proxy mitteilen sollte.
 
Das Problem ist das ich nicht auf alle Geräte den entsprechenden Zugriff habe um Proxies zu definieren: z.B. embedded Geräte, Smartphones etc. Daher möchte ich den Proxy transparent haben.

Laut tcpdump läuft es so:
Client -> Firewall -> Server...?
Die Anfragen kommen am Server an, "verschwinden" dort aber. Keine Ahnung wieso.

Ich habe das jetzt vorerst so gelöst:
Der Proxy läuft auf der oben als "Server" bezeichneten Maschine. Desweiteren habe ich auf dem Server pf aktiviert und rdr / pass Regeln auf den (nunmehr lokalen) Proxy erzeugt. Gefällt mir zwar nicht so richtig, aber anders scheint es erstmal nicht zu gehen.

Falls dir noch einfällt wie das ging...? Squid hatte ich bisher als intercepting Proxy konfiguriert, damit funktioniert es in o.g. Konfiguration.


Grüße,
errorsmith
 
Ich hatte nicht noch ein Maschine dazwischen hängen. Der Proxy war direkt an der Firewall angeschlossen.
 
Ich werde nicht mal aus dem Diagramm schlau. Hängt der Proxy jetzt am Server oder wie? Total unverständlich...
 
Meine ASCII Skills sind so doll, tut mir leid.
Vielleicht ist das da klarer:
attachment.php


Makenoob hat das schon richtig erkannt. Der Proxy hängt an dem Server

Grüße,
errormsith
 

Anhänge

  • diagramm.gif
    diagramm.gif
    10 KB · Aufrufe: 546
Also routet der Server? Wieso hängt der Proxy nicht an der Firewall in seinem eigenen Netz?

Edit: z.B. so:

Code:
               Proxy
                 |
Internet --- Firewall --- Clients
                 |
               Server
 
Zuletzt bearbeitet:
Weil
1. Die Firewall nur 2 Anschlüsse hat (wan und intern)
2. Der Server die Clients in verschiedenen Subnetzen bedient und daher so oder so routen muß:
1 Subnetz für die "normalen" Clients
1 Subnetz für die WLAN Clients
1 Subnetz für die "Infrastruktur" ( Telefone, NAS etc)

Der Server stellt für die Clients die üblichen Netzwerkdienste in einem kleinen Netz bereit: dhcp, caching DNS, ntp, samba, nfs und einen lokalen Webserver mit einer Mail/Groupwarelösung

Grüße,
errorsmith
 
Hat die Firewall eine Route zum Proxy über den Server?

Im Übrigen nimmt man dann VLANs. Die zentrale Stelle sollte die Firewall sein. Ein Server mit Diensten sollte nicht routen.

Was mir noch einfällt:

Code:
rdr on $intif from $clients to any port 80 -> $proxy port 3128
nat on $extif from $proxy to any port 80 -> ($extif)
[...]
pass quick proto tcp from $proxy to any port 80 keep state

Du musst die Verbindung intern nochmal NATen. Also quasi

Code:
rdr on $intif from $clients to any port 80 -> $proxy port 3128 tag PROXY
nat on $intif tagged PROXY -> ($intif)

oder so ähnlich. Ich hab nur die neuere OpenBSD-Syntax im Kopf. Die Verbindungen erscheinen dann auf dem Proxy, als kämen sie von der Firewall. Deswegen wäre es auch besser, wenn die ganzen Netze direkt an der Firewall lägen, dann wäre das mit dem rdr sauberer.

Wenn du dir überlegst, wie der Traffic jetzt für eine einzelne Verbindung aussieht: clients -> firewall -> proxy -> firewall -> proxy -> firewall -> clients, dann siehst du hoffentlich selber, wie unausgegoren das Setup ist.
 
Zuletzt bearbeitet:
Jupp

Code:
root@igel:/usr/home/extern # netstat -rn
Routing tables

Internet:
Destination        Gateway            Flags    Refs      Use  Netif Expire
default            xxx.x.xxx.xxx      UGS         0    58404   tun0
10.0.0.0/8         link#1             U           0      566    rl0
10.0.0.1           link#1             UHS         0        0    lo0
yy.yy.y.yyy       link#12            UHS         0        0    lo0
127.0.0.1          link#10            UH          0      282    lo0
192.168.20.0/24    192.168.200.2      UGS         0  1491989    vr0
192.168.22.0/24    192.168.200.2      UGS         0   103189    vr0
192.168.23.0/24    192.168.200.2      UGS         0   529097    vr0
192.168.24.0/24    192.168.200.2      UGS         0    59246    vr0
192.168.25.0/24    192.168.200.2      UGS         0        0    vr0
192.168.200.0/24   link#7             U           0   290558    vr0
192.168.200.1      link#7             UHS         0      252    lo0
xxx.x.xxx.xxx      link#12            UHS         0        0   tun0

Die Firwall hat intern 192.168.200.1, der Server 192.168.200.2, der Proxy liegt auf 192.168.20.10, die Clients auf den Subnetzen 192.168.22.0/24, 192.168.23.0/24 und 192.168.24.0/24. 10.0.0.1 ist die NIC am DSL Modem.

Die Routen sind statisch konfiguriert. Der Server hat als default-gateway die Firewall eingetragen, die restlichen Routen sind lokal. Der Proxy hat den Server als default-gateway, die Clients bekommen ihn über DHCP. Ich arbeite nicht mit VLAN, der Server hat tatsächlich für jedes Subnetz eine NIC verbaut.

Grüße,
errorsmith
 
Dann solltest du die Rollen tauschen; die ganzen NICs aus dem Server in die Firewall stopfen.
 
Hat die Firewall eine Route zum Proxy über den Server?

Im Übrigen nimmt man dann VLANs. Die zentrale Stelle sollte die Firewall sein. Ein Server mit Diensten sollte nicht routen.

Was mir noch einfällt:

Code:
rdr on $intif from $clients to any port 80 -> $proxy port 3128
nat on $extif from $proxy to any port 80 -> ($extif)
[...]
pass quick proto tcp from $proxy to any port 80 keep state

Du musst die Verbindung intern nochmal NATen. Also quasi

Code:
rdr on $intif from $clients to any port 80 -> $proxy port 3128 tag PROXY
nat on $intif tagged PROXY -> ($intif)

oder so ähnlich. Ich hab nur die neuere OpenBSD-Syntax im Kopf. Die Verbindungen erscheinen dann auf dem Proxy, als kämen sie von der Firewall. Deswegen wäre es auch besser, wenn die ganzen Netze direkt an der Firewall lägen, dann wäre das mit dem rdr sauberer.

Deine AW kam während ich am schreiben war ;)

VLAN: Als das Netz aufgebaut wurde konnte das Switch noch kein VLAN. Im Moment muß ich mit der Totpologie leben wie es jetzt ist. Ich denke darüber nach eine 2 Port Karte zu kaufen und die ans Switch zu hängen, diec Netzwerke (Proxy, Clients) dann mit VLANS am Switch zu trennen und gut ist. Zunächst muß ich es aber so ans laufen kriegen.

Wenn ich den Verkehr über die Firewall auf den Proxy natten würde, verliere ich meine IP-basierten Filteroptionen (Wlan darf weniger als die verkabelten Clients, einige Clients haben nur eine kleine Whitelist auf die sie zugreifen dürfen). Gibt es da einen Weg das zu lösen?

Nachtrag zum Rollentausch: Die Firewall hat nur einen PCI Steckplatz.

Grüße,
errorsmith
 
Ja, das ist das was ich ja oben schrieb wie ich es jetzt zum laufen gebracht habe. Also gibt es scheinbar - in der aktuellen Konfiguration - keinerlei Möglichkeit den rdr auf der Firewall durchzuführen ohne die Quelladressen umzuschreiben. Ursprünglich wollte ich pf auf dem Server deaktiviert lassen.

Grüße,
errorsmith
 
80 EUR für einen 802.1q-fähigen Switch ausgeben und richtig[tm] machen wäre mein dringender Rat, aber musst du selber wissen, wie du nachts schläfst :)
 
Die Situation ist die:
Als das Netz aufgebaut wurde gab es erst zwei, später 4 8-Port Switches und einen zentralen Rechner der sowohl Server als auch Router/Firewall war. Mittlerweile gibt es einen großen (VLAN fähigen) Switch, VLANs wurden verwendet um die kleinen Switches zu "emulieren", die "Serverfirewall" blieb, der Proxy auch. Die ganze Sache ist halt irgendwie gewachsen.

Nun gibt es eine dedizierte Firewall: Der Grundgedanke war, diese dort anzuschließen wo vorher der WAN Anschluß vom Server war und die PF Konfiguration zu übertragen.

Wenn ich dich richtig verstehe, wäre es nun richtiger, die Firwall über VLANs als zentralen Gateway in die Subnetze zu bringen, den Server als reinen Server zu nutzen (aus Geschwindigkeitsgründen trotzdem mit mehreren NICs) und den Proxy auch direkt ans LAN zu hängen, ggf in ein eigenes VLAN.

Frage dazu:
Wenn der Server mit 192.168.20.1 und 192.168.22.1 am Switch in jeweils einem Subnetz hängt. Wie bringe ich ihn dazu Pakete die von 192.168.20.1 nach 192.168.22.99 sollen auch wirklich über das Switch zu senden anstatt intern von NIC a zu NIC B? Reicht es dann IP Forwarding via Sysctl zu deaktivieren? Gerade bei jails habe ich festgestellt das die Pakete schwer zu fassen sind: Ich habe es z.B. noch nicht geschafft den oben genannten rdr auf die jails anzuwenden: Egal auf welchem Interface ich den rdr anbringe und welche IP Adresen ich angebe: Die Pakete kommten direkt auf der Firewall an. (Oder ich stelle mich zu doof an, mit PF habe ich mich bisher nicht sehr eingehend beschäftigen müssen)

Grüße,
errorsmith
 
Zurück
Oben