nft-Konfiguration, um einen lokalen NATed-FTP-Server öffentlich verfügbar zu machen

nft-Konfiguration, um einen lokalen NATed-FTP-Server öffentlich verfügbar zu machen

Alles wird in einem isolierten Netzwerk sein, Sicherheit ist kein Thema.
eth0 ist mit dem „öffentlichen“ Netzwerk verbunden. Die Adresse wird von DHCP zugewiesen.
eth1 ist mit einem „privaten Netzwerk“-Server verbunden, der SSH, Telnet, „Andere“ und FTP bereitstellt.
Dieser Server hat in diesem Beispiel eine feste IP (192.168.1.2).

Das Gateway läuft mit Debian Buster und Linux Kernel 4.19.94

nft wird mit NAT verwendet.
Dies ist meine bisherige „Gateway“-NFT-Konfiguration:

table ip my_nat {
    chain my_prerouting { type nat hook prerouting priority 0;
    tcp dport { 2222 } dnat to :22 # 2222 backdoor for ssh to the gateway
    tcp dport { 1-1023 } dnat to 192.168.1.2
  }
  chain my_postrouting {
    type nat hook postrouting priority 100;
    ip daddr 192.168.1.2  masquerade
  }
}

Was muss ich hinzufügen, damit FTP funktioniert?

Antwort1

Kurz zusammengefasst

# nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'
# nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
# nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming
# modprobe nf_nat_ftp

weitere Einzelheiten finden Sie weiter unten …

Protokoll-Hilfsmodule für problematische Protokolle

FTP ist ein altes Protokoll und nicht sehr Firewall-freundlich: Befehle auf dem FTP-Befehlskanal (21/TCP) verhandeln einen temporären Port, der für den nächsten Übertragungsbefehl verwendet werden soll. Aus diesem Grund muss eine Stateful Firewall diese Befehle und Antworten überwachen, um den entsprechenden Port, der verwendet werden soll, vorübergehend freizugeben.

Unter Linux wird dies durch protokollspezifische Hilfsmodule bereitgestellt, die Plugins sind fürKontakt, das Netfilter-Subsystem, das Verbindungen für NAT und Stateful Firewalling verfolgt. Bei FTP fügt der Helper einen kurzlebigen Eintrag in einem speziellen Feld hinzu, wenn eine Portverhandlung (meistens PORT, EPRT, PASV oder EPSV) für die nächste Übertragung auf dem FTP-Befehlsport festgestellt wurde.KontaktTabelle (dieConntrack-ErwartungTabelle), die auf die nächste zugehörige und erwartete Datenverbindung wartet.

Meine Antwort verwendet die moderne "sichere" Handhabung wie beschrieben indieser Blog überiptablesfür Allgemeines und in derNftablesWikiUndman nftfür die Abwicklung inNftablesdas unterscheidet sich voniptables.

Sichere Verwendung von Hilfs- und Nftables-Regeln

Linux-Kernel 4.7+ (also einschließlich 4.19) verwendet standardmäßig einen sicheren Ansatz: Wenn das (hier FTP) Hilfsmodul geladen ist, wird es nicht mehr alle Pakete mit einem TCP-Quell- oder Zielport 21 abhören, bis bestimmteNftables(oderiptables)-Anweisungen geben an, in welchem ​​(eingeschränkten) Fall snoopt werden soll. Dies vermeidet unnötige CPU-Auslastung und ermöglicht es, die zu snoopenden FTP-Ports jederzeit durch Ändern einiger Regeln (oder Sets) zu ändern.

Der erste Teil besteht darin, die Flows zu deklarieren, die das Snooping auslösen können. Dies wird anders gehandhabt inNftablesals iniptables. Hier wird es als statusbehaftetes Objekt deklariert ct helperund Filter zur Aktivierung müssen nachKontakt(währendiptableserfordert zuvor ausgeführte Aktionen).man nfterzählt:

Anders als bei iptables muss die Helferzuweisung nach Abschluss der Conntrack-Suche durchgeführt werden, beispielsweise mit der standardmäßigen Hook-Priorität 0.

nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'

nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming

Ich habe dieselbe Tabelle ausgewählt, aber diese hätte auch in einer anderen Tabelle erstellt werden können, solange sich die Statusobjektdeklaration und die darauf verweisende Regel in derselben Tabelle befinden.

Man kann natürlich auch weniger restriktive Regeln wählen. Das Ersetzen der letzten Regel durch die folgende Regel hätte den gleichen Effekt wie der Legacy-Modus:

nft add rule ip my_nat my_helpers tcp dport 21 ct helper set ftp-incoming

Nur als Referenz: Der Legacy-Modus, der nicht mehr verwendet werden sollte, erfordert nicht die oben genannten Regeln, sondern nur diesen Schalter (und das manuelle Laden des relevanten Kernelmoduls):

sysctl -w net.netfilter.nf_conntrack_helper=1

Sicherstellen, dass nf_nat_ftpgeladen ist

Das Kernelmodul nf_conntrack_ftpwird automatisch mit der von erstellten Abhängigkeit geladen ct helper ... type "ftp". Das ist bei nicht der Fall nf_nat_ftp, dennoch ist es erforderlich, auch die Paketmanschette im Befehlsport zu aktivieren, wenn NAT auf den Datenflussports durchgeführt wird.

Um beispielsweise das Modul nf_nat_ftpbei jedem nf_conntrack_ftpLaden abzurufen, /etc/modprobe.d/local-nat-ftp.confkönnte die Datei mit folgendem Inhalt hinzugefügt werden:

install nf_conntrack_ftp /sbin/modprobe --ignore-install nf_conntrack_ftp; /sbin/modprobe --ignore-install nf_nat_ftp

oder fügen Sie stattdessen einfach zum Beispiel hinzu /etc/modules-load.d/local-nat-ftp.confmit:

nf_nat_ftp

Um sicherzustellen, dass es geladen wird, sollte jetzt dieser Befehl ausgeführt werden:

modprobe nf_nat_ftp

Informationen zur Firewall

Hier ist ein zusätzlicher Hinweis zur Firewall. Es können auch Firewall-Regeln mit einigen Einschränkungen vorhanden sein, anstatt jeden neuen Fluss zuzulassen, der alsverwandtvonKontakt.

Obwohl das FTP-Hilfsmodul beispielsweise sowohl den passiven als auch den aktiven Modus handhabt, könnte man, wenn man aus irgendeinem Grund nur den passiven Modus (mit Datenverbindung vom Client zum Server) und kein „aktives“ FTP (Datenverbindung vom Serverquellport 20 zum Client) zulassen möchte, beispielsweise diese Regeln im Firewall-Teil des Regelsatzes anstelle der üblichen verwenden ct state established,related accept:

ct state established accept
ct state related ct helper "ftp" iif eth0 oif eth1 tcp sport 1024-65535 accept
ct state related ct helper "ftp" drop
ct state related accept 

Andere Art vonverwandtFlows, die nicht mit FTP in Zusammenhang stehen, werden weiterhin akzeptiert (oder können separat weiter aufgeteilt werden)


Beispiel für die Handhabung durch den Helfer

Hier (in einer simulierten Umgebung) sind zweiKontaktListen von Ereignissen gemessen auf demErwartungTisch und dieKontaktTabelle mit den Regeln des OP + den zusätzlichen oben genannten Regeln mit einem Internet-Client 203.0.113.101, der FTP im passiven Modus mit der öffentlichen IP-Adresse 192.0.2.2 des Routers ausführt und nach der Anmeldung einen LIST-Befehl verwendet:

# conntrack -E expect
    [NEW] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp
[DESTROY] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp

gleichzeitig:

# conntrack -E
    [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
 [UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
 [UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 [ASSURED] helper=ftp
    [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
 [UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
 [UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 120 FIN_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 30 LAST_ACK src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
 [UPDATE] tcp      6 120 TIME_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]

Der Start der Erwartung proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157besagt, dass die nächste TCP-Verbindung von 203.0.113.101:* zu 192.0.2.2:37157 zugeordnet wird (Statusverwandt) mit der FTP-Verbindung. Nicht direkt sichtbar, aber da auch das NAT-FTP-Hilfsmodul geladen ist, wurden die tatsächlichen Daten, die vom Server als Antwort auf den PASV/EPSV-Befehl gesendet wurden, abgefangen und übersetzt, sodass der Client eine Verbindung zu 192.0.2.2 statt zu 192.168.1.2 herstellt, was auf dem Client natürlich fehlgeschlagen wäre.

Trotz des zweiten Flusses (zweiterNEULinie), ohne explizite Regel inmein_prerouting, es wurde erfolgreich per DNAT an den Server hinter dem Router übermittelt.


Anmerkungen

  • Wenn der FTP-Steuerport verschlüsselt ist ( AUTH TLS...), kann das Hilfsmodul den ausgehandelten Port nicht mehr ausspionieren und dies kann nicht funktionieren. Man muss auf die Konfiguration eines reservierten Portbereichs sowohl in der FTP-Serverkonfiguration als auch in der Firewall/dem NAT-Router zurückgreifen und den Server so konfigurieren, dass er beim Aushandeln die richtige (öffentliche) IP-Adresse sendet und nicht seine eigene. Und der aktive FTP-Modus kann nicht verwendet werden, wenn der Server keine Route zum Internet hat (wie es hier der Fall zu sein scheint).

  • Erbsenzählerei: Die Prerouting-Priorität von 10 stellt sicher, dass selbst für Kernel < 4.18 NAT bereits für neue Flows erfolgt ist (OP wählte Hook-Prerouting-Priorität 0 statt der üblichen -100, da dies in nftables selten eine Rolle spielt), sodass die Verwendung von daddr 192.168.1.2möglich ist. Wenn die Priorität 0 (oder niedriger als 0) wäre, wäre es vielleicht möglich (nicht überprüft), dass die Regel das erste Paket noch unNATed mit einer öffentlichen IP-Zieladresse sehen würde, aber die folgenden Pakete desselben Flows abfangen würde, da sie direkt von behandelt werdenKontaktmit Priorität -200. Gehen Sie lieber auf Nummer sicher und verwenden Sie 10. Tatsächlich ist dies seit Kernel 4.18 nicht mehr relevant (siehebegehenReferenz inDasausstehender Patch), wobei die NAT-Priorität nur für den Vergleich zwischen mehreren NAT-Ketten relevant ist (und das Mischen von NAT im Iptables-Legacy zusammen mit Nftables ermöglicht).

Antwort2

Nach einigem Herumprobieren bin ich zu folgender nftables.conf gekommen. Diese funktioniert wie vorgesehen und unterstützt NAT in beide Richtungen. Außerdem exportiert sie alle Ports meines Servers bis auf einen in das „öffentliche“ Netzwerk. Port 2222 wird immer noch als „Hintertür“ zum Gateway verwendet, falls ich jemals wieder darauf zugreifen muss :-)

table ip my_nat {
        ct helper ftp-incoming {
                type "ftp" protocol tcp
                l3proto ip
        }

        chain my_prerouting {
                type nat hook prerouting priority 0; policy accept;
                iifname "eth0" tcp dport { 2222 } dnat to :ssh
                iifname "eth0" tcp dport { 1-2221, 2223-65535 } dnat to 192.168.0.2
        }

        chain my_postrouting {
                type nat hook postrouting priority 100; policy accept;
                ip daddr 192.168.0.2 masquerade
                oifname "eth0" masquerade
        }

        chain my_helpers {
                type filter hook prerouting priority 10; policy accept;
                iif "eth0" ip daddr 192.168.0.2 tcp dport ftp ct helper set "ftp-incoming"
        }

}

verwandte Informationen