SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-21

FTP tryb pasywny zawiesza się - jak naprawić firewall

Problem z listowaniem katalogów FTP wynika z blokowania dynamicznych portów danych. Zdefiniuj zakres PassivePorts w konfiguracji serwera i otwórz odpowiedni zakres w firewall.

Dlaczego FTP loguje się, ale lista katalogów zawiesza się

Tryb pasywny FTP nie działa poprawnie za firewallem, ponieważ FTP wykorzystuje dwa połączenia TCP, a nie jedno. Połączenie z portem 21 obsługuje logowanie oraz komendy, więc nazwa użytkownika i hasło są akceptowane, a firewall wydaje się skonfigurowany poprawnie. Pierwsze ls wymaga jednak drugiego połączenia na innym porcie. Żadna reguła firewalla na to nie zezwala, więc klient oczekuje na odpowiedź do momentu przekroczenia limitu czasu.

Rozwiązaniem jest zdefiniowanie stałego zakresu portów dla tych połączeń danych oraz dodanie reguły firewalla zezwalającej na ruch w tym zakresie. Serwer znajdujący się za NAT (network address translation) wymaga dodatkowego ustawienia, aby anonsował właściwy adres IP. Mechanizmy śledzenia połączeń (connection tracking helpers) wykonywały tę pracę automatycznie. Obecnie już tego nie robią i warto poznać przyczynę, zanim skorzysta się z przestarzałego poradnika.

Kanał sterujący i kanał danych

Protokół FTP (file transfer protocol) został zdefiniowany w RFC 959 i powstał przed opracowaniem mechanizmów NAT oraz stanowych zapór sieciowych (stateful firewall). Sesja otwiera jedno połączenie sterujące na porcie TCP 21 i utrzymuje je przez cały czas trwania sesji. Polecenia przesyłane są jako czysty tekst. Odpowiedzi wracają w postaci trzycyfrowego kodu oraz linii tekstu. To połączenie nigdy nie przenosi zawartości plików.

Każdy fragment danych wymaga własnego połączenia TCP: jedno dla listy plików (LIST), jedno dla każdego pobierania (RETR) oraz jedno dla każdego wysyłania (STOR). Połączenie jest otwierane, używane jednorazowo i zamykane. Uwierzytelnianie odbywa się w całości w kanale sterującym, dlatego awaria ścieżki danych zawsze objawia się w ten sam sposób: udanym logowaniem, po którym następuje zawieszenie. Jeśli klient wyświetla odpowiedź 230, a następnie zatrzymuje się na listowaniu plików, problem dotyczy kanału danych, a nie poświadczeń.

Tryb aktywny: serwer nawiązuje połączenie zwrotne z klientem

W trybie aktywnym klient wybiera port, nasłuchuje na nim i informuje serwer, gdzie ma się połączyć:

PORT 192,168,1,50,195,80

Pierwsze cztery liczby to adres IP klienta. Ostatnie dwie to port zakodowany jako dwa bajty: 195 * 256 + 80 = 50000. Następnie serwer otwiera połączenie danych z własnego portu 20 do portu 50000 na kliencie.

Z punktu widzenia klienta połączenie to jest przychodzące i nieoczekiwane, dlatego zapora sieciowa klienta je odrzuca. Jeśli klient znajduje się za domowym routerem, adres w poleceniu PORT jest adresem prywatnym, do którego serwer nie ma dostępu. To właśnie przez tryb aktywny FTP zyskał opinię protokołu, który nie działa.

Tryb pasywny: klient otwiera oba połączenia

Tryb pasywny odwraca kierunek nawiązywania połączenia danych. Klient wysyła PASV, a serwer odpowiada własnym adresem oraz portem:

227 Entering Passive Mode (203,0,113,10,195,80)

Kodowanie pozostaje takie samo, więc klient łączy się z 203.0.113.10 na porcie 50000. Klient otwiera teraz oba połączenia, dlatego tryb pasywny działa poprawnie za NAT-em po stronie klienta i dlatego każdy współczesny klient żąda go w pierwszej kolejności.

