Active and passive are the two modes that FTP can run in.
For background, FTP actually uses two channels between client and server, the command and data channels, which are actually separate TCP connections.
The command channel is for commands and responses while the data channel is for actually transferring files.
This separation of command information and data into separate channels a nifty way of being able to send commands to the server without having to wait for the current data transfer to finish. As per the RFC, this is only mandated for a subset of commands, such as quitting, aborting the current transfer, and getting the status.
In active mode, the client establishes the command channel but the server is responsible for establishing the data channel. This can actually be a problem if, for example, the client machine is protected by firewalls and will not allow unauthorised session requests from external parties.
In passive mode, the client establishes both channels. We already know it establishes the command channel in active mode and it does the same here.
However, it then requests the server (on the command channel) to start listening on a port (at the servers discretion) rather than trying to establish a connection back to the client.
As part of this, the server also returns to the client the port number it has selected to listen on, so that the client knows how to connect to it.
Once the client knows that, it can then successfully create the data channel and continue.
More details are available in the RFC: https://www.ietf.org/rfc/rfc959.txt
The timeout doesn't happen until you try to send the data, so you were able to connect to the server successfully. The only difference I see is that ftplib uses passive mode by default, whereas your command-line client does not appear to. Try doing
ftp.set_pasv(False)
before initiating the transfer and see what happens.
Note that non-passive mode is essentially obsolete because it cannot be used across NAT firewalls, so you should probably configure vsFTP to allow passive mode.
Best Answer
This means that when the FTP server opens a second port for your client to connect to, your client (libcurl) fails to reach it. It is most likely due to a firewall or other network equipment somewhere along the way that blocks your ability to do the request operation.
Alternative reasons could be a wrongly configured ftp server, but if it works for other users, that seems less likely.
Another reason for failure may be that you have an active firewall that doesn't know EPSV and thus gets confused by it and ruins it for you. Try without it by setting CURLOPT_FTP_USE_EPSV to 0.
You can try to the active approach instead (which is what most older style FTP clients do by default), which makes the client ask the server to connect back to you instead. You activate that in libcurl with CURLOPT_FTPPORT. (See the docs for exact details on how to use it.)