This month Mark shows us the safe and painless way to set up anonymous ftp on your system.
The standard ftp daemon that comes with recent Slackware distributions, and which is used by many—perhaps most—anonymous ftp sites, is the wu.ftpd which comes from Washington University at Saint Louis. It offers many useful features, including:
Extensible support for get filename.gz when only filename exists, and for get filename when only filename.gz exists (auto-gzip and auto-gunzip), and similar functionality for .Z (compress).
Extensible support for get dir.tar (auto-tar)
Ability to limit the number of connected users based on location
Ability to easily change configuration
You can get the most recent copy of wu.ftpd at sunsite.unc.edu as /pub/Linux/system/Network file-transfer/wu-ftpd-2.4.linux.tar.gz. Be sure not to get the wu-ftpd-2.4.patch.gz file that exists there—the file wu-ftpd-2.4.linux.tar.gz is already patched, and applying wu-ftpd-2.4.patch.gz removes the patches.
Once you uncompress and untar the file, you'll have a wu-ftpd-2.4.linux directory containing all the source files. The configuration for wu.ftpd is slightly different than most packages you may install for Linux. For example, you don't use make. You execute the build script with the lnx option:
trippy:~/wu-ftpd-2.4.linux> build lnx
Before you do that, you may want to change the configuration files. The config.h configuration file usually does not need to be changed. The more important configuration src/pathnames.h file tells the daemon where various files, including the bianary, are located. The INSTALL file in the source root directory explains each of the entries in the configuration files.
During the build, you may notice a number of warnings from GCC. Many of them relate to SIGBUS being redefined. The second warning will tell you where it was previously declared. This is okay. It just means GCC noticed that two header files defined the same thing, in this case SIGBUS.
After the build is complete, you may wish to back up and remove the old ftpd program. Using /sbin/pkgtool, which comes with most Slackware releases, is an easy way to do this. You will want to view tcpip. Write down the locations of files that have ftp or in.ftp in them. After this, you can back up and remove the existing files. This way, you can be sure you have a clean installation.
When you are ready to install, use su to assume root status, then type build install, which will copy the binaries to the correct locations. By default, the daemon itself goes in /usr/local/etc/, support files go in /usr/local/bin/, and man pages go in /usr/local/man/.
Last, create the ftp user, by either manually editing /etc/passwd as root (be careful!) or by using the useradd command. Optimally, ftp should have “*” as an encrypted password, be in its own group (you probably want to create an ftp group for this, if there isn't one already); and have /bin/true as a login shell. Having /bin/true as a shell means that even if someone is able to break into the account, they will be automatically logged out, as /bin/true immediately exits (you can also use /bin/false). When you're done editing the ftp user in /etc/passwd, it should look something like this:
The two numbers may be different, and the /home/ftp may be different if your users have another path to access their home directories (like /user/ftp), but you get the general idea.
Now on to the fun part—setting up the configuration files. This may appear at first to be a large task, but once a configuration is set up, it requires very little maintenance—if it is set up correctly the first time. The obvious advantage to having many configuration files is that you don't have to re-compile wu.ftpd to add or modify features.
Before we go into the configuration files, I have to explain how anonymous ftp works from an administration point of view. In order to preserve the security of legitimate users of the system, ftpd changes its root directory so that it can only see a small part of the filesystem. That is, when you type cd / during an anonymous ftp connection, you don't really go to the real root directory, the one that normal users see. A chroot(2) function call changes the root of ftpd to the home directory for user ftp in /etc/passwd. In my case, the root for an anonymous user becomes /home/ftp relative to me, a legitimate user of the system. From here on, I'll call the root for an anonymous user “ftp” root or “~ftp/” and the `/' or `root directory' will be the root directory you know and love.
First, we have to set up files in our root directory. The ~/wu-ftpd-2.4.linux/doc/examples directory contains a number of sample files that will work for most situations. These files include ftpusers, ftpaccess, and ftpconversions. They should be installed in the /etc directory after modifying it for your local setup.
The ftpusers file contains a list of users who are not allowed to connect via ftp. This increases the security by not allowing users such as “root” to connect and possibly overwrite a file like /etc/passwd. Users are listed one per line.
The ftpaccess file is the primary ftpd configuration file. It sets up certain definitions of users, configures the major sections of security, and a previous number of other functions. The ftpaccess file in the examples directory should be fine for most people, but if you expect large numbers of people connecting for anonymous ftp use, you can use the ftpaccess.heavy file. Here are a few things you will want to look at in whichever ftpaccess files you use:
loginfails int—This sets the number of unsuccessful log in attempts allowed before ftpd disconnects.
class class typelist addrglob
[addrglob...]—This sets up a class of users. typelist can be real for real users of the system, anonymous for anonymous users of the system, and guest for guest accounts (which aren't quite like anonymous). addrglob lists where someone is coming from, either in IP (or dot—198.30.149.*) notation, or name notation (*.satelnet.org). This allows you to set up a group as local users (anonymous users who are on your same subnet for example) and a group for remote users who might be outside the local subnet. A setup could look like this:
class local real,guest,anonymous 198.30.149.* class remote real,guest,anonymous *
limit class n time msg file—This sets up limits on class of users, limiting access to n users during time. If they can't get in, display the text in the file ~ftp/msg file. Time is defined as in UUCP's L.sys file, but for those of you who can't find that file, the times are rather easy. Sunday is represented as `Su', Monday as `Mo' and so on. These can be followed by times in 24-hour format. So, to limit the number of remote users to 5 except for weekends and at night (when the limit goes to 10):
limit remote 10 SaSu|Any1800-0600 /etc/msgs/msg.toomany limit remote 5 Any /etc/msgs/msg.toomany
The default ftpaccess.heavy file seems to have this backwards. Also, if a limit is not valid (i.e. you put fubar as a limit) or it is -1, this is taken to be unlimited users.
passwd-check none|trivial|rfc822 warn|enforce—This sets up how the ftpd should respond when given a password for an anonymous login. There are three methods that you can have for allowing passwords:
none—We don't care what the password is (you can log in as guest)
trivial—Has a @ in the name (you can log in as komarimf@)
rfc822—Must be an RFC822 complaint address (full username and host)
If you have set trivial or rfc822 and the user does not comply with the requested password format, you can do two things:
warn—tells the user that an invalid password was entered, gives a suggested password, but lets the user log in anyway
enforce—tells the user the password is invalid, gives a suggested password, then logs the user out.
readme file when—tells the user to be sure to read the ~ftp/<file> during when. when can be on login or on certain directories. For example, the entries:
readme README* login readme README* cwd=*
will notify you of all the README files (README*) upon login, and any time you change directory. Note that you may want to change this to just README if you have a large number of README files in a directory.
message file when—This is almost the same as the readme entries above, only the ~ftp/file is output to the user's screen during when.
shutdown file—If file exists, ftpd will not allow any logins. This gives you a good way of shutting down ftp without having to edit /etc/inetd.conf and restarting inetd, then doing the reverse to get it all working again. In fact, all you need do is type (in this case):
and no more logins will be allowed. Notice that connected users are not disconnected automatically via this method. You bump connected users off the system, and I'll get to that in a bit.
Finally, there is the ftpconversions file. One of the features of wuftpd is that it allows you to download files in a format different from the on the remote side. That is, you can automatically compress a text file as it gets sent to you, making the transfer go quicker. Or you can get an entire directory bundled up in one .tar file, ready to put on a floppy disk. There are few modifications you should make to this, as the .tar and .gz (for gzip) already exist to allow you to tar, compress, untar, and uncompress a file on the fly. This should go in /etc/ftpconversions. Other files are placed under ~ftp/. For example, you have to install the gzip and tar binaries, plus the shared libraries necessary to run the commands. Change directory to ~ftp/bin (use mkdir to create it first, if it does not exist) and execute the following:
cp /bin/ls . cp /bin/gzip . chmod 0111 *
This will copy the binaries, then make them both execute only.
Next you'll need the libraries. Go into the ~ftp/lib directory (or make it and do the following:)
cp /lib/libc.so.4 .
Yes, you can make a hard link, and you can also use statically linked executables. If you feel confident in your abilities to do either, you can do it.
You could also have a copy of /etc/passwd. Without it, when regular users of the system make files available to anonymous ftp users, user and group names (only the literal UID and GID as they are stored in the filesystem) will show up. So to resolve numbers to names, you'll need copies of both /etc/passwd and /etc/group in ~ftp/etc/. However, you don't need encrypted passwords or other information in the passwd file, only the UID, GID, and username. So you can replace all the passwords in the copied passwd file (be sure you're editing the correct file!!) with stars (*), then erase all the fields after the GID, leaving you with entries like:
The downside of this (for the extremely security conscious) is that a remote user could now know login names for legitimate users. Then again, you can change the names of the valid users of the system to something else. What could be better than letting a cracker spend all day (without success and increasing his chances of getting caught) trying to crack an account named “bob” on your machine who he saw as the owner of a file on anonymous ftp?
To be sure that the files are set up correctly, run the ~\wu-ftpd-2.4.linux/bin/ckconfig program. It will verify the locations of various files needed to run.
Speaking of security—now is the time to make sure that files are as they should be. You don't want anyone getting free access to your system, do you? Here's how the directories in ~ftp/ should be laid out:
Execute only (mode 0111 in chmod): ~ftp/bin and ~ftp/etc
Read and execute (mode 0555 in chmod): ~ftp/pub, ~ftp/usr, and ~ftp/var (if you want it—or it can be a link to ~ftp/usr)
Write and execute (optionally read too—0333 or 0777 in chmod): /incoming
Incoming is a special directory where users are allowed to place incoming files. From here, the files are then moved by the ftp administrator to another location. Many sites have their incoming directories set up so that any file that is uploaded can immediately be downloaded by another anonymous user. But, an unscrupulous user can upload an illegal program for immediate download by anyone else. In the time it takes the ftp administrator to discover the file and erase it, hundreds of people could have downloaded it. By denying read access to the directory, users can put files there, but not see them. Instead you get a message about “permission denied”.
The execute-only directory is also special in that while anonymous users can run the programs in that directory (tar and ls usually), they can't get a directory of what is there, nor can they put anything in the directory. This is good because it prevents an anonymous user from finding out what kinds of programs are available, and also allows extra security on the ~ftp/etc/passwd and ~ftp/etc/group files.
Now your ftp site should be ready for allowing incoming users. If you had to install wu.ftpd, make your changes to /etc/inetd.conf by adding the following line:
ftp stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/ftpd
This assumes that you want the tcpd(8) wrapper and that the ftpd binary is located in /usr/local/bin. An ftp line may already be in the file, so you may have to only edit it. Restart inetd with a killall -HUP inetd, and sit back and relax.
If you are interested in watching how popular your ftp site is, a few programs can help. The ftpcount tells you how many users of each class are connected to your machine, and what the maximum is. ftpwho gives you slightly better information about who is logged in, and ftpshut is used to bump connected users off at a specific time. The xferstats program in the util directory can give you detailed reports of when most people connect, what gets downloaded, and other information that may help you fine-tune your configuration.
wu.ftpd has many more abilities than I have described here, such as the ability to create “private” directories and groups to allow only certain anonymous ftp users access to directories. There are also provisions for logging access information via syslogd(8) and file transfer information to /var/adm/ftpd/xferlog. There's a man page for xferlog(5) too. Both of these methods of logging are set up by default.
If you have any questions about setting up ftp on your linux machine, or any questions, comments, or even complaints about this article, please e-mail me at email@example.com.