Problem został przeniesiony, a nie wyeliminowany. Niezamówione połączenie przychodzące trafia teraz na serwer, na wysoki port, który zmienia się przy każdym transferze. Skoro firewall należy do administratora serwera, problem również staje się jego problemem.

EPSV (rozszerzony tryb pasywny, RFC 2428) opiera się na tej samej koncepcji, oferując czytelniejszą odpowiedź:

229 Entering Extended Passive Mode (|||50000|)

Nie zawiera ona adresu. Klient ponownie wykorzystuje adres, który posiada już dla połączenia sterującego, co umożliwia działanie w sieciach IPv6 i eliminuje całą klasę błędów związanych z NAT. Dokumentacja curl wskazuje, że narzędzie to zazwyczaj próbuje EPSV przed PASV. Port nadal jest wybierany w czasie wykonywania, więc EPSV nie zmienia niczego w regułach firewalla.

Dlaczego standardowa reguła firewalla nie pozwala na otwarcie kanału danych

Ponieważ numer portu nie istnieje w momencie tworzenia reguły. Serwer wybiera go dla każdego transferu indywidualnie. Przy ustawieniach domyślnych, dokumentacja pasv_min_port oraz pasv_max_port wskazuje na 0, co oznacza „użyj dowolnego portu”, więc połączenie danych może nadejść na dowolnym porcie powyżej 1023. sudo ufw allow 21/tcp zezwala jedynie na kanał sterujący i nic więcej, co w praktyce skutkuje poprawnym logowaniem przy jednoczesnym braku możliwości wyświetlenia zawartości katalogu. Jeśli koncepcja usługi nasłuchującej na jednym stałym porcie jest niejasna, sposób działania portów i gniazd nasłuchujących w systemie Linux stanowi niezbędne wprowadzenie.

Firewall stanowy (stateful) śledzi połączenia, a jądro systemu może dopuścić nowe połączenie jako RELATED do już istniejącego. W przypadku FTP wymaga to mechanizmu, który odczyta strumień sterujący i wyodrębni numer portu z linii 227 lub PORT. Domyślnie żaden mechanizm tego nie realizuje.

Dlaczego moduł śledzenia połączeń FTP nie jest już właściwym rozwiązaniem

Starsze poradniki wskazują na moduł jądra nf_conntrack_ftp. Odczytuje on niezaszyfrowany kanał sterujący, znajduje anonsowany port i rejestruje oczekiwanie, dzięki czemu połączenie danych jest akceptowane bez reguły wskazującej konkretny port. Od czasu publikacji tych poradników zmieniły się cztery kwestie.

Automatyczne przypisywanie pomocników jest wyłączone. Dokumentacja jądra określa parametr sysctl nf_conntrack_helper jako "0 - wyłączony (domyślnie)" i dodaje: "Jeśli jest wyłączony, wymagane jest skonfigurowanie reguł iptables w celu przypisania pomocników do połączeń". Samo załadowanie modułu nie przynosi żadnego efektu.

W obecnych wersjach jądra przełącznik został usunięty. Uruchom sysctl net.netfilter.nf_conntrack_helper. Odpowiedź sysctl: cannot stat /proc/sys/net/netfilter/nf_conntrack_helper: No such file or directory oznacza, że jądro nie posiada już funkcji automatycznego przypisywania pomocników. Jeśli otrzymasz w odpowiedzi liczbę, przełącznik nadal istnieje, a jego wartość domyślna to 0.

