[OpenBSD]

[Zurück: Leistung] [Inhalt] [Weiter: Authpf: Benutzer-Shell für authentifizierende Gateways]

PF: Probleme mit FTP


Inhaltsverzeichnis


FTP-Modi

FTP ist ein Protokoll, das zu der Zeit entwickelt wurde, als das Internet noch eine kleine, freundliche Ansammlung von Computern war und jeder jeden kannte. Zu dieser Zeit war die Notwendigkeit zum Filtern und für straffe Sicherheit nicht gegeben. FTP wurde nicht zum Filtern, zum Weiterleiten durch Firewalls oder für die Zusammenarbeit mit NAT entwickelt.

Du kannst FTP auf zwei unterschiedliche Weisen verwenden: passiv oder aktiv. Generell gilt, dass die Wahl zwischen aktiv und passiv entscheidet, wer das Problem mit der Firewall haben wird. Sei realistisch, du wirst beide unterstützen müssen, um glückliche Anwender zu haben.

Bei aktivem FTP wird der FTP-Server eine neue Verbindung zurück zum -Client eröffnen, um die angefragten Daten zu übertragen, wenn ein Benutzer sich zu einem entfernten FTP-Server verbindet und eine Information oder Datei anfragt. Diese wird als data connection bezeichnet. Am Anfang entscheidet der FTP-Client sich für einen zufälligen Port, auf dem die ,data connection' angenommen werden soll. Der Client sendet dann die gewählte Portnummer zum FTP-Server und lauscht dann auf dem Port für eine eingehende Verbindung. Der FTP-Server erstellt dann eine Verbindung zur Adresse vom Client am gewählten Port und überträgt die Daten. Dies ist ein Problem für Benutzer, die auf einen FTP-Server zugreifen wollen, wenn sie selbst hinter einem NAT-Gateway liegen. Wegen der Funktionsweise von NAT wird der FTP-Server eine ,data connection' zur externen Adresse des NAT-Gateways auf dem gewählten Port aufbauen. Die NAT-Maschine wird diese Verbindung erhalten, aber da sie nicht in der ,state'-Tabelle aufgelistet ist, wird sie das Paket fallen lassen und nicht zum Client weiterleiten.

Beim passiven FTP-Modus (dem standardmäßigem Modus mit OpenBSDs ftp(1)-Client) wird der Client vom Server verlangen, dass dieser einen zufälligen Port auswählen soll, auf dem er dann auf die ,data connection' wartet. Der Server teilt dem Client mit, welchen Port er ausgewählt hat und der Client verbindet sich auf diesen Port, um die Daten zu übertragen. Unglücklicherweise ist dies nicht immer möglich oder erwünscht, da die Möglichkeit besteht, dass eine Firewall vor dem FTP-Server die eingehende ,data connection' blockt. OpenBSDs ftp(1) verwendet standardmäßig den passiven Modus; um aktives FTP zu erzwingen, verwende die -A-Option mit ftp oder setze den passiven Modus aus (off), indem du das Kommando ,passive off' am ,ftp>' Prompt eingibst.

FTP-Client hinter der Firewall

Wie zuvor schon angedeutet, geht FTP nicht sonderlich gut durch NAT und Firewalls hindurch.

Packet Filter bietet eine Lösung für dieses Problem, indem der FTP-Verkehr durch einen FTP-Proxyserver hindurch geleitet wird. Dieser Prozess ,leitet' deinen FTP-Verkehr durch das NAT-Gateway/durch die NAT-Firewall. Der FTP-Proxy, der von OpenBSD und PF verwendet wird, ist ftp-proxy(8). Um ihn zu aktivieren, erstelle in der NAT-Sektion von pf.conf etwas, das ähnlich diesem Eintrag ist:

rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \
   port 8021

Die Erklärung dieser Zeile ist: "Verkehr auf dem internen Interface wird zum Proxyserver weitergeleitet, der auf dieser Maschine läuft und auf dem Port 8021 lauscht."

Hoffentlich ist es offensichtlich, dass der Proxyserver auf dem OpenBSD-Rechner gestartet werden und auch laufen muss. Dies wird durch das Eintragen der folgenden Zeile in die /etc/inetd.conf realisiert:

127.0.0.1:8021 stream tcp nowait root /usr/libexec/ftp-proxy \
   ftp-proxy -n

