OS Used: Gentoo, Mandriva 2007, openSUSE 11.0
First written: June 2007
Last updated: September 2008
While this howto has been aimed at Gentoo users, I have however used this same setup on both Mandriva and OpenSUSE Installations.
* net-ftp/pure-ftpd
Latest version available: 1.0.21-r1
Latest version installed: [ Not Installed ]
Size of files: 464 kB
Homepage: http://www.pureftpd.org/
Description: Fast, production-quality, standard-conformant FTP server.
License: BSD
Install pure-ftpd with MySQL and SSL support.
server ~ # echo "net-ftp/pure-ftpd mysql ssl" >> /etc/portage/package.use server ~ # emerge -D net-ftp/pure-ftpd
Create users and group for file access
server ~ # groupadd -g 4400 ftpgroup server ~ # adduser -u 4401 -d /home/ftpROOT -s /bin/false -g ftpgroup ftpread server ~ # adduser -u 4402 -d /home/ftpROOT -s /bin/false -g ftpgroup ftpwrite server ~ # mkdir /home/ftpROOT server ~ # chown ftpwrite: /home/ftpROOT server ~ # chmod 750 /home/ftpROOT
Create MySQL database. (You can just copy and paste the below into the mysql command prompt. Be sure to change the password though.)
CREATE DATABASE ftp; USE ftp; CREATE TABLE users ( User VARCHAR(64) BINARY NOT NULL, Password VARCHAR(256) BINARY NOT NULL, Uid INT(11) NOT NULL default '4401', Gid INT(11) NOT NULL default '4400', Dir VARCHAR(256) BINARY NOT NULL default '/home/ftpROOT', PRIMARY KEY (User) ); GRANT SELECT, INSERT, UPDATE ON ftp.* TO 'pure-ftp'@'localhost' IDENTIFIED BY 'P@$$w0rD!' ; FLUSH PRIVILEGES;
Once the database is setup, insert some user accounts for testing.
INSERT INTO `ftp`.`users` (`User` ,`Password` ,`Uid` ,`Gid` ,`Dir`)
VALUES ('upload', ENCRYPT( 'upload' ) , '4402', '4400', '/home/ftpROOT');
INSERT INTO `ftp`.`users` (`User` ,`Password` ,`Uid` ,`Gid` ,`Dir`)
VALUES ('download', ENCRYPT( 'download' ) , '4401', '4400', '/home/ftpROOT');
Now edit your Pure-FTPd config file to look something like this.
# Config file for /etc/init.d/pure-ftpd ##Comment variables out to disable its features, or change the values in it... ## ## This variable must be uncommented in order for the server to start ## IS_CONFIGURED="yes" ## FTP Server,Port (separated by comma) ## ## If you prefer host names over IP addresses, it's your choice: SERVER="-S ftp.uplinkzero.com,21" ## IPv6 addresses are supported. ## !!! WARNING !!! ## Using an invalid IP will result in the server not starting, ## but reporting a correct start! ## SERVER="-S 192.168.0.1,21" ## By default binds to all available IPs. SERVER="-S 21" ## Number of simultaneous connections in total, and per IP ## MAX_CONN="-c 30" MAX_CONN_IP="-C 10" ## Start daemonized in background ## DAEMON="-B" ## Don't allow uploads if the partition is more full then this var ## DISK_FULL="-k 90%" ## If your FTP server is behind a NAT box, uncomment this ## #USE_NAT="-N" ## Authentication mechanisms (others are 'pam', ...) ## ## Further infos can be found in the README file. AUTH="-l mysql:/etc/conf.d/pure-ftpd-mysql" ## Change the maximum idle time (in minutes) ## ## If this variable is not defined, it will default to 15 minutes. TIMEOUT="-I 10'" ## Facility used for syslog logging ## ## If this variable is not defined, it will default to the 'ftp' facility. ## Logging can be disabled with '-f none'. LOG="-f ftp" ## Charset conversion support *experimental* ## ## Only works if USE "charconv" is enabled (only Pure-FTPd >=1.0.21). ## Set the charset of the filesystem. # CHARCONV="--fscharset" ## If you want to process each file uploaded through Pure-FTPd, enter the name ## of the script that should process the files below. ## man pure-uploadscript to learn more about how to write this script. # UPLOADSCRIPT="/path/to/uploadscript" ## Misc. Others ## MISC_OTHER="-A -E -i -R -Z" # # Use these inside $MISC_OTHER # More can be found on "http://download.pureftpd.org/pub/pure-ftpd/doc/README" # # -A [ chroot() everyone, but root ] # -e [ Only allow anonymous users ] # -E [ Only allow authenticated users. Anonymous logins are prohibited. ] # -i [ Disallow upload for anonymous users, whatever directory perms are ] # -j [ If the home directory of a user doesn't exist, auto-create it ] # -M [ Allow anonymous users to create directories. ] # -R [ Disallow users (even non-anonymous ones) usage of the CHMOD command ] # -x [ In normal operation mode, authenticated users can read/write # files beginning with a dot ('.'). Anonymous users can't, for security reasons # (like changing banners or a forgotten .rhosts). When '-x' is used, authenticated # users can download dot-files, but not overwrite/create them, even if they own # them. ] # -X [ This flag is identical to the previous one (writing # dot-files is prohibited), but in addition, users can't even *read* files and # directories beginning with a dot (like "cd .ssh"). ] # -D [ List files beginning with a dot ('.') even when the client doesn't # append the '-a' option to the list command. A workaround for badly # configured FTP clients. ] # -G [ Disallow renaming. ] # -d [ Send various debugging messages to the syslog. ONLY for DEBUG ] # -F [ Display a fortune cookie on login. Check the README file ] # -H [ By default, fully-qualified host names are logged. The '-H' flag avoids host names resolution. ]
Now create the MySQL config file defined in the main config file above.
# Sample Pure-FTPd Mysql configuration file. #
# See README.MySQL for explanations. #
# Optional : MySQL server name or IP. Don't define this for unix sockets.
MYSQLServer localhost
# Optional : MySQL port. Don't define this if a local unix socket is used.
MYSQLPort 3306
# Optional : define the location of mysql.sock if the server runs on this host.
# MYSQLSocket /tmp/mysql.sock
# Mandatory : user to bind the server as.
MYSQLUser pure-ftp
# Mandatory : user password. You must have a password.
MYSQLPassword P@$$w0rD!
# Mandatory : database to open.
MYSQLDatabase ftp
# Mandatory : how passwords are stored
# Valid values are : "cleartext", "crypt", "md5" and "password"
# ("password" = MySQL password() function)
# You can also use "any" to try "crypt", "md5" *and* "password"
MYSQLCrypt crypt
# In the following directives, parts of the strings are replaced at
# run-time before performing queries :
#
# \L is replaced by the login of the user trying to authenticate.
# \I is replaced by the IP address the user connected to.
# \P is replaced by the port number the user connected to.
# \R is replaced by the IP address the user connected from.
# \D is replaced by the remote IP address, as a long decimal number.
#
# Very complex queries can be performed using these substitution strings,
# especially for virtual hosting.
# Query to execute in order to fetch the password
MYSQLGetPW SELECT Password FROM users WHERE User="\L"
# Query to execute in order to fetch the system user name or uid
MYSQLGetUID SELECT Uid FROM users WHERE User="\L"
# Optional : default UID - if set this overrides MYSQLGetUID
# MYSQLDefaultUID 4401
# Query to execute in order to fetch the system user group or gid
MYSQLGetGID SELECT Gid FROM users WHERE User="\L"
# Optional : default GID - if set this overrides MYSQLGetGID
# MYSQLDefaultGID 4400
# Query to execute in order to fetch the home directory
MYSQLGetDir SELECT Dir FROM users WHERE User="\L"
# Optional : query to get the maximal number of files
# Pure-FTPd must have been compiled with virtual quotas support.
# MySQLGetQTAFS SELECT QuotaFiles FROM users WHERE User="\L"
# Optional : query to get the maximal disk usage (virtual quotas)
# The number should be in Megabytes.
# Pure-FTPd must have been compiled with virtual quotas support.
# MySQLGetQTASZ SELECT QuotaSize FROM users WHERE User="\L"
# Optional : ratios. The server has to be compiled with ratio support.
# MySQLGetRatioUL SELECT ULRatio FROM users WHERE User="\L"
# MySQLGetRatioDL SELECT DLRatio FROM users WHERE User="\L"
# Optional : bandwidth throttling.
# The server has to be compiled with throttling support.
# Values are in KB/s .
# MySQLGetBandwidthUL SELECT ULBandwidth FROM users WHERE User="\L"
# MySQLGetBandwidthDL SELECT DLBandwidth FROM users WHERE User="\L"
# Enable ~ expansion. NEVER ENABLE THIS BLINDLY UNLESS :
# 1) You know what you are doing.
# 2) Real and virtual users match.
# MySQLForceTildeExpansion 1
# If you upgraded your tables to transactionnal tables (Gemini,
# BerkeleyDB, Innobase...), you can enable SQL transactions to
# avoid races. Leave this commented if you are using the
# traditionnal MyIsam databases or old (< 3.23.x) MySQL versions.
# MySQLTransactions On
Now start pure-ftpd and test.
Login with upload and upload and make sure that you can create a directory.
Then login with download and download and make sure that you are unable to create or remove directories.
Users with the UID 4402 in the MySQL database get write access to the file system.
Users with the UID 4401 only get read access to the file system because the directory structure is owned by ftpwrite (UID 4402) and the group ftpgroup (UID 4400) of which both ftpwrite (UID 4402) and ftp read (UID 4401) are members.
server ~ # ftp localhost Connected to localhost (127.0.0.1). 220---------- Welcome to Pure-FTPd [privsep] [TLS] ---------- 220-You are user number 1 of 30 allowed. 220-Local time is now 11:50. Server port: 21. 220-This is a private system - No anonymous login 220 You will be disconnected after 10 minutes of inactivity. Name (localhost:user): upload 500 This security scheme is not implemented SSL not available 331 User upload OK. Password required Password: 230-User upload has group access to: ftpgroup 230 OK. Current restricted directory is / Remote system type is UNIX. Using binary mode to transfer files. ftp> ls -l 200 PORT command successful 150 Connecting to port 39689 drwxr-x--- 4 4402 ftpgroup 96 May 12 00:20 Debian drwxr-x--- 4 4402 ftpgroup 96 May 12 00:27 Gentoo drwxr-x--- 3 4402 ftpgroup 72 May 12 00:35 OpenOffice 226-Options: -l 226 3 matches total ftp> quit 221-Goodbye. You uploaded 0 and downloaded 0 kbytes. 221 Logout.