Narzędzia do zarządzania firewallem również wycofały to rozwiązanie. man ufw-framework w systemie Ubuntu 24.04 odnośnie linii IPT_MODULES w pliku /etc/default/ufw stwierdza: "Bezwarunkowe ładowanie modułów śledzenia połączeń (nf_conntrack_*) w ten sposób jest przestarzałe" i dodaje, że reguły pomocników "muszą być zarządzane poprzez PLIKI REGUŁ". Dokumentacja firewalld określa AutomaticHelpers w firewalld.conf jako "Przestarzałe. Ta opcja jest ignorowana i nie jest już używana". Dołączenie pomocnika wymaga obecnie ręcznego utworzenia jawnej reguły z celem CT, co jest bardziej pracochłonne niż poniższe rozwiązanie i przestaje działać w momencie włączenia TLS. iptables i nftables w systemie Ubuntu zawiera informacje o tym, gdzie faktycznie znajdują się te reguły.

TLS kończy dyskusję. Pomocnik działa poprzez odczyt kanału sterującego jako tekst. Zaszyfruj ten kanał, a pomocnik zobaczy tekst zaszyfrowany, przez co nie będzie w stanie odnaleźć portu. Nie ma na to poprawki i nie powinno jej być: urządzenie pośredniczące zdolne do odczytu kanału sterującego to urządzenie, które odczytało Twoje hasło.

Deklaracja zakresu portów pasywnych na serwerze

Każdy serwer FTP pozwala na wybór zakresu portów pasywnych. Nazwy opcji różnią się w zależności od oprogramowania, dlatego należy sprawdzić dokumentację używanego serwera.

vsftpd, w /etc/vsftpd.conf:

pasv_enable=YES
pasv_min_port=30000
pasv_max_port=30099

pasv_enable domyślnie przyjmuje YES. Obie opcje portów mają domyślnie wartość 0, co oznacza zachowanie "użyj dowolnego portu" opisane powyżej. Zastosuj zmiany za pomocą sudo systemctl restart vsftpd, a następnie potwierdź poprawność działania usługi poleceniem systemctl status vsftpd. vsftpd odmawia uruchomienia w przypadku napotkania niepoprawnej linii konfiguracji, zamiast ją ignorować. Jeśli restart się nie powiedzie, sprawdź journalctl -u vsftpd -n 20 pod kątem linii 500 OOPS: zawierającej wpisaną opcję.

ProFTPD, w proftpd.conf:

PassivePorts 30000 30099

ProFTPD nie definiuje tutaj wartości domyślnej: bez tej dyrektywy port wybiera jądro systemu. Dokumentacja wskazuje również, że gdy żaden port z zadeklarowanego zakresu nie jest wolny, serwer przełącza się na port przydzielony przez jądro i zapisuje komunikat w dzienniku. Zbyt mały zakres powoduje zatem sporadyczne błędy zamiast całkowitego odrzucenia połączenia, co jest znacznie trudniejsze w diagnostyce. Należy używać portów nieuprzywilejowanych, od 1024 wzwyż.

Pure-FTPd przyjmuje flagę -p first:last, opisaną w man pure-ftpd jako "Używaj tylko portów z zakresu od pierwszego do ostatniego włącznie dla pobierania w trybie pasywnym", co "zwiększa kompatybilność pure-ftpd z filtrami pakietów". Pakiety dystrybucyjne zazwyczaj umieszczają tę flagę w pliku konfiguracyjnym, dlatego zamiast zgadywać, należy sprawdzić dokumentację własnej dystrybucji w celu ustalenia nazwy pliku.

Ilu portów potrzeba? Jednego na każde aktywne połączenie danych. Zamknięty port TCP pozostaje w stanie TIME_WAIT przez kilka minut, zanim będzie mógł zostać ponownie użyty, dlatego należy przewidzieć zakres kilkukrotnie większy niż oczekiwane obciążenie szczytowe. Sto portów jest wystarczającą liczbą dla kilku użytkowników, natomiast obciążony serwer publiczny wymaga znacznie większego zakresu.

Gdzie powinien znajdować się zakres? Najpierw uruchom sysctl net.ipv4.ip_local_port_range. W standardowej instalacji Ubuntu wynik to 32768 60999, czyli porty przydzielane przez jądro dla połączeń wychodzących. Zakres pasywny wewnątrz tego okna może kolidować z połączeniem wychodzącym, które już zajmuje dany port, dlatego należy utrzymywać zakres poniżej tej wartości. Zakres od 30000 do 30099 jest bezpieczny w domyślnej konfiguracji. Należy jednak zweryfikować własny system, zamiast polegać na tych wartościach.