Bedenke, dass die -n-Option nur notwendig ist, wenn die OpenBSD-Maschine als NAT arbeitet. Sende jetzt ein ,HUP'-Signal zum inetd(8), so dass dieser seine Konfigurationsdatei neu einließt. Ein Weg, das ,HUP'-Signal zu senden, ist, folgendes Kommando einzugeben:

kill -HUP `cat /var/run/inetd.pid`

Du wirst bemerken, dass der ftp-proxy auf den Port 8021 hört, dem gleichen Port, auf den in der vorherigen rdr-Angabe der FTP-Verkehr weitergeleitet wird. Die Wahl von Port 8021 ist willkürlich, wobei 8021 eine gute Wahl ist, da dieser für keine andere Applikation definiert wurde.

Zu diesem Zeitpunkt werden nur passive FTP-Verbindungen funktionieren. Um aktive Verbindungen ebenfalls zu ermöglichen, muss die ,ftp-data connection', die der FTP Server aufbaut, zur Firewall durchgelassen werden. Leider kann der Port, auf den die Verbindung aufgebaut werden soll, nicht vorhergesagt werden, nur der Bereich, in dem dieses möglich sein könnte. Was jedoch bekannt ist, ist, dass die Verbindung vom Port 20 (ftp-data-Port) aus errichtet wird, und dass der ftp-proxy die Verbindung akzeptieren wird (und dann die Daten zum Client weiterleitet). Da der ftp-proxy als Benutzer proxy läuft, kann das user-Schlüsselwort in der Filterregel angewandt werden.

pass in on $ext_if inet proto tcp from port 20 to ($ext_if) \
    user proxy flags S/SA keep state

Bedenke bitte, dass der ftp-proxy(8) dazu da ist, den FTP-Clients hinter einem PF-Filter zu helfen; er kann keinen FTP-Server hinter einem PF-Filter handhaben.

Ein FTP-Server, der ,sich selbst mit PF schützt'

In diesem Fall läuft PF direkt auf dem FTP-Server, statt auf einem extra dafür installiertem Firewall-Computer. Wenn eine passive FTP-Verbindung angeboten wird, wird FTP zufällig einen hohen TCP-Port für eingehende Daten auswählen. Standardmäßig wird OpenBSDs nativer FTP-Server ftpd(8) einen Port aus dem Bereich 49152 bis 65535 nutzen. Diese müssen selbstverständlich durch die Filterregeln gelassen werden, zusätzlich zum Port 21 (dem FTP-Kontroll-Port):
pass in on $ext_if proto tcp from any to any port 21 keep state
pass in on $ext_if proto tcp from any to any port > 49151 \
   keep state

Wenn du möchtest, kannst du den Bereich der Ports beachtlich verbessern. Im Falle vom OpenBSD ftpd(8)-Programm wird dies durch die Verwendung von den sysctl(8)-Variablen net.inet.ip.porthifirst und net.inet.ip.porthilast ermöglicht.

FTP-Server, die durch eine externe PF-Firewall beschützt werden, die NAT verwendet

In diesem Fall muss die Firewall den Verkehr zum FTP-Server zusätzlich zum Durchlassen der Ports auch weiterleiten. Um das Beispiel einfach zu halten, nehmen wir an, dass wieder der normale OpenBSD- ftpd(8) unter Verwendung des standardmäßigen Portbereichs genutzt wird.

Hier ist ein Beispiel-Unterregelsatz, der dies realisieren würde:

ftp_server = "10.0.3.21"

rdr on $ext_if proto tcp from any to any port 21 -> $ftp_server \
   port 21
rdr on $ext_if proto tcp from any to any port 49152:65535 -> \
   $ftp_server port 49152:65535

# in on $ext_if
pass in quick on $ext_if proto tcp from any to $ftp_server \
   port 21 keep state
pass in quick on $ext_if proto tcp from any to $ftp_server \
   port > 49151 keep state

# out on $int_if
pass out quick on $int_if proto tcp from any to $ftp_server \
   port 21 keep state
pass out quick on $int_if proto tcp from any to $ftp_server \
   port > 49151 keep state

Weitere Informationen zum Thema FTP

Weitere Informationen zum Thema FTP-Filtern und wie FTP generell funktioniert, können in diesem ,whitepaper' gefunden werden:

[Zurück: Leistung] [Inhalt] [Weiter: Authpf: Benutzer-Shell für authentifizierende Gateways]


[zurück] www@openbsd.org
$OpenBSD: ftp.html,v 1.10 2006/04/25 08:25:49 saad Exp $