【proftpd】 MySQLでアカウント管理する リターンズ 201511


以前中途半端に終わってしまった、ProFTPDのユーザーデータをMySQLに持たせるシリーズのリトライです。今度もTwitterがキッカケでしたw

今回はCentOS6にepelリポジトリをインストールし、ここからProFTPDを、標準リポジトリからmysql-serverをインストールして設定しています。ユーザー管理とクォータ管理をするところまでは確認しましたが、それ以外の細かなProFTPDの設定は一切弄っていません。

■ 事前準備

一旦iptablesとSELinuxを止めておきます。

$ sudo service iptables stop
$ sudo chkconfig iptables off
$ sudo sed -i.orig "/^SELINUX=/s/[[:alnum:]]*$/disabled/" /etc/selinux/config
$ sudo reboot

■ epelリポジトリ インストール

yumコマンドでサックリとepelリポジトリをインストールします。普段使いしないので、あわせてリポジトリをデフォルトで無効化しておきます。

$ sudo yum -y install epel-release
$ sudo sed -i.orig "/^enabled/s/1/0/g" /etc/yum.repos.d/epel.repo

■ proftpd proftpd-mysqlパッケージ インストール

epelリポジトリから、proftpdとproftpd-mysqlを、標準リポジトリからmysql-serverをインストールします。mysql-serverについては、お好みでOracleのリポジトリからインストールしても構わないでしょう。(この場合、パッケージ名はmysql-community-serverになります)

$ sudo yum -y install mysql-server
$ sudo yum --enablerepo=epel -y install proftpd proftpd-mysql

これらインストールが終わったら、ひとまずmysqldを起動します。

$ sudo service mysqld start
$ sudo chkconfig mysqld on

■ FTP用UNIXアカウント作成

FTP用UNIXユーザー「ftpuser」、同じくグループ「ftpgroup」を作成し、MySQLで管理するバーチャルユーザーとマッピングします。まずはグループから。UID、GIDは一旦2001で固定することにします。

$ sudo groupadd -g 2001 ftpgroup
$ sudo useradd -u 2001 -s /bin/false -d /bin/null -c "proftpd user" -g ftpgroup ftpuser

■ データベースとDBユーザー作成

DB名「ftp」、DBユーザー「proftpd」を作成します。DBユーザーのパスワードは一旦「password」としますが、適宜変更してくださいね。

$ mysql -e "create database ftp; GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost' IDENTIFIED BY 'password'; GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost.localdomain' IDENTIFIED BY 'password'; FLUSH PRIVILEGES;"

mysqlのシェルからはこんな感じでどうぞ。

create database ftp;
GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost.localdomain' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

終わったら確認です。こんな感じで表示されればOKです。

$ mysql -N -s -e "select user,host,password from mysql.user;" | grep ^proftpd
proftpd	localhost	*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19
proftpd	localhost.localdomain	*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19

■ グループ管理テーブル作成

FTPのグループを管理するテーブルを作成します。

$ mysql ftp -e "CREATE TABLE ftpgroup (groupname varchar(16) NOT NULL default '', gid smallint(6) NOT NULL default '5500', members varchar(16) NOT NULL default '', KEY groupname (groupname) ) TYPE=MyISAM COMMENT='ProFTP group table';"

mysqlのシェルからはこんな感じでどうぞ。

USE ftp;
CREATE TABLE ftpgroup (
groupname varchar(16) NOT NULL default '',
gid smallint(6) NOT NULL default '5500',
members varchar(16) NOT NULL default '',
KEY groupname (groupname)
) TYPE=MyISAM COMMENT='ProFTP group table';

■ FTPユーザーのquotaを管理するテーブル作成

ftpquotalimitsテーブルとftpquotatalliesテーブルの2つを作成します。

$ mysql ftp -e "CREATE TABLE ftpquotalimits ( name varchar(30) default NULL, quota_type enum('user','group','class','all') NOT NULL default 'user', per_session enum('false','true') NOT NULL default 'false', limit_type enum('soft','hard') NOT NULL default 'soft', bytes_in_avail int(10) unsigned NOT NULL default '0', bytes_out_avail int(10) unsigned NOT NULL default '0', bytes_xfer_avail int(10) unsigned NOT NULL default '0', files_in_avail int(10) unsigned NOT NULL default '0', files_out_avail int(10) unsigned NOT NULL default '0', files_xfer_avail int(10) unsigned NOT NULL default '0' ) TYPE=MyISAM;"
$ mysql ftp -e "CREATE TABLE ftpquotatallies ( name varchar(30) NOT NULL default '', quota_type enum('user','group','class','all') NOT NULL default 'user', bytes_in_used int(10) unsigned NOT NULL default '0', bytes_out_used int(10) unsigned NOT NULL default '0', bytes_xfer_used int(10) unsigned NOT NULL default '0', files_in_used int(10) unsigned NOT NULL default '0', files_out_used int(10) unsigned NOT NULL default '0', files_xfer_used int(10) unsigned NOT NULL default '0' ) TYPE=MyISAM;"

mysqlのシェルからはこんな感じでどうぞ。

CREATE TABLE ftpquotalimits (
name varchar(30) default NULL,
quota_type enum('user','group','class','all') NOT NULL default 'user',
per_session enum('false','true') NOT NULL default 'false',
limit_type enum('soft','hard') NOT NULL default 'soft',
bytes_in_avail int(10) unsigned NOT NULL default '0',
bytes_out_avail int(10) unsigned NOT NULL default '0',
bytes_xfer_avail int(10) unsigned NOT NULL default '0',
files_in_avail int(10) unsigned NOT NULL default '0',
files_out_avail int(10) unsigned NOT NULL default '0',
files_xfer_avail int(10) unsigned NOT NULL default '0'
) TYPE=MyISAM;
CREATE TABLE ftpquotatallies (
name varchar(30) NOT NULL default '',
quota_type enum('user','group','class','all') NOT NULL default 'user',
bytes_in_used int(10) unsigned NOT NULL default '0',
bytes_out_used int(10) unsigned NOT NULL default '0',
bytes_xfer_used int(10) unsigned NOT NULL default '0',
files_in_used int(10) unsigned NOT NULL default '0',
files_out_used int(10) unsigned NOT NULL default '0',
files_xfer_used int(10) unsigned NOT NULL default '0'
) TYPE=MyISAM;

■ FTPユーザーを管理するテーブル作成

$ mysql ftp -e "CREATE TABLE ftpuser ( id int(10) unsigned NOT NULL auto_increment, userid varchar(32) NOT NULL default '', passwd varchar(32) NOT NULL default '', uid smallint(6) NOT NULL default '5500', gid smallint(6) NOT NULL default '5500', homedir varchar(255) NOT NULL default '', shell varchar(16) NOT NULL default '/sbin/nologin', count int(11) NOT NULL default '0', accessed datetime NOT NULL default '0000-00-00 00:00:00', modified datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY userid (userid) ) TYPE=MyISAM COMMENT='ProFTP user table';"

mysqlのシェルからはこんな感じでどうぞ。

CREATE TABLE ftpuser (
id int(10) unsigned NOT NULL auto_increment,
userid varchar(32) NOT NULL default '',
passwd varchar(32) NOT NULL default '',
uid smallint(6) NOT NULL default '5500',
gid smallint(6) NOT NULL default '5500',
homedir varchar(255) NOT NULL default '',
shell varchar(16) NOT NULL default '/sbin/nologin',
count int(11) NOT NULL default '0',
accessed datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (id),
UNIQUE KEY userid (userid)
) TYPE=MyISAM COMMENT='ProFTP user table';

■ proftpd.conf 編集

proftpd.confを編集し、ユーザー管理とクォータ管理をMySQLで行えるようにします。

$ sudo cp -p /etc/proftpd.conf{,.orig}
$ sudo vi /etc/proftpd.conf

以下、vimでの編集箇所です。「Use pam to authenticate (default) and be authoritative」の下の2行「AuthPAMConfig」と「AuthOrder」をコメントアウトします。

# Use pam to authenticate (default) and be authoritative
##--@--##AuthPAMConfig			proftpd
##--@--##AuthOrder			mod_auth_pam.c* mod_auth_unix.c

「# General database support (http://www.proftpd.org/docs/contrib/mod_sql.html)」の下の行「# LoadModule mod_sql.c」のコメントアウトを外します。

# General database support (http://www.proftpd.org/docs/contrib/mod_sql.html)
#   LoadModule mod_sql.c
LoadModule mod_sql.c

「# Mysql support (requires proftpd-mysql package)」の2行下の「# LoadModule mod_sql_mysql.c」のコメントアウトを外します。

# Mysql support (requires proftpd-mysql package)
# (http://www.proftpd.org/docs/contrib/mod_sql.html)
#   LoadModule mod_sql_mysql.c
LoadModule mod_sql_mysql.c

「# Quota support (http://www.proftpd.org/docs/contrib/mod_quotatab.html)」の下の「#   LoadModule mod_quotatab.c」のコメントアウトを外します。

# Quota support (http://www.proftpd.org/docs/contrib/mod_quotatab.html)
#   LoadModule mod_quotatab.c
LoadModule mod_quotatab.c

「# SQL database "driver" for storing quota table information in SQL table」の2行下の「#   LoadModule mod_quotatab_sql.c」のコメントアウトを外します。

# SQL database "driver" for storing quota table information in SQL tables
# (http://www.proftpd.org/docs/contrib/mod_quotatab_sql.html)
#   LoadModule mod_quotatab_sql.c
LoadModule mod_quotatab_sql.c

「#   LoadModule mod_ifsession.c」の直下あたりに以下追記します。

# 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  ftp@localhost proftpd password

# 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     ftpuser userid 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    ftpgroup groupname gid members

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

# create a user's home directory on demand if it doesn't exist
##--@Disabled@--##SQLHomedirOnDemand on # ここだけonにするとproftpdが起動しなかったのでコメントアウト

# Update count every time user logs in
SQLLog PASS updatecount
SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" ftpuser

# Update modified everytime user uploads or deletes a file
SQLLog  STOR,DELE modified
SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" ftpuser

# User quotas
# ===========
QuotaEngine on
QuotaDirectoryTally on
QuotaDisplayUnits Mb
QuotaShowQuotas 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 ftpquotalimits 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 ftpquotatallies 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}'" ftpquotatallies

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

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

RootLogin off
RequireValidShell off

あとはトラブル時の切り分けのため「ExtendedLog /var/log/proftpd/proftpd.log all」あたりを先頭くらいに付け加えてみてもよいでしょう。

■ proftpd起動

上記設定が終わったらproftpdをデーモンとして起動します。

$ sudo chkconfig proftpd on
$ sudo chkconfig proftpd --list
$ sudo service proftpd start

バージョン確認とモジュール一覧表示をしてみます。

$ sudo /usr/sbin/proftpd -vv
ProFTPD Version: 1.3.3g (maint)
  Scoreboard Version: 01040003
  Built: Thu Sep 10 2015 18:30:06 UTC

Loaded modules:
  mod_quotatab_sql.c
  mod_quotatab/1.3.0
  mod_sql_mysql/4.0.8
  mod_sql/4.2.5
  mod_lang/0.9
  mod_ctrls/0.9.4
  mod_cap/1.0
  mod_vroot/0.9.2
  mod_tls/2.4.2
  mod_auth_pam/1.1
  mod_readme.c
  mod_ident/1.0
  mod_dso/0.5
  mod_facts/0.1
  mod_delay/0.6
  mod_site.c
  mod_log.c
  mod_ls.c
  mod_auth.c
  mod_auth_file/0.8.3
  mod_auth_unix.c
  mod_xfer.c
  mod_core.c

■ ftpgroupテーブルに実UID、実GIDをマッピングするデータを投入

$ mysql ftp -e "INSERT INTO \`ftpgroup\` (\`groupname\`, \`gid\`, \`members\`) VALUES ('ftpgroup', 2001, 'ftpuser');"

mysqlのシェルからはこんな感じでどうぞ。

INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('ftpgroup', 2001, 'ftpuser');

■ ftpquotalimitsテーブルにクォータ設定データを投入

$ mysql ftp -e "INSERT INTO \`ftpquotalimits\` (\`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\`) VALUES ('exampleuser', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0);"

mysqlのシェルからはこんな感じでどうぞ。

INSERT INTO `ftpquotalimits` (`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`) VALUES ('exampleuser', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0);

■ ftpuserテーブルにユーザーデータを投入

$ mysql ftp -e "INSERT INTO \`ftpuser\` (\`id\`, \`userid\`, \`passwd\`, \`uid\`, \`gid\`, \`homedir\`, \`shell\`, \`count\`, \`accessed\`, \`modified\`) VALUES (1, 'exampleuser', 'secret', 2001, 2001, '/home/www.example.com', '/sbin/nologin', 0, '', '');"

