port-mapping -> so geht's
Als kleinen Nachtrag zu meiner eigenen Frage will ich mal meine Lösung an die Nachwelt hinterlassen. Vielleicht hat ja jemand ein ähnliches Problem.
Der Schlüssel zum port-mapping/port-forwarding liegt tatsächlich im nat-daemon. Wer sich in den Foren von Free-BSD umschaut, findet auch genügend Futter zu diesem Thema. Leider hat Apple natürlich einiges verschraubt, damit man durch den einfachen Klick auf die Knöpfchen NAT und die IPFW firewall unter der 10.3 Server Version konfigurieren/aktivieren kann. Die Konfigurationsmöglichkeiten für NAT unter dem GUI beschränken sich allerdings auf die Auswahl der Netzwerkkarte, die das public-interface repräsentieren soll. Was wir fürs port-mapping brauchen, ist eine Zeile in der Konfigurationsdatei für natd mit dem Befehl
redirect_port tcp lokale_IP: port externe_IP: port. Alles nachzulesen unter
man natd. FreeBSD hat normalerweise für diesen Zweck eine Datei namens
natd.conf unter
/etc liegen. Die gibt es unter OSX natürlich nicht. Hier findet man in
/etc/nat/ drei Dateien, nämlich
natd.conf.apple, natd.plist und
natd.plist.default. Das GUI modifiziert
natd.plist, eine Standard Parameterdatei in XML, und benutzt diese als Grundlage, um
natd.conf.apple zu generieren, welche wiederum natd beim Starten als Alternativ-Konfigurationsdatei untergeschoben wird.
natd.plist.default ist lediglich ein template zum Generieren von
natd.plist und kommt nur dann zum Einsatz, wenn letztere nicht vorhanden ist.
Jetzt gibt es unterschiedliche Möglichkeiten, um zu erreichen, dass NAT unseren redirect_port Befehl erhält. Der direkteste Weg wäre NAT über das GUI zu deaktivieren,
natd.conf.apple zu modifizieren (oder alternativ eine natd.conf Datei anzulegen) und natd anschliessend manuell zu starten, z.B. mit
sudo natd -f /etc/nat/natd.conf.apple. Das hat allerdings den Schönheitsfehler, dass alles wieder dahin ist, sobald man wieder das Knöpfchen im Server-Administrationsprogramm benutzt.
Will man künftig NAT weiterhin über das Knöpfchen starten und stoppen, kommt man nicht umhin,
natd.plist zu modifizieren, da hieraus wie gesagt jedesmal
natd.conf.apple dynamisch erzeugt wird. Die XML-Syntax der verschiedenen Konfigurationsparameter für natd findet man in
natd.plist.default. Beispielsweise steht da
redirect_port - array of redirect_port dictionaries; optional
und als Erläuterung zum Aufbau des dictionary
redirect_port dictionary keys:
proto - string; required
targetIP - string; required
targetPortRange - string; required
aliasIP - string; required
aliasPortRange - string; required
Laut
man natd sind alias IP und Port zwar optional, aber die plist möchte es halt haben. Wenn man
natd.plist mit dem PLIST-Editor aus den Developer tools editieren möchte, muss man wohl als echter root Nutzer eingeloggt sein, daher geht man besser den Weg über das Terminal. Mein bevorzugter Editor ist pico, also öffne ich mit
sudo pico /etc/nat/natd.plist und füge folgenden Absatz ein:
<key>redirect_port</key>
<array>
<dict>
<key>aliasIP</key>
<string>193.175.25.xxx</string>
<key>aliasPortRange</key>
<string>21</string>
<key>proto</key>
<string>tcp</string>
<key>targetIP</key>
<string>192.168.102.xxx</string>
<key>targetPortRange</key>
<string>21</string>
</dict>
</array>
Die letzten Stellen der IPs sind wegen stetig wachsender paranoider Anwandlungen mal augeixt. ;-) Startet man NAT jetzt wieder über das Knöpfchen wird danach folgende Zeile in
natd.conf.apple auftauchen:
redirect_port tcp 192.168.102.xxx:21 193.175.25.xxx:21
Übersetzt bedeutet dies, dass alle Anfragen an das externe Interface (193.175.25.xxx) auf port 21 (=ftp Kommandoport) umgeleitet werden auf den ftp-port vom internen Rechner mit der IP 192.168.102.xxx.
Damit ist von NAT-Seite eigentlich alles gelaufen. Jetzt muss man IPFW nur noch sagen, dass er NAT auch einsetzen soll und entsprechende Port-Freigaben setzen. Die Konfigurationsmöglichkeiten der firewall Regeln über das Server Administrationsprogramm sind leider ebenfalls nur halbherzig. Deshalb regele ich das auf anderem Wege. Allerdings würde das jetzt ein wenig den Rahmen sprengen. Falls es wirklich jemanden interessiert, kann er/sie ja mal nachhaken. Die Kurzform ist jedenfalls, einen divert der eingehenden Verbindungen über NAT, eine Freigabe von port 21 auf dem internen (nicht ! dem externen) Rechner und die Freigabe eines Portbereiches für die Datenverbindungen bei passivem FTP.
...
add 015 divert natd ip from any to any in via en0
...
add 350 allow log tcp from any to 192.168.102.xxx ftp,ftp-data in via en0
add 351 allow log tcp from any to 192.168.102.xxx 49000-49100 in via en0
add 352 skipto 30000 tcp from 192.168.102.xxx ftp,ftp-data to any out via en0
add 353 skipto 30000 tcp from 192.168.102.xxx 49000-49100 to any out via en0
...
add 2000 deny log all from any to any in via en0
...
add 30000 divert natd ip from any to any out via en0
add 30010 allow ip from any to any
...
Einiges ist jetzt aus dem Kontext gerissen und in statischen Regeln formuliert. Man kann das natürlich auch statefull mit dynamischen Regeln aufbauen. Wichtig ist nur noch, dass ftp-data (port 20) nur gebraucht wird, wenn der client aktives ftp einsetzen will. Aktives ftp scheitert allerdings, wenn der client auch hinter einer fw sitzt. In dem Fall geht es nur passiv, und der client kontaktiert den server auf einem port im Bereich von 49000 bis 49100. Der ftp-server ist natürlich so konfiguriert, dass er dem client nur diesen Bereich vorschlägt.
So, das tolle ist, dass es prima funktioniert. Wenn ich ehrlich bin, weiss ich allerdings nicht so genau, wieso eigentlich. Der Knackpunkt ist nämlich die Freigabe von den ports 49000-49100 auf dem internen Rechner. Diese Ports werden ja nicht durch einen entsprechenden Befehl in
natd.conf.apple ge-forwarded. Aus der Sicht des Routers kommen neue Verbindungsanfragen an diese ports von einem externen Rechner auf en0 an. Woher weiss NAT/IPFW, dass es diese Verbindungen auf den internen ftp-server via en2 mappen muss? Ohne, dass ein Paket-Sniffer die Verhandlungen über den künftigen Datenport (die ja über port 21 serverseitig laufen) belauscht, kann NAT/IPFW doch gar nichts darüber wissen! Sowohl client wie auch server benutzen neue ports. Andererseits muss es so eine Funktionalität wohl geben, denn gerade für solche Fälle wie FTP gibt es die Konfigurationsanweisung
punch_fw für den natd. Dabei werden in einem vorgegebenen Bereich der IPFW-Regeltabelle temporär neue Regeln eingefügt (ich meine nicht die dynamischen Regeln), die selektive Löcher für die Datenkanäle bohren. Supergeile Geschichte, aber zum Laufen hab ich's noch nicht gebracht. Hauptsächlich, weil es keine vollständige Apple-Dokumentation dazu gibt. Man findet zwar
punch_fw - punch_fw dictionary; optional
in der Beschreibung von
natd.plist.default, aber leider nichts zum Aufbau des dictionary und der keys. Meine "best guess" Versuche mit "basenumber" und "count" als keys hat er schlichtweg ignoriert. Aber das ist eine andere Geschichte...
Hoffe, das mein Megaposting hier irgendwann jemandem hilft.
Gruss, Lupus