Otwarcie tego samego zakresu w zaporze sieciowej

Narzędzie ufw zapisuje zakres z użyciem dwukropka, a dokumentacja wskazuje, że zakres lub lista „mogą być również użyte do określenia wielu portów, w takim przypadku wymagane jest podanie protokołu”:

sudo ufw allow 21/tcp
sudo ufw allow 30000:30099/tcp
sudo ufw status verbose

Polecenie ufw status verbose powinno teraz wyświetlić oba wpisy. To samo polecenie bez /tcp zostanie odrzucone z błędem informującym o konieczności wskazania tcp lub udp, ponieważ ufw nie podejmuje prób odgadnięcia protokołu. składnia reguł ufw na VPS omawia pozostałe kwestie.

Narzędzie firewalld zapisuje zakres z użyciem myślnika i wymaga przeładowania:

sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=30000-30099/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Polecenie --add-service=ftp otwiera port 21/tcp i żąda użycia pomocnika ftp, co jest zdefiniowane w dostarczonej definicji usługi. Nie otwiera ono jednak zakresu pasywnego, więc samodzielnie nie rozwiązuje problemu. strefy i usługi firewalld na VPS przedstawia szerszy kontekst.

W przypadku bezpośredniego użycia nftables, wewnątrz łańcucha wejściowego (input chain):

tcp dport { 21, 30000-30099 } accept

Należy pamiętać o jeszcze jednej zaporze: większość dostawców uruchamia sieciową zaporę w panelu sterowania, poza systemem operacyjnym. Jeśli reguły na serwerze wydają się poprawne, a pakiety nadal nie docierają, należy otworzyć ten sam zakres również w tym miejscu.

Poinformuj serwer o jego publicznym adresie, gdy znajduje się za NAT

Uruchom ip -4 addr show na serwerze. Jeśli adres na interfejsie jest tym, z którym łączą się klienci, pomiń tę sekcję. Jeśli interfejs posiada adres prywatny (10.x, 172.16 do 172.31.x, 192.168.x), a platforma mapuje na niego adres publiczny, serwer nie zna własnego adresu publicznego. Dokumentacja vsftpd określa domyślne zachowanie dla pasv_address jako „adres pobierany z przychodzącego gniazda połączenia”, więc odpowiedź 227 zawiera adres prywatny, a klient jest kierowany w miejsce, do którego nie ma dostępu.

FileZilla nazywa to dokładnie tak:

Server sent passive reply with unroutable address. Using server address instead.

FileZilla naprawia ten problem i kontynuuje działanie. Wiele innych klientów tego nie robi. Próbują połączyć się z 10.0.0.5 i zawieszają się.

curl również ukrywa ten problem, co ma znaczenie, jeśli używasz curl do testów. Instrukcja obsługi podaje, że --ftp-skip-pasv-ip „jest domyślnie włączone (dodane w wersji 7.74.0)”, więc curl ignoruje adres w odpowiedzi 227 i ponownie używa adresu połączenia sterującego. Transfer, który działa z curl, może nadal kończyć się niepowodzeniem w kliencie graficznym z tego właśnie powodu.

Ustaw adres jawnie. vsftpd przyjmuje pasv_address=203.0.113.10 oraz pasv_addr_resolve=YES (domyślnie NO), jeśli wolisz wpisać nazwę hosta. ProFTPD przyjmuje MasqueradeAddress, który akceptuje adres, nazwę DNS lub nazwę interfejsu. Pure-FTPd przyjmuje -P, udokumentowane dla przypadku, w którym „serwer znajduje się za bramą maskującą (NAT)”. EPSV pozwala uniknąć całego problemu, ponieważ odpowiedź nie zawiera pola adresu, ale nie można na tym polegać, ponieważ to klient decyduje, które polecenie wysłać.

