Chapter 5. Configuration problems

1. How do I add another anonymous login or guest account?
2. How do I ftp as root?
3. How do I provide a secure upload facility?
4. How can I stop my users from using their space as a warez repository
5. Can I rotate files out of an upload directory after upload?
6. How can I hide a directory from anonymous clients.
7. File/Directory hiding isn't working for me!
8. I want to prevent users from accessing a hidden directory
9. How do I setup a virtual FTP server?
10. I only want to allow anonymous access to a virtual server.
11. How does <Limit LOGIN> work, and where should I use it?
12. How can I limit users to a particular directory tree?
13. How do I create individual anonymous FTP sites for my users?
14. I want to support normal login and Anonymous under a particular user
15. Why doesn't Anonymous ftp work (550 login incorrect)?
16. Bandwidth control
17. CHMOD isn't working
18. How can I limit the size of uploaded files?
19. Can I disable Anonymous logins?
20. Limiting the connections per loginID
21. How do I configure proftpd to allow transfer resumption (for downloads and uploads)?

Problems encountered in trying to make the server behave exactly as required after compilation and installation are complete and the server is running.

1. 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.

2. How do I ftp as root?

First off this is a bad idea ftping as root is insecure, there are better more secure ways of shifting files as root.

To enable root ftp ensure that the directive "RootLogin on" is included in your configuration.

3. How do I provide a secure upload facility?

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>
  # All files uploaded are set to username.usergroup ownership
  User username
  Group usergroup
  UserAlias ftp username
  AuthAliasOnly on
  RequireValidShell off

  <Directory pub/incoming/>
     <Limit STOR CWD>
        AllowAll
     </Limit>
     <Limit READ RMD DELE MKD>
        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.

4. How can I stop my users from using their space as a warez repository

The above fragment will control anonymous users however if a local user with a full account with up and download capability is abusing their space then the technical measures which can be taken are limited. Applying a sane system quota is a good start, using the mod_quota and mod_ratio modules may control the rates of upload/download making it less useful as a warez repository. In the end it comes down to system monitoring and good site AUP's and enforcement.

5. Can I rotate files out of an upload directory after upload?

Yes. You'll need to write a script which either checks the contents of the directory regularly and moves once it's detected no size change in a file for xyz seconds. Or a script which monitors an upload log. There is no automatic method for doing this.

6. How can I hide a directory from anonymous clients.

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. For example:

<Anonymous ~ftp>
...
<Directory Private>
HideGroup staff
</Directory>
...
</Anonymous>
          

7. File/Directory hiding isn't working for me!

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.

8. I want to prevent users from accessing a hidden directory

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).

9. How do I setup a virtual FTP server?

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.

10. I only want to allow anonymous access to a virtual server.

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>
          

11. How does <Limit LOGIN> work, and where should I use it?

The <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 snippet 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>
...
          

12. How can I limit users to a particular directory tree?

For general open access you can use an <Anonymous> directive context block, possibly in combination with a UserPassword/AnonRequirePassword directive.

However if you wish to jail an entire group (or groups) of users, you can use the DefaultRoot directive. 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 example, 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).

Security Implications

The DefaultRoot directive is implemented using the chroot(2) system call. This moves the "/" (or root) directory to a specified point within the file system and jails the user into this sub-tree. However this is not the holy grail of security, a chroot jail can be broken, it is not a trivial matter but it's nowhere near impossible. DefaultRoot should be used as part of a general system of security not the only security measure.

A more detailed http://www.bpfh.net/simes/computing/chroot-break.html on this subject and on the breaking of chroot jails has been written by Simon Burr

Non-root server issues

The chroot() system call will not work under a non-root ftp server process, the call requires root privaliges. Without them it simply doesn't work, there doesn't appear to be any checking in the code of the uid/gid before calling chroot so using DefaultRoot in such a setup will cause the server to fail.

Symlinks

Symlinks will not work from within a chrooted area. The reason should be clear from a casual inspection of the nature of the chroot command. It is not possible to have a symbolic link to a directory which can"t be reached beacuse it's outside of the current chroot. Work arounds to allow access to other parts of the file system include exporting the part of the filesystem to be accessed from inside the chroot and mounting via NFS, using hard file links or (on Solaris) using lofs to mount the directory via the loopback.

mount -Flofs /home/data1 /ftp/data1
mount -Flofs /home/data2 /ftp/data2
          

As of the 2.4.x Linux kernel tree it is possible to mount filesystems multiple times and to mount subdirectories of filesystems elsewhere on the filesystem.

13. How do I create individual anonymous FTP sites for my users?

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 deferred <Directory> block to carefully limit outside access to each user's site.

  1. Create a new unix group on your system named `anonftp". Please each user who will have per-user anonymous FTP in this group.

  2. Create an `anon-ftp" and `anon-ftp/incoming" directory in each user's home directory.

  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 virtual host, 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 virtual host.
     DefaultRoot ~/anon-ftp
     # Finally, force all logins to be anonymous for the anonftp group
     AnonymousGroup anonftp
     
     </VirtualHost>
                  

14. I want to support normal login and Anonymous under a particular user

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.

15. Why doesn't Anonymous ftp work (550 login incorrect)?

Things to check

Check the following first:

  • 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.

  • 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.

  • 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 mentioned elsewhere in this FAQ.

16. Bandwidth control

A new patch providing the TransferRate directive has been provided and is slated for inclusion in 1.2.8, this gives per-connection bandwidth limits with Class support. The limits are more effective against downloads than uploads.

There is no method to control the total bandwidth a single VirtualHost context can use.

17. CHMOD isn't working

AllowChmod is deprecated and has been replaced with the SITE_CHMOD expansion for controlling this functionality.

18. How can I limit the size of uploaded files?

As of 1.2.7rc1 there are two new directives MaxRetrieveFileSize and MaxStoreFileSize to control the maximum size of files being transfered to or from the server.

19. Can I disable Anonymous logins?

Yes, just remove all the <Anonymous> sections from your configuration file and reload the daemon.

20. Limiting the connections per loginID

As of 1.2.7rc1 MaxClientsPerUser has been implemented.

21. How do I configure proftpd to allow transfer resumption (for downloads and uploads)?

To allow downloads to be resumed, you need to use the AllowRetrieveRestart configuration directive.

To allow uploads to be resumed, you need to use both the AllowOverwrite and AllowStoreRestart directives. The reason that both need to be allowed is that a restarted/resumed upload is a form of overwriting the file.

Also note that using HiddenStores and AllowStoreRestart is incompatible, as mentioned in the documentation for the AllowStoreRestart and HiddenStores directives.