FTP uses two TCP connections! The first connection is setup by the client when it connects to an FTP server, and is called the control connection. As the initial connection, it gets to handle authentication and changing to the correct directory on the remote server, etc. When the client then is ready to transfer a file, a second TCP connection is established and the data is transferred over that.
This setting up of a second connection causes nuisances and headaches for several reasons.
The client can opt to ask the server to connect to the client to set it up, a
so-called "active" connection. This is done with the PORT or EPRT
commands. Allowing a remote host to connect back to a client on a port that
the client opens up requires that there's no firewall or other network
appliance in between that refuses that to go through and that is far from
always the case. You ask for an active transfer using curl -P [arg]
(also
known as --ftp-port
in long form) and while the option allows you to specify
exactly which address to use, just setting the same as you come from is almost
always the correct choice and you do that with -P -
, like this way to ask
for a file:
curl -P - ftp://example.com/foobar.txt
You can also explicitly ask curl to not use EPRT (which is a slightly newer
command than PORT) with the --no-eprt
command-line option.
Curl defaults to asking for a "passive" connection, which means it sends a PASV or EPSV command to the server and then the server opens up a new port for the second connection that then curl connects to. Outgoing connections to a new port are generally easier and less restricted for end users and clients, but it then requires that the network in the server's end allows it.
Passive connections are enabled by default, but if you have switched on active
before, you can switch back to passive with --ftp-pasv
.
You can also explicitly ask curl not to use EPSV (which is a slightly newer
command than PASV) with the --no-epsv
command-line option.
Sometimes the server is running a funky setup so that when curl issues the
PASV command and the server responds with an IP address for curl to connect
to, that address is wrong and then curl fails to setup the data
connection. For this (rare) situation, you can ask curl to ignore the IP
address mentioned in the PASV response (--ftp-skip-pasv-ip
) and instead use
the same IP address it has for the control connection even for the second
connection.
Using either active or passive transfers, any existing firewalls in the network path pretty much have to have stateful inspection of the FTP traffic to figure out the new port to open that up and accept it for the second connection.