Zmiany w obsłudze TLS

FTPS to protokół FTP z wykorzystaniem TLS (transport layer security). Klient łączy się standardowo z portem 21, wysyła AUTH TLS w celu zabezpieczenia kanału sterowania, a następnie wysyła PROT P, aby zaszyfrować również kanał danych. Zwykły protokół FTP przesyła hasło otwartym tekstem, dlatego w przypadku konieczności korzystania z FTP należy używać FTPS. Oprogramowanie vsftpd jest dostarczane z ustawieniem ssl_enable domyślnie ustawionym na NO.

Wynikają z tego dwie kwestie. Żaden mechanizm śledzenia połączeń (connection tracking helper) nie będzie działał, co stanowi drugą stronę powyższego zagadnienia. Ponadto sudo tcpdump -nAi any 'tcp port 21' nie wyświetli już odpowiedzi 227, więc w celu ustalenia, jaki adres i port zostały ogłoszone przez serwer, należy sprawdzić dziennik serwera zamiast analizować ruch sieciowy.

Testowanie zmian z zewnątrz

Polecenia te należy wykonać z innej maszyny. Testowanie z poziomu samego serwera pomija firewall, którego konfigurację próbujesz naprawić.

sudo ss -ltnp | grep :21
curl -v --disable-epsv --user ftpuser:secret ftp://example.com/
nc -vz example.com 30000

ss powinno wykazać, że demon FTP nasłuchuje na porcie 21. W stanie bezczynności serwera żaden proces nie nasłuchuje w zakresie portów pasywnych, ponieważ gniazda te są tworzone na czas transferu i zamykane bezpośrednio po jego zakończeniu.

--disable-epsv wymusza użycie przez curl ścieżki PASV, która ujawnia problem z adresem. Ślad wyświetla odpowiedź serwera, a następnie adres i port, z którym łączy się curl:

< 227 Entering Passive Mode (203,0,113,10,117,52)

117 * 256 + 52 = 30004, co mieści się w zadeklarowanym zakresie. Prywatny adres w tej linii oznacza, że pasv_address nie zostało ustawione. Port spoza zakresu oznacza, że serwer nie wczytał zmiany konfiguracji; sprawdź, czy edytowano plik używany przez działającą usługę.

nc samodzielnie rozstrzyga kwestię firewalla. Natychmiastowe Connection refused oznacza, że pakiet dotarł do serwera i nie znalazł żadnej nasłuchującej usługi, co jest poprawnym wynikiem dla bezczynnego portu pasywnego: reguła działa. Zawieszenie połączenia do momentu, aż nc przerwie operację, oznacza, że coś po drodze odrzuciło pakiet w sposób cichy. Jest to firewall – albo ten na serwerze, albo ten w panelu dostawcy. Rozróżnienie to jest identyczne z tym opisanym w odrzucone kontra przekroczony czas oczekiwania dla SSH i dotyczy każdego portu.

Czy nadal należy korzystać z FTP?

W przypadku nowych wdrożeń – nie. SFTP (SSH file transfer protocol) działa w ramach pojedynczego połączenia SSH na porcie 22. Nie wymaga drugiego kanału, zakresu portów pasywnych, konfiguracji NAT ani dodatkowego demona, ponieważ zapewnia to OpenSSH. sftp user@example.com działa na serwerze, na którym nigdy nie konfigurowano usługi przesyłania plików. Aby udostępnić komuś pliki bez nadawania innych uprawnień, sshd_config wykorzystuje ForceCommand internal-sftp wraz z ChrootDirectory. Katalog ten musi należeć do użytkownika root i nie może być zapisywalny dla użytkownika, w przeciwnym razie sshd odrzuci sesję i zapisze w dzienniku linię bad ownership or modes for chroot directory.

