1

On a server I'm using a Perl script which is scheduled to regularly download a few files using FTP from another server. Unfortunately, there's some issue in the Perl FTP module which causes the script to fail and terminate unexpectedly from time to time. I found that this issue can be easily resolved by switching from passive mode to the active mode.

If I understand the difference between these two FTP modes correctly, using the active mode would mean that I need to open up a certain port range within my firewall. I presume that this comes with some security risks. So my question is whether there's some workaround or a good practice so I can use the active mode on my server in a way it doesn't cause any additional risks.

1
  • preemptive answer that will probably show up: use sftp Jul 18, 2011 at 18:37

3 Answers 3

6

In a nutshell:

  • FTP connections consist of two streams: command (control) and data
  • When a socket is opened and code does not explicitly bind to a port, the OS will consume a high numbered port in its ephemeral port range (sysctl -a | grep ip_local_port_range)
  • Non-root processes must use ports >1024

Active Mode FTP

Client connects to server over port 21 and establishes a command stream:

client:32198 -> server:21

Client must send or receive some data, so it informs the server to connect back to it on some port. To do this, it sends a PORT command similar to this:

PORT 1,2,3,4,5,6

This is the client informing the server that the server may connect back to the client (at address 1.2.3.4 on port (5 * 256) + 6 = 1286.

server:20 -> client:1286

Typically, this is where you see active mode FTP sessions die; with respect to firewalls and load balancers, the traffic normally flowing from client -> server is expected, but connections initiated by the server to the client are often denied (load balancers are often smart enough to tie associate this data stream with the existing command stream).

Your understanding about needing to open a port range on your firewall to facilitate this behavior is absolutely correct.

Passive Mode FTP

In this scenario, the client establishes a command session as before:

client:56221 -> server:21

But when data is communicated, the client sends a PASV command primitive. The server responds with an IP:Port combination that the client should connect back to (in a similar format to the PORT request earlier. So the client then connects to the server as follows:

client:12347 -> server:4566

This bypasses the firewall issues described above for active mode because the connections are established in a traditional and expected manner.

The downside to passive mode is that it consumes more sockets on the server. Issuing frequent PASV primitives in a heavily loaded environment could eventually lead to port exhaustion. (Sockets will linger in a TIME_WAIT state for some OS-defined amount of time (~2 minutes I think on Redhat systems).

About your problem

Unless you really are suffering from port exhaustion issues, it is highly unusual that passive mode would fail and active mode would more often succeed. Usually is is the other way around. If you are able to post more about the errors you occasionally receive, we can debug it further.

I would recommend using passive mode wherever possible, and so I would recommend looking into the passive-mode specific failures to find the root cause of your issue before conceding to using active mode FTP.

5
  • I dint want to post the script source here as that would be more StackOverflow kind of question. However, Im using ordinary ftp->get() method from Net::FTP and when I turn on the Debug flag I get the following error: Can't use an undefined value as a symbol reference at dataconn.pm line 54. and the script dies That is obviously a Net::FTP module related error. After some googling I found that this is resolved by using the active mode instead as the error doesn't seem to be fixed in the newer versions of the module.
    – NumberFour
    Jul 18, 2011 at 19:01
  • @NumberFour: So do some good for the community and fix the error yourself.
    – womble
    Jul 18, 2011 at 23:34
  • 1
    @womble: I would if I was an experienced Perl programmer, Im rather more like a Perl user. There's been also a lots of bug reports on this issue.
    – NumberFour
    Jul 18, 2011 at 23:49
  • Consider this a learning experience then. Gain the acclaim of lesser Perl users everywhere by fixing a bug everyone's talking about. Dare to dream big, and one day you too can play at Carnegie Hall!
    – womble
    Jul 18, 2011 at 23:51
  • That error indicates that the Net::FTP module is not testing the availability of the data connection before attempting to utilize it. While it manifests as an error in the Perl code, the underlying issue is that the FTP server is either never permitting the client to establish a data connection, or it is permitting the client to establish a data connection and then it goes away (perhaps it times out due to server side idle timeout or something?). Jul 19, 2011 at 2:15
1

With active mode the client connects to the server on port 21 for a control channel, then when a download begins the client begins listening on a socket with a random port number above 1024 for the server to connect to.

In order to allow active mode FTP then the client's firewall needs to allow all incoming traffic above port 1024, which defeats the purpose of a firewall.

Passive mode means that the server listens on port 20 and the client initiates the connection.

You should always use passive mode with FTP. Or better yet, don't use FTP. If you're downloading a file it's best to use HTTP. If you need to upload a file, still do it with HTTP (or another protocol such as scp).

1
  • A proper client-side firewall should be snooping ftp control traffic and allowing the requested connection when using active mode. In practice, using passive mode Just Tends to Make Thing Work.
    – MikeyB
    Jul 18, 2011 at 19:49
1

the issue has nothing to due with the Perl itself. More, the solution of setting active FTP connections instead of passive ones is exactly the proof.

Actually, the problem above will occur when trying to list content of a FTP directory, not when connecting or uploading/downloading. Hence, the problem is firewall related.

You have to check whether your firewall allows the passive FTP connections passing through, read the excellent description of loopforever above.

One catch, if using a Linux based firewall, is to unload the nf_conntrack_ftp memory.

1
  • 1
    Maybe it's just a language issue but I can't make any sense out of what you wrote. Sep 26, 2012 at 12:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .