2004年01月23日

ProFTPd1.2.9+mod_quotatab+mysql

今度は放っておくとパンクしかねないFTPサーバを運用することとなり、quotaを掛ける事となりました。
んで、例によって運用ツールをperlで書いてユーザの作成もquotaの調整もリモート管理したいので設定系は全部mysqlに任せることにして、mod_quotaの実装方法を探していると 1.2.8で動かなかったですと(;´д`)ノ
でも、もうちょっと調べてみたらハックして1.2.9でも動くようにしている方を発見 そのページを見ていたところ
でも私的には、mod_quotatab のほうが良いmoduleだと思います。
mod_quotatab?

調べてみると通常のquotaだけではなく、ダウンロード転送量制限や、総転送量制限、転送ファイル数制限なども掛けられるようでなんだかよさげだったのでこっちで実装してみることにしました。
なお、MySQL上でのテーブルの実装方法は運用ツールの作成の手間を省くために独自の方法を用いてますので不具合があるかもしれません(^^;

まず、mod_quptatabはのTarボールに含まれてないので、ソースを別に取ってくる必要があります。
ソースは

ここらへんからさっくり持ってきます。

で、普通にmake installするなら、持ってきたソースを解凍して*.c等のファイル一式をProFTPdのtarボールを解凍して出来た中のcotribの中にmvして、configuleの時に「--with-modules=mod_quotatab:mod_quotatab_sql」してやればいいのですが、今回はrpmでつくって入れたかったのでProFTPdのspecファイルをいじることにしました。

proftpd.specファイルの変更点

Source: ftp://ftp.proftpd.org/distrib/%{name}-%{version}.tar.gz
の下の行に以下の行を追加
Source1: http://www.castaglia.org/proftpd/modules/proftpd-mod-quotatab-1.2.11.tar.gz

%setup -q

%setup -q -a 1
に変更

./configureの直前の行に以下の行を追加
mv mod_quotatab/* contrib/

./configuleの--with-modules=の行に下を追記
mod_quotatab:mod_quotatab_sql

あとは落としたソースをSORCESディレクトリに入れてrpmbilud -bbをすればmod_quotatabの組み込まれたProFTPdができあがるはずです。

ただ、これだけだとmysqlが使えないので、今回はこっちこっちも同時にやってあります。

で、rpmで無事インストールが出来たら、今度はmysqlでの設定に入ります。
まず、こっちを参考にして基本を作ってください。
なおusersテーブルはこの後作り直しますので、ひとまずデーターベースの作成・ユーザーの作成・groupの作成を行ってください。
それから、必ずDBアクセス用のユーザーには参照権限だけでは無く更新・挿入権限も付与してください。

次にusersテーブルと容量の記憶用のテーブル(quotatallies)を作成します。

CREATE TABLE users (
userid VARCHAR(30) NOT NULL,
password VARCHAR(30) NOT NULL,
uid SMALLINT(5) UNSIGNED NOT NULL DEFAULT 1000,
gid SMALLINT(5) UNSIGNED NOT NULL DEFAULT 1000,
homedir VARCHAR(255) DEFAULT NULL,
shell VARCHAR(255) DEFAULT '/bin/true',
quota_type ENUM("user") DEFAULT 'user' NOT NULL,
per_session ENUM("false", "true") DEFAULT 'true' NOT NULL,
limit_type ENUM("soft", "hard") DEFAULT 'soft' NOT NULL,
bytes_in_avail FLOAT DEFAULT '0' NOT NULL,
bytes_out_avail FLOAT DEFAULT '0' NOT NULL,
bytes_xfer_avail FLOAT DEFAULT '0' NOT NULL,
files_in_avail INT UNSIGNED DEFAULT '0' NOT NULL,
files_out_avail INT UNSIGNED DEFAULT '0' NOT NULL,
files_xfer_avail INT UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (userid)
);

CREATE TABLE quotatallies (
userid VARCHAR(30) NOT NULL,
quota_type ENUM("user", "group", "class", "all") DEFAULT 'user' NOT NULL,
bytes_in_used FLOAT DEFAULT '0' NOT NULL, 
bytes_out_used FLOAT DEFAULT '0' NOT NULL, 
bytes_xfer_used FLOAT DEFAULT '0' NOT NULL, 
files_in_used INT UNSIGNED DEFAULT '0' NOT NULL, 
files_out_used INT UNSIGNED DEFAULT '0' NOT NULL, 
files_xfer_used INT UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (userid)
);
なお、quota用の項目の意味はそれぞれ次の通り
usersの方
フィールド名 意味
quota_type user, group, class, alllのいずれか quotaの制限単位を決めます。今回はユーザ別でしかquotaの制限を掛けないためusersテーブルにマージして他の制限を使えなくしてありますが、ユーザ単位の他にグループ単位、アカウント全体に対する制限も可能です。またClass単位というのもありますが、こいつだけよく判りません(^^;(現状バージョンじゃ動作してない!?)
もし本来の挙動が良いのならusersテーブルからquota関連のフィールドを抜いてこちらを参考にしてquotalimitsテーブルを作ってください。
per_session 「true」または「false」 trueの場合、通信開始時から終了までの間のみ制限対象となります。(つまり次回通信時にはリセットされる)。いまいち使いどころが判らないので通常はfalseにしておきましょう。
limit_type 「soft」 または「head」 制限をまたぐファイルの処置を決めます。softの場合は制限をまたいだファイルまでがセーフで、hardの場合は制限をまたぐファイルを削除します。
bytes_in_avail 指定バイト アップロード出来る最大容量(Byte)を指定する
bytes_out_avail 指定バイト ダウンロード出来る最大容量(Byte)を指定する
bytes_xfer_avail 指定バイト 送受信の最大転送量(Byte)を指定する
files_in_avail ファイル数 アップロードできる最大ファイル数を指定する
files_out_avail ファイル数 ダウンロードできる最大ファイル数を指定する
files_xfer_avail ファイル数 送受信可能な最大ファイル数を指定する

quotatalliesのテーブルはプログラムが自動的に読み書きするため管理者は基本的に操作しません。
なお、それぞれのフィールドには上記の内容に対応する現在値が記入されます。

で、これらを作成したら、今度はproftpd.confの設定に入ります。

  # mod_quotatabの有効化
  QuotaEngine           on

  # SQLの検索文(テーブル名称など変更している人はそれに併せて書き換えてください)
  SQLNamedQuery get-quota-limit SELECT "userid, 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 users WHERE userid = '%{0}' AND \
quota_type = '%{1}'"

  SQLNamedQuery get-quota-tally SELECT "userid, quota_type, bytes_in_used, \
bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used \
FROM quotatallies WHERE userid = '%{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 userid = '%{6}' AND quota_type = '%{7}'" quotatallies

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

  # 検索文のモジュールへの引き渡し
  QuotaLimitTable sql:/get-quota-limit
  QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally

  # 同時にSQLを発行しないようにするためのロックファイル名称
  QuotaLock             /proftpd-quota-lock

  # Quota情報をユーザに通知するかどうか
  QuotaShowQuotas       on

  # ユーザへのメッセージを表示する際のquotaの制限値の表示単位[b Kb Mb Gb]
  QuotaDisplayUnits     Mb

  # ディレクトリ操作をmod_quotatabが認識するかどうか(onにする必要は無いかもしれません)
  QuotaDirectoryTally   on

  # mod_quotatabの動作状況のログを記録するファイル名
  QuotaLog              /var/log/proftpd-quota-log
最後にmysql上のuserテーブルにuserの作成を行います
INSERT users(userid, password, uid, gid, homedir, shell, 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('test','{md5}nXOvMmAdZFTHIdXHzkF/Lw==',5000,5000,'/ftp/test','/bin/true','user','true','soft',42949672960,0,0,0,0,0)
なお、上記の場合bytes_in_availに42949672960=4GBを書き入れる事によって4GBまでしかファイルをディスク上に置けなくなっています。 (0になっている項目は自動的にquota対象から無視されます)

また、上記の制限でいっぱいになった場合はFTP上から削除コマンドを発行することで消したファイルの分、さらにアップロードすることが可能となります。

参考URL

追記(2004年3月17日(水))
FTPコマンドで正常にログイン出来ない場合はこちらを参照の事

(2004年5月11日(火))
こちらでひっそり誤植を指摘されてたので、ひっそり直してみる(笑)

Posted by Takuchan at 2004年01月23日 10:28 | トラックバック(1)