mysqlのシェルからはこんな感じでどうぞ。

INSERT INTO `ftpuser` (`id`, `userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES (1, 'exampleuser', 'secret', 2001, 2001, '/home/www.example.com', '/sbin/nologin', 0, '', '');

■ ディレクトリ作成

FTPユーザーのホームディレクトリを作成し、オーナーをMySQLのユーザーとマッピングしているUNIXユーザーのオーナーとグループに変更します。

$ sudo mkdir -p /home/www.example.com
$ sudo chown 2001:2001 /home/www.example.com

■ 確認

ここまでできたら設定を確認してみましょう。

$ mysql ftp -e "SELECT * FROM ftpgroup;"
+-----------+------+---------+
| groupname | gid  | members |
+-----------+------+---------+
| ftpgroup  | 2001 | ftpuser |
+-----------+------+---------+
$ mysql ftp -e "SELECT * FROM ftpquotalimits;"
+-------------+------------+-------------+------------+----------------+-----------------+------------------+----------------+-----------------+------------------+
| 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 |
+-------------+------------+-------------+------------+----------------+-----------------+------------------+----------------+-----------------+------------------+
| exampleuser | user       | true        | hard       |       15728640 |               0 |                0 |              0 |               0 |                0 |
+-------------+------------+-------------+------------+----------------+-----------------+------------------+----------------+-----------------+------------------+
$ mysql ftp -e "SELECT * FROM ftpquotatallies;"
+-------------+------------+---------------+----------------+-----------------+---------------+----------------+-----------------+
| name        | quota_type | bytes_in_used | bytes_out_used | bytes_xfer_used | files_in_used | files_out_used | files_xfer_used |
+-------------+------------+---------------+----------------+-----------------+---------------+----------------+-----------------+
| exampleuser | user       |             0 |              0 |               0 |             0 |              0 |               0 |
+-------------+------------+---------------+----------------+-----------------+---------------+----------------+-----------------+
$ mysql ftp -e "SELECT * FROM ftpuser;"
+----+-------------+--------+------+------+-----------------------+---------------+-------+---------------------+---------------------+
| id | userid      | passwd | uid  | gid  | homedir               | shell         | count | accessed            | modified            |
+----+-------------+--------+------+------+-----------------------+---------------+-------+---------------------+---------------------+
|  1 | exampleuser | secret | 2001 | 2001 | /home/www.example.com | /sbin/nologin |    18 | 2015-11-07 02:53:26 | 2015-11-07 02:56:32 |
+----+-------------+--------+------+------+-----------------------+---------------+-------+---------------------+---------------------+

あとはFTPクライアントから接続できればOKです。なお、ユーザー単位でのクォータは0ですが、1セッションあたり15MBの転送制限があります。

■ テーブルのカラム解説

以下ザックリですがテーブルを解説を。

ftpuserテーブル

userid proftpdのバーチャルユーザー名
passwd proftpdバーチャルユーザーのパスワード (※ クリアテキストで格納されます。暗号化はご随意に!)
uid proftpdバーチャルユーザーの実UID
gid proftpdバーチャルユーザーの実GID
homedir proftpdバーチャルユーザーのホームディレクトリ(実際のPATH)
shell proftpdバーチャルユーザーのシェル(デフォルトは /sbin/nologin )

 

ftpquotalimitsテーブル

name proftpdのバーチャルユーザー名
quota_type userかgroupで選択。通常はuser。
per_session 1セッションあたりのquota制限をするかどうかを選択。trueかfalseの2択。上記の例だとアップロード時に15MBを超えると制限がかかる。
limit_type ソフトリミットかハードリミットを選択。
bytes_in_avail アップロード時のquota上限をバイト数で指定。0で無制限。
bytes_out_avail ダウンロード時のquota上限をバイト数で指定。0で無制限。
bytes_xfer_avail 転送量のquota上限をバイト数で指定。0で無制限。
files_in_avail アップロードするファイル数を指定。0で無制限。
files_out_avail ダウンロードするファイル数を指定。0で無制限。
files_xfer_avail 転送するファイル数を指定。0で無制限。

これだけのテーブルがあってどれが優先されるかまでは未検証です!><

いかがでしたでしょうか。案外簡単でしたね。でわ〜。

[参考URI]

Virtual Hosting With Proftpd And MySQL (Incl. Quota) On Fedora 9

SQL and mod_sql