2
votes

My application connects to FTP clients that are connected to the server via VPN. So far all clients supported active PHP and the library I used went with active FTP by default, so there was no issue. Now however we have installed some new clients that don't properly work over active PHP, so I found out that from the server (via the FTP cli and FileZilla over RDP) can connect to and talk to all clients via a passive connection.

When trying to establish a passive connection in PHP however, all FTP commands (such as nlist) just time out. I came across this blog post, which provides a patch for a specific passive FTP issue (which is now available in regular PHP versions), so I tried testing it like so:

$conn = ftp_connect($address);
$login = ftp_login($conn, 'username', 'password');

ftp_set_option($conn, USEPASVADDRESS, false);
ftp_pasv($conn, true);

$contents = ftp_nlist($conn, '.');

var_dump($contents);

ftp_close($conn);

ftp_pasv returns true, so it is switching over to passive mode, but ftp_nlist times out, which it doesn't for active mode and the compatible clients.

What is so different between PHPs FTP implementation and the FTP cli application?

1
What exact error message you getting from ftp_nlist? + Show "FTP cli" log file (do I understand correctly what you run "FTP cli" from the same machine/server, that you are running you PHP code at?)Martin Prikryl
"FTP cli" is /usr/bin/ftp. ftp_nlist doesn't throw an error, it simply times out and returns false.Padarom
You didn't answer all of my questions.Martin Prikryl
Not sure if ftp even writes a log file, so I don't know where to look for it, all I can give you right now is this: pastebin.com/FUEXbBRN As for the other question, yes, I'm running this on the server that the PHP script is running on.Padarom
So in your PHP code, the $address is 192.168.12.10? + How do you run the PHP code? From command-line? From the same environment as ftp? + Do you have an access to server-side log file? If not, can you do Wireshark capture (or similar)?Martin Prikryl

1 Answers

-1
votes

I think I have figured out what the exact issue was in my case. I'm not sure if this helps anyone else, but it might be an idea to look into if you're having similar issues.

When activating passive mode, the server tells you an IP and a port to connect to for data transfer. When using the ftp CLI the actual PASV command is only sent when you send a data command (like requesting folder content). In those cases the CLI sends the PASV command, receives an IP/port, connects to it and then sends the original command (LIST) through that.

PHP seems to do this differently: As soon as you switch to a passive connection in our code, it sends the PASV command and immediately receives the IP/port from the server - But PHP doesn't yet connect to it. When I then ask for a directory listing, first the ASCII mode gets activated and only then does it connect to the previously received IP/Port to send the LIST command.

My suspicion therefore was that the FTP server I'm connecting to is faulty. My idea was that once it receives a PASV command it waits until someone actually connects to that passive connection, before even starting to accept any other command. In fact I managed to verify just that. While the PHP script was still waiting for a response, I manually established a TCP connection to the received passive port, after which my PHP code resumed running and showing me the results.

Unfortunately for me that means I can't use passive FTP at all with those servers and updating/switching to a different server implementation is not possible. Active FTP also is pretty much impossible since my app is running in Docker.