pyftpdlib Frequently Asked Questions

1.0 - Introduction

1.1 - What is pyftpdlib?

pyftpdlib is a high-level library to easily write asynchronous portable FTP servers with Python.

1.2 - What is Python?

Python is an interpreted, interactive, object-oriented, easy-to-learn programming language. It is often compared to Tcl, Perl, Scheme or Java.

1.3 - I'm not a python programmer. Can I use it anyway?

Yes. pyftpdlib is a fully working FTP server implementation that can be run "as is". For example, (after having installed a Python interpreter) you could run an anonymous ftp server from cmd-line by running:

python -m pyftpdlib.FTPServer

Customizing ftpd more deeply requires a python script which imports pyftpdlib to be written separately. Customizing ftpd for basic tasks like adding users or deciding where log file should be placed is mostly simply editing variables. This is basically like learning how to edit a common unix ftpd.conf file and doesn't really require Python knowledge.

1.4 - Documentation

http://code.google.com/p/pyftpdlib/ is the primary source for all information about the project including Tutorial, Wikis and the Bug Tracker.

1.5 - Mailing lists

There are a number of mailing lists for pyftpdlib:

Name E-mail Web Interface Description
pyftpdlib-users pyftpdlib@googlegroups.com topics This is intended for end user support.
pyftpdlib-commit pyftpdlib-commits@googlegroups.com topics This list receives all change notifications for code in the Subversion repository. Unless you're a pyftpdlib developer you will probably not be interested in it.
pyftpdlib-issues pyftpdlib-issues@googlegroups.com topics This list receives all change notifications from the Bug Tracker. Unless you are involved into pyftpdlib development you will probably not find this useful.

1.6 - Bug reporting

Bug reports should be made via Google Code Issue Tracker. Patches should be attached to the appropriate bug and not mailed directly to the mailing lists or any given team member.

2.0 - Installing and compatibility

2.1 - How do I install pyftpdlib?

First download latest package release release from the Download Page, then unpack it into a directory (on unix: tar -zxf pyftpdlib_0.x.x.tar.gz) and run:

python setup.py install

If you're on Windows it should be enough just running:

setup.py install

2.2 - Which Python versions are compatible?

Python 2.3 and higher.

2.3 - Which one is recommended?

Python 2.4 or 2.5 because of the newer collection.deque object which provides better performances for file transfers.

2.4 - On which platforms can pyftpdlib be used?

pyftpdlib should work on any platform where select( ) or poll( ) are available. The development team has mainly tested it under various Linux and Windows systems and OS X. A port for FreeBSD systems is also available and maintained by Li-Wen Hsu <lwhsu@freebsd.org>.

3.0 - Usage

3.1 - Why do I get socket.error "Permission denied" error on ftpd starting?

Probably because you're on a unix system and you're trying to start ftpd as an unprivileged user. ftpserver.py binds on port 21 by default and only super-user account (e.g. root) could bind sockets on such ports. If you want to bind ftpd as non-privileged user you should set a port higher than 1024.

3.2 - How can I prevent the server version from being displayed?

Just override and modify banner attribute of FTPHandler class.

3.3 - Can control upload/download ratios?

Yes. There's an example of a hack around asyncore socket_map in the Tutorial wiki.

3.4 - Are there ways to limit connections?

FTPServer class comes with two overridable attributes defaulting to zero (no limit): max_cons, which sets a limit for maximum simultaneous connection to handle by ftpd and max_cons_per_ip which set a limit for connections from the same IP address. Overriding these variables is always recommended to avoid DoS attacks.

3.5 - I'm behind a NAT / gateway

When behind a NAT a ftp server needs to replace the IP local address displayed in PASV replies and instead use the public address of the NAT to allow client to connect. By overriding masquerade_address attribute of FTPHandler class you will force pyftpdlib to do such replacement. However, one big problem still exists. The passive FTP connections will use ports from 1024 and up, which means that you must forward all ports 1024-65535 from the NAT to the FTP server! And you have to allow many (possibly) dangerous ports in your firewalling rules! To resolve this, simply override passive_ports attribute of FTPHandler class to control what ports proftpd will use for its passive data transfers. Value expected by passive_ports attribute is a list of integers (e.g. range(60000, 65535)) indicating which ports will be used for initializing the passive data channel.

3.6.1 - What is FXP?

FXP is part of the name of a popular Windows FTP client: http://www.flashfxp.com. This client has made the name "FXP" commonly used as a synonym for site-to-site FTP transfers, for transferring a file between two remote FTP servers without the transfer going through the client's host. Sometimes "FXP" is referred to as a protocol; in fact, it is not. The site-to-site transfer capability was deliberately designed into RFC 959. More info can be found here: http://www.proftpd.org/docs/howto/FXP.html.

3.6.2 - Does pyftpdlib support FXP?

Yes. It is disabled by default for security reasons (see RFC 2257 and FTP bounce attack description) but in case you want to enable it just set to True the permit_foreign_addresses attribute of FTPHandler class.

4.0 - Implementation

4.1 - Globbing / STAT command implementation

Globbing is a common Unix shell mechanism for expanding wildcard patterns to match multiple filenames. When an argument is provided to the STAT command, ftpd should return directory listing over the command channel. RFC 959 does not explicitly mention globbing; this means that FTP servers are not required to support globbing in order to be compliant. However, many FTP servers (including pyftpdlib) do support globbing as a measure of convenience for FTP clients and users. In order to search for and match the given globbing expression, the code has to search (possibly) many directories, examine each contained filename, and build a list of matching files in memory. Since this operation can be quite intensive, both CPU- and memory-wise, pyftpdlib limits the search to only one directory non-recursively, which is identical to the LIST command implementation in pyftpdlib.

4.2 - ASCII transfers / SIZE command implementation

Properly handling the SIZE command when TYPE ASCII is used would require to scan the entire file to perform the ASCII translation logic (file.read().replace(os.linesep, '\r\n')) and then calculating the len of such data which may be different than the actual size of the file on the server. Considering that calculating such result could be very resource-intensive it could be easy for a malicious client to try a DoS attack, thus pyftpdlib do not perform the ASCII translation. However, clients in general should not be resuming downloads in ASCII mode. Resuming downloads in binary mode is the recommended way as specified in RFC 3659.

4.3 - IPv6 support

IPv6 support for FTP including EPRT & EPSV commands is a feature defined in RFC 2428. There is currently no official support for IPv6 within the 0.2.x code tree.

4.4 - SSL/TLS support

SSL/TLS support including AUTH, ADAT, PROT, PBSZ, CCC, MIC, CONF and ENC commands is a feature defined in RFC 2228. There is currently no official support for SSL/TLS within the 0.2.x code tree. Contributors willing to help add support for these protocols are greatly appreciated.