FTP znajduje zastosowanie w sytuacjach, gdy druga strona nie może zmienić konfiguracji. Skanery i urządzenia wielofunkcyjne posiadają oprogramowanie układowe obsługujące wyłącznie FTP. Sprzęt laboratoryjny i przemysłowy często działa w oparciu o stały obraz systemu, którego nikt nie podda ponownej certyfikacji. Partnerzy biznesowi udostępniają punkt zrzutu FTPS i nie dodadzą nowego protokołu dla jednego dostawcy. W każdym z tych przypadków konfiguracja zakresu pasywnego wraz z odpowiednią regułą firewalla stanowi pełne rozwiązanie, przy czym należy stosować FTPS zamiast zwykłego FTP. Architektura dwukanałowa to rozwiązanie z 1985 roku, które obecnie funkcjonuje w środowisku, dla którego nie zostało zaprojektowane – historię tę opisano w historii protokołów przesyłania plików.

FAQ

Dlaczego logowanie do FTP przebiega pomyślnie, ale lista katalogów zawiesza się?

Logowanie wykorzystuje wyłącznie połączenie sterujące na porcie 21, które jest dozwolone przez firewall. Lista katalogów wymaga drugiego połączenia TCP na innym porcie, a to połączenie jest blokowane. Należy zdefiniować zakres portów pasywnych na serwerze FTP i otworzyć ten sam zakres w firewallu, aby lista katalogów mogła zostać pobrana. Zawieszanie się listy katalogów to problem kanału danych, a nie hasła.

Jakie porty należy otworzyć dla trybu pasywnego FTP?

Port 21 dla kanału sterującego oraz wybrany zakres dla pasywnych połączeń danych. Nie istnieje standardowy zakres, ponieważ konfiguruje go administrator. Zakres taki jak 30000 do 30099 jest odpowiedni: należy dobrać jego wielkość do szczytowej liczby jednoczesnych transferów i upewnić się, że nie pokrywa się z zakresem portów wychodzących jądra, który można sprawdzić za pomocą sysctl net.ipv4.ip_local_port_range. Jeśli dostawca udostępnia firewall sieciowy w panelu sterowania, należy otworzyć w nim ten sam zakres.

Czy nadal potrzebuję nf_conntrack_ftp?

Nie, a w przypadku nowoczesnego jądra nie można na nim polegać. Automatyczne przypisywanie pomocników (helpers) jest domyślnie wyłączone, a w nowszych wersjach jądra przełącznik net.netfilter.nf_conntrack_helper został usunięty, przez co sysctl zgłasza brak pliku. Dokumentacja ufw uznaje bezwarunkowe ładowanie tych modułów za przestarzałe, a firewalld całkowicie ignoruje AutomaticHelpers. Pomocnik musi również odczytywać kanał sterujący jako tekst jawny, więc przestaje działać w momencie włączenia FTPS. Zamiast tego należy zdefiniować zakres portów pasywnych.

Dlaczego klient FTP zgłasza, że odpowiedź pasywna zawiera adres nieosiągalny?

Serwer odpowiedział PASV adresem, który widzi na własnym interfejsie, a jest to adres prywatny. Dzieje się tak, gdy platforma mapuje adres publiczny na prywatny. Należy jawnie ustawić adres publiczny: pasv_address w vsftpd, MasqueradeAddress w ProFTPD lub -P w Pure-FTPd. FileZilla obchodzi ten problem, ponownie używając adresu, z którym już się połączyła, i loguje komunikat "Using server address instead" – dlatego niektórzy klienci działają mimo błędnej konfiguracji, a inni zawieszają się.

Czy używać FTPS czy SFTP?

SFTP należy stosować wszędzie tam, gdzie kontroluje się obie strony: jedno połączenie przez SSH na porcie 22, brak konieczności otwierania kanału danych i gotowość do pracy bez dodatkowej konfiguracji. FTPS to FTP przez TLS, więc zachowuje architekturę dwóch kanałów i wszystkie związane z nią problemy z firewallem. Należy go wybrać tylko wtedy, gdy druga strona nie obsługuje innego protokołu. Nie należy używać zwykłego FTP przez Internet, ponieważ hasło jest przesyłane w sieci jako tekst jawny.