- Professional FTP Daemon -
Configuration - Frequently Asked Questions
ProFTPD doesn't seem to work, I start it but it doesn't show up in a `ps'. What's wrong?
It could be many things, possibly something like not running proftpd as root (it needs to be run as root initially, but will switch to a non-privileged user). Regardless, proftpd logs all errors via the standard syslog mechanism. You need to check your system logs in order to determine what the problem is.
   
My syslog has errors in it such as "inet_create_connection() failed: Operation not permitted".
I use the shadow password suite. Users cannot login to ProFTPD.
You aren't starting proftpd as root, or you have inetd configured to run proftpd as a user other than root. The proftpd daemon must be started as root in order to bind to tcp ports lower than 1024, or to open your shadow password file when authenticating users. The daemon switches uid/gids to the user and group specified by the User/Group directives during normal operation, so a `ps' will show it running as the user you specified.
   
When I try to start proftpd from the command line, all I see is "Fatal: Socket operation on non-socket", and proftpd does not start.
You have proftpd configured to run in inetd mode instead of standalone. In this mode, proftpd expects that it will be run from the inetd super-server, which implies that stdin/stdout will be sockets instead of terminals. As a result, socket operations will fail and the above error will be printed. If you wish to run proftpd from the shell, in standalone mode, you'll need to modify your proftpd.conf configuration file and add or edit the ServerType directive to read:

ServerType standalone
   
I'm having problems with FTP clients behind firewalls, they cannot seem to get directory listings or transfer files. I've checked and it seems that proftpd isn't using port 20 as the source port for it's data connections; can this be changed?
There is a known security problem with ALL unix FTP daemons, which requires the daemon to retain root privileges even after a client has fully authenticated. In proftpd versions 1.0.x, we chose to ignore RFC959's port 20 requirements in the interests of security. Unfortunately, over time, it became obvious that this was a bad idea. Until the RFC is "fixed", this problem will continue to plague unix FTP servers.

In proftpd versions 1.1.x and higher, we chose to go the "standard" route, retaining root at all times, allowing the daemon to bind to port 20 and be completely RFC959 compliant. The security issue remains, however the code is carefully structured to handle this in as secure a fashion as possible.

You have two options for working around this problem:

1. Upgrade to proftpd 1.1.x (development versions).

2. Have your FTP clients use passive mode. Passive mode data connections originate from the client, and thus do not experience this "port 20" problem.
   
I cannot get Anonymous FTP to work. I've tried all the sample configuration files, however no matter what I try, every time I attempt to login to proftpd as 'ftp' or 'anonymous' I get "550 Login incorrect.".
Check the following first:

1. Make sure the user/group you specified inside the <Anonymous> block actually exists. This must be a real user and group, as it is used to control whom the daemon runs as and authenticates as.

2. If RequireValidShell is not specifically turned off, make sure that your "ftp user" (as specified by the User directive inside an <Anonymous> block), has a valid shell listed in /etc/shells. If you do not wish to give the user a valid shell, you can always use "RequireValidShell off" to disable this check.

3. If UseFtpUsers is not specifically turned off, make sure that your "ftp user" is not listed in /etc/ftpusers.

If all else fails, you should check your syslog. When authentication fails for any reason, proftpd uses the syslog mechanism to log the reason for failure; using the AUTH (or AUTHPRIV) facility. If you need further assistance, you can send email, including related syslog entries and your configuration file, to the proftpd mailing list at: proftpd-l@evcom.net.
   
What should I add or remove from my /etc/inetd.conf in order to run proftpd from the inetd super-server?
Find the line in /etc/inetd.conf that looks something like this:
ftp stream tcp nowait root in.ftpd in.ftpd

Replace it with:
ftp stream tcp nowait root in.proftpd in.proftpd

Then, find your inetd process in the process listing and send it the SIGHUP signal so that it will rehash and reconfigure itself. Example (do not type the following literally, as pid 189 will most likely NOT be your inetd process):
kill -1 189
   
Can I use tcp-wrappers with proftpd?
Sure. Although ProFTPD has built-in IP access control (see the Deny and Allow directives), many admins choose to consolidate IP access control in one place via in.tcpd. Just configure proftpd to run from inetd as any other tcp-wrapper wrapped daemon does:
ftp stream tcp nowait root in.tcpd in.proftpd
   
How do I add another anonymous login or guest account?
You should look in the sample-configurations/ directory from your distribution tarball. Basically, you'll need to create another user on your system for the guest/anonymous ftp login. For security reasons, it's very important that you make sure the user account either has a password or has an "unmatchable" password. The root directory of the guest/anonymous account doesn't have to be the user's directory, but it makes sense to do so. After you have created the account, put something like the following in your /etc/proftpd.conf file (assuming the new user/group name is private/private):

<Anonymous ~private>
AnonRequirePassword off
User private
Group private
RequireValidShell off
<Directory *>
<Limit WRITE>
DenyAll
</Limit>
</Directory>
</Anonymous>


This will allow ftp clients to login to your site with the username 'private' and their e-mail address as a password. You can change the AnonRequirePassword directive to "on" if you want clients to be forced to transmit the correct password for the 'private' account. This sample configuration allows clients to change into, list and read all directories, but denies write access of any kind.
   
How do I allow uploads to a specific directory in a secure fashion? I don't want users downloading or creating sub-directories in it.
The following snippet from a sample configuration file illustrates how to protect an "upload" directory in such a fashion (which is a very good idea if you don't want people using your site for "warez"):

<Anonymous /home/ftp>

User ftp
Group ftp
UserAlias anonymous ftp

<Directory *>

<Limit WRITE>
DenyAll
</Limit>

</Directory>

<Directory incoming>

<Limit STOR>
AllowAll
</Limit>
<Limit READ>
DenyAll
</Limit>

</Directory>

</Anonymous>

This denies all write operations to the anonymous root directory and sub-directories, except "incoming/" where the permissions are reversed and the client can store but not read. If you used <Limit WRITE> instead of <Limit STOR> on <Directory incoming>, ftp clients would be allowed to perform all write operations to the sub-dir, including deleting, renaming and creating directories.

   
How can I hide a directory from anonymous clients. I only want clients getting in to it if they know the exact name.
Use the HideUser or HideGroup directive in combination with the proper user/group ownership on the directive. For example, if you have the follow directory in your anonymous ftp directory tree:

drwxrwxr-x 3 ftp staff 6144 Apr 21 16:40 private

You can use a directive such as "HideGroup staff" to hide the private directory from a directory listing. Example:

<Anonymous ~ftp>
...
<Directory Private>
HideGroup staff
</Directory>
...
</Anonymous>
   
File/Directory hiding isn't working for me! I can still see the file or directory when performing an anonymous FTP?
You need to make sure that the group you are hiding isn't the anonymous ftp user's primary group, or HideGroup won't apply.
   
I have a hidden directory, but I want to prevent users from accessing it altogether. How can I do this?
You can either change the permissions on the directory to prevent the anonymous FTP user from accessing it, or if you want to make it appear completely invisible (as though there is no such directory), use the IgnoreHidden directive inside a <Limit> block for one or more commands that you want to completely ignore the hidden directory entries (ignore = act as if the directory entry does not exist).
   
How do I setup a virtual FTP server?
First off, have you read the documentation that came with the server? If not, do so now. If you still have questions, read on:

You'll need to configure your host to be able to handle multiple IP addresses. This is often called "aliasing", and can generally be configured through an IP alias or dummy interface. You need to read your operating system documentation to figure out how to do this. Once your have the host configured to accept the additional IP address that you wish to offer a virtual FTP server on, use the <VirtualHost> configuration directive to create the virtual server:

<VirtualHost 10.0.0.1>
ServerName "My virtual FTP server"
</VirtualHost>


You can add additional directive blocks into the <VirtualHost> block in order to create anonymous/guest logins and the like which are only available on the virtual host.
   
I don't want to let my normal FTP users into my virtual FTP servers using their usernames/passwords. I only want anonymous FTP to work for a virtual server. How can I do this?
Use a <Limit LOGIN> block to deny access at the top-level of the virtual host, then use <Limit LOGIN> again in your <Anonymous> block to allow access to the anonymous login. This permits logins to a virtual anonymous server, but denies to everything else. Example:

...
<VirtualHost 10.0.0.1>
ServerName "My virtual FTP server"
<Limit LOGIN>
DenyAll
</Limit>
<Anonymous /usr/local/private>
User private
Group private
<Limit LOGIN>
AllowAll
</Limit>
...
</Anonymous>
</VirtualHost>
   
Can I run an FTP server on another port besides the standard ftp port (21) without running a separate copy of ProFTPD?
Yes. Use a <VirtualHost> block with your machine's FQDN (Fully Qualified Domain Name) or IP address, and a Port directive inside the <VirtualHost> block. For example, if your host is named "myhost.mydomain.com" and you want to run an additional FTP server on port 2001, you would:

...
<VirtualHost myhost.mydomain.com>
Port 2001
...
</VirtualHost>
   
How does <Limit LOGIN> work, and where should I use it?
The <Limit LOGIN> directive is used to control connection or login access to a particular context (the directive block which contains it). When a client initially connects to proftpd, the daemon searches the configuration tree for <Limit LOGIN> directives, and attached parameters (such as Allow, Deny, etc). If it determines that there is no possible way for the client to ever be allowed to login, such as a "Deny from" matching the client's source address, without an overriding "Allow from" at a lower level, the client is disconnected without being offered the opportunity to transmit a user and password. However, if it is possible for the client to be allowed a login, proftpd continues as per normal, allowing the client to login only if the proper <Limit LOGIN> applies. Normally, <Limit> directive blocks are allowed in the server config, <VirtualHost>, <Anonymous> and <Directory> contexts. However, <Limit LOGIN> should not be used in a <Directory> context, as clients do not connect/login to a directory (and thus it is meaningless).

By way of example, the following configuration snippit illustrates a <Limit LOGIN> deny which will cause any incoming connections from the 10.1.1.x subnet to be immediately disconnected, without a welcome message:

...
<Limit LOGIN>
Order deny,allow
Deny from 10.1.1.
Allow from all
</Limit>
...


Next, an example of a configuration using <Limit LOGIN> that will not immediately disconnect an incoming client, but will return "Login invalid" for all login attempts except anonymous.

...
<Limit LOGIN>
DenyAll
</Limit>
<Anonymous ~ftp>
...
<Limit LOGIN>
AllowAll
</Limit>
...
   
How can I limit one or more user sessions to a particular directory tree? (chroot jail)
You can use an <Anonymous> directive context block, possibly in combination with a UserPassword/AnonRequirePassword directive. If you wish to jail an entire group (or groups) of users, you can use the DefaultRoot directive (available only in 0.99.0pl7 and above). DefaultRoot lets you specify a root jailed directory (or '~' for the user's home directory), and an optional group-expression argument which can be used to control which groups of users the jail will be applied to. For example:

...
<VirtualHost myhost.mynet.foo>
DefaultRoot ~
...
</VirtualHost>


This creates a configuration where all users who log into myhost.mynet.foo are jailed into their home directories (cannot chdir into a higher level directory). Alternatively, you could:

...
<VirtualHost myhost.mynet.foo>
DefaultRoot /u2/public users,!staff
...
</VirtualHost>


In this sample, all users who are members of group 'users', but not members of group 'staff' are jailed into /u2/public. If a user does not meet the group-expression requirements, they login as per normal (not jailed, default directory is their home).

You can use multiple DefaultRoot directives to create multiple jails inside the same directive context. If two DefaultRoot directives apply to the same user, proftpd arbitrarily chooses one (based on how the configuration file was parsed).
   
  The following questions and answers apply to proftpd version 1.1.3 and later only! None of these features will work in 1.0.x versions.
   
How do I create anonymous FTP sites for my users? Creating a separate <Anonymous> configuration for each user is too difficult.
There are two methods of accomplishing this (possibly more). First, you can create a directory structure inside your anonymous FTP root directory, creating a single directory for each user and setting ownership/permissions as appropriate. Then, either create a symlink from each user's home directory into the FTP site, or instruct your users on how to access their directory.

The alternate method (and more versatile) of accomplishing per-user anonymous FTP is to use AnonymousGroup in combination with the DefaultRoot directory. You'll probably want to do this inside a <VirtualHost>, otherwise none of your users will be able to access your system without being stuck inside their per-user FTP site. Additionally, you'll want to use a defered <Directory> block to carefully limit outside access to each user's site.

Step 1: Create a new unix group on your system named `anonftp'. Please each user who will have per-user anonymous FTP in this group.
Step 2: Create an `anon-ftp' and `anon-ftp/incoming' directory in each user's home directory.
Step 3: Modify your /etc/proftpd.conf file to look something like this (you'll probably want to customize this to your needs):

<VirtualHost my.per-user.virtual.host.address>

# the next line limits all logins to this virtualhost, so that only anonftp users can connect

<Limit LOGIN>
DenyGroup !anonftp
</Limit>

# limit access to each user's anon-ftp directory, we want read-only except on incoming

<Directory ~/anon-ftp>

<Limit WRITE>
DenyAll
</Limit>

</Directory>

# permit stor access to each user's anon-ftp/incoming directory, but deny everything else

<Directory ~/anon-ftp/incoming>

<Limit STOR>
AllowAll
</Limit>

<Limit READ WRITE>
DenyAll
</Limit>

</Directory>

# provide a default root for all logins to this virtualhost.
DefaultRoot ~/anon-ftp
# Finally, force all logins to be anonymous for the anonftp group
AnonymousGroup anonftp

</VirtualHost>

How do I create an Anonymous configuration that runs as a particular user, but still allow the user to login normally? I don't want to have to use a separate virtual host.
You can use the AuthAliasOnly directive to control how and where real usernames get authenticated (as opposed to aliased names, via the UserAlias directive). Note that it is still impossible to have two identical aliased names login to different anonymous sites; for that you would need <VirtualHost>.

Example:

...
<Anonymous ~jrluser>

User jrluser
Group jrluser
UserAlias ftp jrluser
UserAlias anonymous jrluser
AuthAliasOnly on
...

</Anonymous>

Here, the <Anonymous> configuration for ~jrluser is set to allow alias authentication only. Thus, if a client attempts to authenticate as 'jrluser', the anonymous config will be ignored and the client will be authenticated as if they were a normal user (typically resulting in `jrluser' logging in normally). However, if the client uses the aliased username `ftp' or `anonymous', the anonymous block is applied.