Setting up the FTP Server

[ref. OpenBSD FAQ System Management -> Setting up Anonymous FTP Services | [PF: Issues with FTP](http://www.openbsd.org/faq/pf/ftp.html)]

Security Warning: Default ftpd behaviour is to allow all users access to the root-directory, this can be a significant compromise. Use -A, anonymous access which is chroot to /home/ftp. Valid User accounts can be forced ftp access only to their home directories (eg. /home/janedoe)

Again: chroot is not the default behaviour of ftpd.

Secure Alternative A (also known as "I've just discovered sftpserver")

Get your clients to use an ftp client that supports Secure FTP or sftp. OpenBSD delivers OpenSSH (since 2.6) which also has a component for secure ftp (sftp - unix client, sftpserver - unix server [since 2.9?].) If you require secure FTP then you will have the 'features' of FTP together with the security of OpenSSH.

An Open Source Windows ftp client that supports sftp is FileZilla or commercial-ware GlobalScape's CuteFTP

Secure Alternative B (also known as, document what you've been using)

Although less interactive, and in my experience much slower than ftp, you can use a combination of OpenSSH's ssh client and scp (Secure Copy.) This is a reasonable alternative using character based Unix shells.

A number of MS Windows clients which I have used including WinSCP, Putty, and iXplorer. You could also go for commercialware from the originators, SSH Secure Shell at www.ssh.com. For a more complete list of alternative clients please visit the OpenSSH website.

Configure ftp login

Before we can setup the ftp user account, we 1st need to configure the 'shell' we will allocate for anonymous users: /usr/bin/false.

Configure the Shell.

The /usr/bin/false is a short sh script that exits if any user attempts to connect to the system through the account. It is installed during the default installation but not included in /etc/shells, which provides the options for shells for user accounts.

File: /usr/bin/false

#! /bin/sh
#             CONTENTS OF /usr/local/false
# $OpenBSD: false.sh,v 1.2 1996/06/26 05:32:50 deraadt Exp $

exit 1

Edit the file: /etc/shells and include a line to /usr/bin/false. Verify that false is in the /usr/bin directory. The /etc/shells file should end up looking similar to the below.

Edit: /etc/shells

# $OpenBSD: shells,v 1.5 1997/05/28 21:42:20 deraadt Exp $
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/sh
/bin/csh
/bin/ksh
/usr/local/bin/bash
/usr/bin/false

Configure ftp account

Create the ftp account using "adduser" with the below option, and a blank password.

User Name: ftp
Full Name: Anonymous FTP
Shell: false
Login Group: ftp
Invite to other Groups: No
Enter Password []: <<leave-blank>>
Set the password so that user cannot logon? (y/n) [n]: y

Configure ownership and permissions for directories

Change/ensure the ownership of the ftp root directory is owned by root, and files are read-only.

# chown root.root /home/ftp
# chmod 555 /home/ftp
# mkdir /home/ftp/pub
# chmod 555 /home/ftp/pub

We change the mode to readonly execute, so people can traverse directories and read the files but cannot delete or move files.

From the man pages (and FAQ,) the below are suggested directories, but are not required for the server to operate.

~/ftp/bin Make this directory owned by "root" and unwritable by anyone (mode 511). This directory is optional unless you have commands you wish the anonymous ftp user to be able to run (the ls(1) command exists as a builtin). Any programs in this directory should be mode 111 (executable only)
~/ftp/etc Make this directory owned by "root" and unwritable by anyone (mode 511). The files pwd.db (see pwd_mkdb(8)) and group(5) must be present for the ls command to be able to produce owner names rather than numbers. The password field in pwd.db is not used, and should not contain real passwords. The file motd, if present, will be printed after a successful login. These files should be mode 444
~/ftp/pub Make this directory mode 555 and owned by "root". This is traditionally where publically accessible files are stored for download

Restrict User Access

/etc/ftpusers List of unwelcome/restricted users
/etc/ftpchroot List of normal users who should be chroot'd

To maximise security we take a look at denying access to some users, and restricting access to everyone else.

Deny Access: Add users we want to have no access to the ftp services into the /etc/ftpusers file. The standard installation prevents access by special service accounts (eg. root, bin, daemon, operator, uucp, www, named.) To be safe, consider adding other accounts used by daemon services, such as: mysql, samba to /etc/ftpusers.

With the -A switch we effectively deny access to accounts not listed in the /etc/ftpchroot file.

Restrict Access: (chroot) If you provide ftp access for your user-accounts, add all users (not restricted above) to /etc/ftpchroot. ftpd will allow access by ftp accounts to the root directory, we can enforce some security by allowing chroot to force each login into their private directory.

Restrict Using login.conf

[Ref: login.conf(5), ftpd(8) | e-mail from Joakim Aronius | OpenBSD 3.0]

OpenBSD's login classes give us another method for structuring security privileges for our ftp clients. /etc/login.conf is the configuration file that determines your grouping/privilege settings.

In login.conf one can add default values for any user class:

  1. adding 'ftp-chroot' to the user class will chroot everyone in that class. This can be used instead of adding users in /etc/ftpchroot.
  2. adding 'ftp-dir=/home/ftp' will make all class users chroot to /home/ftp without changing each users home directory.

The simplest example, is to merely change the 'default' setting. In the example below, our login.conf settings will ensure all accounts are chrooted without the need to enter all users into the /etc/ftpchroot file.

e.g. Extract from the file /etc/login.conf

default:\
   :path=/usr/bin /bin /usr/sbin /sbin /usr/X11R6/bin /usr/local/bin:\
   :umask=022:\
   :datasize-max=256M:\
   :datasize-cur=64M:\
   :maxproc-max=128:\
   :maxproc-cur=64:\
   :openfiles-cur=64:\
   :stacksize-cur=4M:\
   :localcipher=blowfish,6:\
   :ypcipher=old:\
   :tc=auth-defaults:\
   :tc=auth-ftp-defaults:\
   :ftp-chroot:\
   :ftp-dir=~:

With the above settings we are ready to roll with our more secured, chrooted ftp server.

From the man pages of ftpd(8)

LOGIN.CONF Variables

The ftpd daemon uses the following ftp specific parameters:
(auth-ftp and welcome not listed here.)

ftp-chroot A boolean value. If set, users in this class will be automatically chrooted to the user's login directory.
ftp-dir A path to a directory. This value overrides the login directory for users in this class. A leading tilde (`~') in ftp-dir will be expanded to the user's home directory based on the contents of the password database.

A users class is set in the fifth field of the user record in the passwd(5) file. This field is not set on new users when you add them with adduser etc, hence we all become default. (the other pre defined classes are daemon and staff)

If you do not wish for all users to be treated the same, then you could add a new class (e.g.'ftpusers'.) This way you can set a whole bunch of parameters specific to only these users.

Gratitudes to Joakim Aronius for pointing (and documenting) this out for us.

Enable ftpd through /etc/rc.conf.local

To auto-start ftpd with each system start-up we change the settings in the /etc/rc.conf.local We can also manually start the service with the same flags at the command prompt.

Edit /etc/rc.conf.local:

ftpd_flags="-DllUSA" # for non-inetd use: ftpd_flags="-D"

Starting ftpd at the command-prompt

You can also enable ftpd through inetd (described in the FAQ) but making the above settings in the /etc/rc.conf.local is what I like. Obviously, we can now start the ftpd server manually from the command-line.

# /usr/libexec/ftpd -DllUSA

The command will run ftpd in the background and you are now ready to check your ftp server whether it has been configured correctly.

Reference:

From the man pages:

The switches listed above are described further [man pages.]

D Detach and become a daemon, accepting connections on the FTP port and forking child processes to handle them. This has lower overhead than starting ftpd from inetd(8) and is thus useful on busy servers to reduce load.
l

lower-case L, log successful and failed ftp(1) session using syslog.

When specified twice (eg. -ll,) the log will also include: retrieve (get), store (put), append, delete, make directory, remove directory and rename operations and their filename arguments.

U Log each concurrent ftp(1) session to the file /var/run/utmp, making them visible to commands such as who(1).
S Log all anonymous downloads to the file /var/log/ftpd when this file exists.
A Permit only anonymous ftp connections or accounts listed in /etc/ftpchroot. Other connection attempts are refused.

Other configuration files of interest are:

/etc/nologin The file can be used to disable ftp access. If the file exists, ftpd displays it and exits.
/etc/ftpwelcome Welcome notice. This holds the Welcome message for people once they have connected to your ftp server.
/etc/motd Welcome notice after login. This holds the message for people once they have successfully logged into your ftp server
.message This file can be placed in any directory. It will be shown once a user enters that directory.
/var/run/utmp List of users on the system
/var/run/ftpd.pid Process id if running in daemon mode
/var/log/ftpd Log file for anonymous downloads

Other Links

FTP Server Behind a NAT Gateway Using OpenBSD 3.0 http://www.svartalfheim.net/natftp.html