The FreeBSD Diary
Providing practical examples since 1998If you buy from Amazon USA, please support us by using this link.
installing an alternative ftp daemon - proftpd 10 November 1999
I decided to install another ftp server. Mainly because I was having a small
problem with the default ftp server which I didn't want to spend the time fixing.
The problem was with chroot. If I placed a user in /etc/ftpchroot, they
were unable to use the ls command. I understand this is because the ls
executable must be placed within the chroot tree. That makes sense. However, I
didn't want to do that. I also liked the idea that proftpd does not depend
upon any external executables. It is entirely independent.
See also Creating a chroot ftpd.
Another selling point for me, with respect to proftpd, was the apache-like configuration. If you are familiar with the httpd.conf, the proftp.conf file concepts will be easy for you to pick up.
|And since I have the entire ports tree, all I needed to do
# cd /usr/ports/ftp/proftpd su: cd: /usr/ports/ftp/proftpd: No such file or directory
Oh oh! Why don't I have that? I checked the http://www.freebsd.org/ports/ page to see if proftpd was listed in the ftp section. It was. So my ports were out of date. Time to fix that. It was pretty easy. I used the instructions found in Updating the ports collection. When doing this, I could have modified my ports-supfile and commented out everything except the ftp section. But I didn't. I wanted all my ports updated.
So I started again:
# cd /usr/ports/ftp/proftpd # make
Again, I started getting errors. This time it was complaining about not being able to get autoconf-2.12.tar.gz I think. Hmmm, where does that live? A quick:
# locate autoconf
shows it's from /usr/ports/devel/. A quick check again at http://www.freebsd.org/ports/ finds that the current version is 2.13. So my ports are out of date. I had not been updating the devel directory. So I uncommented that line from the ports-supfile and ran cvsup again. After that, I started with the install again:
# make # make install
Of note was this output from the install:
===> Installing for proftpd-1.2.0p8 ### As of proftpd 1.2.0p5 and later, you need to edit /etc/pam.conf to add support for ftp. To do so, add the following two lines to this file: ftp auth required pam_unix.so try_first_pass ftp account required pam_unix.so try_first_pass ### ===> Generating temporary packing list ===> Compressing manual pages for proftpd-1.2.0p8 ===> Registering installation for proftpd-1.2.0p8
I'm not sure if this will be relevant or not. It turned out it was.
|The main configuration file is /usr/local/etc/proftpd.conf.
I was running this daemon standalone. That's the default configuration. So I commented out the line in /etc/inetd.conf for ftp. Don't forget to HUP inetd (like I did):
# killall -HUP inetd
After making changes to the config file so as to enable anonymous ftp (see config file and below), I started the server:
Then I checked to see if it was running:
# ps -auwx | grep ftp #
Hmmm, there's nothing there. Time to check for error messages:
# tail /var/log/messages Nov 10 23:14:20 ducky proftpd: attempted bind to 0.0.0.0, port 21 Nov 10 23:14:20 ducky proftpd: bind() failed in inet_create_connection(): Address already in use Nov 10 23:14:20 ducky proftpd: Check the ServerType directive to ensure you are configured correctly.
DOH! I forgot to HUP inetd.
# killall -hup inetd # /usr/local/libexec/proftpd # tail /var/log/messages Nov 10 23:18:20 ducky proftpd: ProFTPD 1.2.0pre8 standalone mode STARTUP
OK. That's looking much better!
|With my initial testing, I was unable to connect with any user/password combination.
Most annoying. Checking the messages again, I find this:
Nov 10 23:25:35 ducky proftpd: USER dan: incorrect password from fred.yourdomain.org [10.0.0.1] to 10.0.0.2:21
Hmmm, but my password is correct. I dunno. But anonymous ftp is working.
Eventually I remembered the bit about PAM from the install process and added those bits to the PAM configuration file. But that didn't fix it either. At this point, I went to bed.
The problem was PAM
|After posting a message to the firstname.lastname@example.org
I found the solution. It appears that my version of FreeBSD does not support
PAM. What's PAM you say? If you check /etc/pam.conf, you'll see
this: Pluggable Authentication Modules. And from man pam:
PAM Is a system of libraries that handle the authentica- tion tasks of applications (services) on the system. The library provides a stable general interface (Application Programming Interface - API) that privilege granting pro- grams (such as login(1) and su(1)) defer to to perform standard authentication tasks.
The solution was found at http://hamster.wibble.org/proftpd/ and it involves adding the following line to /usr/local/etc/proftpd.conf:
Note: FreeBSD 3.3 does support PAM. I know because that was the version I used when Installing an ftp server. And there I also used proftpd.
|The first thing you might want to do is add an anonymous ftp user. Look at http://hamster.wibble.org/proftpd/ for the
configuration options. Here is more or less my anonymous settings:
<Anonymous ~ftp> DirFakeUser on ftpd DirFakeGroup on ftpd User ftp Group ftp ### We want clients to be able to login with "anonymous" as well as "ftp" UserAlias anonymous ftp ### Limit the maximum number of anonymous logins MaxClients 10 ### It is wise when making an 'ftp' user that you either block its ### ability to login either via /etc/login.access or my giving it ### an invalid shell. ### Uncomment this if the 'ftp' user you made has an invalid shell RequireValidShell off ### We want 'welcome.msg' displayed at login, and '.message' displayed ### in each newly chdired directory. DisplayLogin welcome.msg DisplayFirstChdir .message ### Limit WRITE everywhere in the anonymous chroot <Limit WRITE> DenyAll </Limit> <Directory incoming/*> <Limit READ DELE RMD RETR MKD> DenyAll </Limit> <Limit WRITE CWD> AllowAll </Limit> </Directory> <Directory bin> HideNoAccess </Directory> </Anonymous>
|One of the things which proftpd does, as do other daemons, is allow you to have virtual ftp servers. Much like virtual websites in apache, it allows a single host to respond with different files for different server names. See virtual ftp servers - proftpd for more detail.|
|I wanted to ensure that proftpd started at boot time. So I created
# cat /usr/local/etc/rc.d/proftpd.sh #!/bin/sh /bin/mkdir -p /var/run/proftpd if [ -x /usr/local/libexec/proftpd ]; then /usr/local/libexec/proftpd && echo -n ' proftpd' fi
Remember to set the permissions correctly or it won't be executed:
chmod 711 proftpd.sh
|Here is a non-anonymous user. It assumes you have a user and group
called Susan. Uploads will be done in the user's home directory.
<Anonymous ~susan> user susan group susan AnonRequirePassword on </Anonymous>
Common shell problem
|The login I created for Susan was an ftp-only login. She is not allowed to use
telnet or ssh. Therefore, when I created her, I assigned a shell of /nonexistent.
But when I tested the connection I encountered a slight problem:
$ ftp ftp.mydomain.org Connected to ftp.mydomain.org. 220 ftp.mydomain.org Name (ftp.mydomain.org:dan): susan 331 Password required for susan. Password: 530 Login incorrect. ftp: Login failed.
In the logs for ftp.mydomain.org I found this
- USER susan (Login failed): Invalid shell.
There are two problems here. First, I gave Susan a login shell of /nonexistent. Second, this shell is not listed within /etc/shells. It is the latter issue which results in the above error message. For more information about nologin, please see this article.
To correct this problem, I changed Susan's login shell to /sbin/nologin after first ensuring this shell existed:
# ls -l /sbin/nologin -r-xr-xr-x 1 root wheel 1990 Dec 6 05:57 /sbin/nologin
And here is what was in /etc/shells after I added the /sbin/nologin entry.
# $FreeBSD: src/etc/shells,v 220.127.116.11 1999/08/29 14:19:02 peter 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 /usr/local/bin/bash /sbin/nologin
After fixing the above, I found that Susan's login worked and resulted in the following log entry:
ANON susan: Login successful.