Saturday, November 20, 2004

Proftpd mySQL Authentication & Quotas on FreeBSD

Tonight I tried setting up Proftpd with mySQL authentication on a development box running FreeBSD 4.10. I got it to work using the steps below, but some security concerns arise from using mySQL user accounts without a system account behind them. Since this setup uses one FTP account to create user home directories and upload files, a compromise to this FTP user would cause the attacker to gain access to all FTP user home directories. I guess it just depends on how much you trust the DefaultRoot directive in Proftpd. I run Proftpd in its own chroot environment ( ) in addition to using DefaultRoot, so I'm used to feeling pretty safe with my Proftpd install. Anyway, here's how I did the install/configuration

1. install proftpd-mysql from the ports with WITH_QUOTA set:
cd /usr/ports/ftp/proftpd-mysql/
env WITH_QUOTA=yes make
env WITH_QUOTA=yes make install

2. Add the global proftpd user & Proftpd group to your system.
I used uid & gid 5500 simply because that's what was used at one of the sites I was referencing (listed below).

pw groupadd -n Proftpd -g 5500
pw useradd proftpd -u 5500 -g Proftpd -s /sbin/nologin -d /dev/null -c "Proftpd User"

3. Create the mySQL database

create database proftpd;
grant all on proftpd.* to 'proftpd'@'localhost' identified by 'password'

( change 'password' to something secret! )

4. Create the mySQL tables for the users & quota

create table proftpdUsers (

sqlUID int unsigned auto_increment not null,
userName varchar(30) not null unique,
passwd varchar(80) not null,
uid int unsigned not null unique,
gid int unsigned not null,
homedir tinytext,
shell tinytext,
primary key(sqlUID)

) ;

create table proftpdGroups (

sqlGID int unsigned auto_increment not null,
groupName varchar(30) not null unique,
gid int unsigned not null unique,
members tinytext,
primary key(sqlGID)

CREATE TABLE proftpdQuotaLimits (
name VARCHAR(30),
quota_type ENUM("user", "group", "class", "all") NOT NULL,
per_session ENUM("false", "true") NOT NULL,
limit_type ENUM("soft", "hard") NOT NULL,
bytes_in_avail FLOAT NOT NULL,
bytes_out_avail FLOAT NOT NULL,
bytes_xfer_avail FLOAT NOT NULL,
files_in_avail INT UNSIGNED NOT NULL,
files_out_avail INT UNSIGNED NOT NULL,
files_xfer_avail INT UNSIGNED NOT NULL

CREATE TABLE proftpdQuotaTallies (
quota_type ENUM("user", "group", "class", "all") NOT NULL,
bytes_in_used FLOAT NOT NULL,
bytes_out_used FLOAT NOT NULL,
bytes_xfer_used FLOAT NOT NULL,
files_in_used INT UNSIGNED NOT NULL,
files_out_used INT UNSIGNED NOT NULL,
files_xfer_used INT UNSIGNED NOT NULL

5. Add a test user to the proftpd database

(assumes /home/ftp is where you keep your ftp users. Otherwise, change the homedir location). This is certainly not a necessary step, but you should probably check to see if your configuration is working. You can delete this user later.

insert into proftpdUsers values ( 0, 'test', 'test', 5500, 5500, '/home/ftp/test', '/sbin/nologin' );

6. Set your proftpd configuration to use the mySQL authentication and quotas:
(NOTE: this is not a complete configuration file, it's basically just the default config file with mySQL auth & quotas added, but note that the User and Group directives are the user & group we added in step 2. )

MaxInstances 30

# Set the user and group under which the server will run.
User proftpd
Group Proftpd

# To cause every FTP user to be "jailed" (chrooted) into their home
# directory, uncomment this line.
DefaultRoot ~

# Normally, we want files to be overwriteable.
AllowOverwrite on

# Bar use of SITE CHMOD by default


# The passwords in MySQL are encrypted using CRYPT
SQLAuthTypes Plaintext Crypt
SQLAuthenticate users* groups*

# used to connect to the database
# databasename@host database_user user_password
SQLConnectInfo proftpd@localhost proftpd yourdatabasepassword

# Here we tell ProFTPd the names of the database columns in the "usertable"
# we want it to interact with. Match the names with those in the db
SQLUserInfo proftpdUsers userName passwd uid gid homedir shell

# Here we tell ProFTPd the names of the database columns in the "grouptable"
# we want it to interact with. Again the names match with those in the db
SQLGroupInfo proftpdGroups groupName gid members

# set min UID and GID - otherwise these are 999 each
SQLMinID 5000

# User quotas
# ===========
QuotaEngine on
QuotaDirectoryTally on
QuotaDisplayUnits Mb
QuotaShowQuotas on

# create a user's home directory on demand if it doesn't exist
SQLHomedirOnDemand on

SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM proftpdQuotaLimits WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM proftpdQuotaTallies WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" proftpdQuotaTallies

SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" proftpdQuotaTallies

QuotaLimitTable sql:/get-quota-limit
QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally

Thanks to the following sites for being great references, and providing most of the information in this post:

1 comment:

qishaya said...

Milan create week ended last night with donatella christian louboutin london disregard presenting the ending show of the autumn christian louboutin online frost 2003 italian collections.Donatella, the creative chief of christian boots the house her delayed brother founded, delivered a collection that was, christian louboutin uk as they say, very christian louboutin shoes.First up was the versus limit, louboutin boots the cheaper christian louboutin line. Girls stomped christian louboutin 2010 out with backcombed tresses bearing turquoise leather trousers, christian louboutin uk sale patchwork pullover and blonde fur sliced into stoles and active jackets. christian boots uk But this aggressive hell’s angels look almost seemed a caricature of the christian louboutin boots christian louboutin boots comfort. louboutin sandals Next up was gianni christian louboutin, buy christian louboutin the main collection