                リソースの制御	

------------------------------------------------------------
1	＊＊＊に制限を加えること
1.1	ＭＬのメンバーの上限数
1.2	メールサイズの制限
1.3	メール一通あたりのコマンド数の上限
1.4	トラフィックの制御

2	Mail Traffic Information
2.1	How to
2.2	Traffic Monitor
2.3	Mail Traffic Information
2.4	メール爆弾 (MAIL BOMBING) 判定評価関数
2.5	評価関数
2.6	MTIの設定変数
2.7	トラフィックの最大値
2.8	その他
2.9	ファイルなど
2.10	カスタマイズ関数とハッシュデータ
2.11	perl 5 tie 
2.12	警告の negative cache
2.13	DB type

3	いろいろなサイズの制限
3.1	投稿メールのサイズの制限
3.2	ＭＬのメンバー数制限(自動登録の時)
3.3	HOOKの例:ある行数を越えるメールは廃棄する設定
3.4	$START_HOOK でＭＬメンバーの人数制限をする
------------------------------------------------------------


1	＊＊＊に制限を加えること

1.1	ＭＬのメンバーの上限数
See also: 3.2 

デフォールトは無制限です。 $MAX_MEMBER_LIMIT で上限を指定します。

1.2	メールサイズの制限

投稿/コマンドメールを問わず入力されるデータの大きさをチェックします。
デフォールトは無制限。$INCOMING_MAIL_SIZE_LIMIT で上限をきめます

1.3	メール一通あたりのコマンド数の上限
See also: $MAXNUM_COMMAND_INPUT 

$MAXNUM_COMMAND_INPUT

1.4	トラフィックの制御
See also: 2 

一気にメールを送ってくる人のメールは拒否します。
この制御機構の名前は MTI (Mail Traffic Information)と呼ばれています。
この機構を有効にするには

	$USE_MTI = 1; (default 0)

    makefml config
    メインメニュ → セキュリティ → USE_MTI

2	Mail Traffic Information

fmlはメールトラフィックの監視をし、バースト状態になったらメールの拒否
をするなどの処理をします。当然さまざまなトレードオフがあります。デフォー
ルトは「使わない」状態になっています。しかしこの機能をONにしておくこと
を推奨しています。

2.1	How to

てっとりばやいカスタマイズを最初にいっておくと

	$MTI_BURST_SOFT_LIMIT
	$MTI_BURST_HARD_LIMIT

の数字を小さくすると、少ない数のメールでも爆弾とみなすようになります。
デフォールトの数字は 1 程度でこの時は十数通程度集中してメールがくるか
否か程度が目安になっています。

2.2	Traffic Monitor

トラフィックのモニターは(学術的興味は別として:)特に必要だとは思いませ
ん。が、トラフィックをモニタすることでメール爆弾(mail bombing)の自動検
出への応用などが考えられると思います。さらなる応用としてメールのループ
なども検出できるでしょう。

Bombing チェックの第一歩は直観的に考えると「トラフィックが一気に大きく
なる時を捉えること」です。しかしこの論理ではUUCPやダイアルアップIPなど
で溜ったメールを一気に掃き出す必要のあるネットワークから出てくる場合や、
ネットワークエラーのために溜ったメールが一気に来る場合なども一気にメー
ルが来るため、正しいメールなのかそれともメール爆弾なのか区別がつかない
などの問題があります。でもそれはある程度はしょうがないので、UUCPやネッ
トワークエラーなども引っ掛けてしまう可能性を覚悟の上で使う必要がありま
す。

いづれの場合でも「意図的なアタックを自動検出できるか？」はどの程度 
fake されたメールが FML につっこまれるかに依存します。これはSMTPに認証
の能力がないからで、IP Spoofing も可能であれば fml.pl が起動された時刻
以外は全て fake も理論上有り得ます。

2.3	Mail Traffic Information

MTI (Mail Traffic Information) はFML内蔵のメールトラフィックモニタシス
テムです。MTIは From: Return-Path: Sender: などの address やホスト情報
を KEY にしてメールがFMLを起動した時間やあるホストの通過時間を cache 
します。この情報を用いて MAIL BOMB ATTACK の監視ができるはずですが、前
述の理由により、うまい評価関数を探すのが非常に大変です。

2.4	メール爆弾 (MAIL BOMBING) 判定評価関数

注意: 以下表記できないので TeX を一部織り混ぜて書く。

メールは時間軸に沿って fml.pl を起動する。この時系列について考える。
メール (m_i) が送られてきてFMLを起動した時間を t_i とし、そのメールの
ヘッダの Date: を d_i とする。ここで i は単なるインデックスでFMLを起動
した順番(正確にはFMLを起動してさらにロックがはずれ実際に処理された順番
になるが)としよう。

MTI では cache として それぞれのメールの t_i と d_i を対にしてキャッシュ
している。m_i は From: Sender: などのアドレスを KEY にしてキャシュして
いる。なお一定時間($MTI_EXPIRE_UNIT)経過後 t_i の情報はキャッシュから
捨てられる。

MTIのデフォールトの評価関数では

	Σ 1 / | t_i - t_j + ε | 

の値を評価する。ここで ε は発散を防ぐためのものである。t_i - t_j は
FMLを起動した時間差だから、多くのメールが送り付けられ連続して起動した
場合には小さな値をとる。これを逆数にして和を取るのでFMLを連続して起動
した場合は大きい値をとることになる。この値がある閾値(threshold)を越え
ると BOMBING だとみなす。

この threshold には 0.2 などの値を設定する。この数字の選び方はかなり微
妙ではっきりとした方針は作れない。例えば

		i=N
	E{t} =	Σ 1 / | t_i - t_j + ε | > Σ 1/M 〜 N/M
		i=1

	| t_i - t_j + ε | < M

と見積もると M = 10, N = 5 でだいたい N/M 〜 0.2 となる。つまり 0.2 は
10秒程度の短い間隔で来るメールが5通連続で来たらメール爆弾か否かの判定
の閾値とみなせる。

この論理の明らかな問題点は 途中のネットワークのエラーやUUCP、DIPなど常
に接続されていないようなネットワークからメールが送られる場合で、この場
合は queue に溜ったメールが一気に送られてくることがあり得る。上の条件
だけではそれも BOMBING だとみなされてしまう。

そのためメールヘッダの Date: フィールドの値 d_i を用いて同様な判定を下
すことを考える。つまり

	E{d} =	Σ 1 / | d_i - d_j + ε |

を考えることにしよう。

普通にメールを書いて queue に溜め一気に送り出す場合を考えると Date: は
かなり飛び飛びの値をとるだろう。そのため E{t} は値が大きくても E{d} の
値は大きくはならないはずである。当然それがうまく判定されるような 
threshold をうまく選んでおく必要がある。

E{d} でも、例えばださいMUAがあって同じ Date: 同じ Message-Id で複数メー
ルを出してしまうとすると、この時は d_i - d_j 〜 0、E{d} >> 1 になって
しまい一瞬でメール爆弾だと判定してしまうだろう。そのため実際のコードで
は発散を防ぐための ε を導入するのではなく

	Σ 1 / ( | d_i - d_j | < 3 ? 3 : | d_i - d_j | )

のように和を取っている。

2.5	評価関数

ここではデフォールトの評価関数について解説する。詳しくは前節参照。
ここで E{t} E{d} は上述の計算方式で計算したものとする。

	E{t}	fml.pl を起動した時刻の差の逆数を足したもの
	E{d}	メールヘッダの Date: の差の逆数を足したもの

を計算する。判定は以下のように行なう。

1	soft limit

	メールを出す大元で一辺に出す時は E{d} の方が一般に大きい
	E{d} < E{t} はネットワークエラーやUUCPの可能性がある

2	hard limit

	条件 1 は Date: が fake されていれば役に立たない。
	そのため E{d} E{t} どちらかがある threshold を越えたら
	それ以外の条件を問わず bomb とみなす。

3 	">" (greater than) 

	">" (greater than) はある誤差の範囲で greater than 
	であるべきだろう

	if ( E{d} > E{t} ) {
		if ( E{d} > $MTI_BURST_SOFT_LIMIT) {
			メール爆弾に違いない
		} 
	}
	else {  # e.g. 条件 1 が成立しないように fake された時

		if ( E{t} > $MTI_BURST_HARD_LIMIT ) {
			メール爆弾に違いない
		}
		if ( E{d} > $MTI_BURST_HARD_LIMIT ) {
			メール爆弾に違いない
		}
	}

2.6	MTIの設定変数

	$USE_MTI

MTI 機能を ON にする。これを enable しないと以下の機能は全て作動しない。

	$USE_MTI_TEST (ベータテストの間だけ存在)

BOMBING と判定した場合に弾くか否か？βテストの間はこの変数をいれないと
弾かずにMTIの判断がログに残っていくだけです。ベータテストが終ったらこ
の変数はなくなり、自動的に弾くように変更されます。

	$MTI_BURST_SOFT_LIMIT
	$MTI_BURST_HARD_LIMIT

デフォールトの評価関数のパラメータ(上述)

	$MTI_BURST_MINIMUM

和を取る時に $MTI_BURST_MINIMUM 以下の値は $MTI_BURST_MINIMUM へ繰り上
げ。デフォールトは3 (3秒)。

	$MTI_COST_EVAL_FUNCTION

自分でカスタマイズした評価関数を呼び出すならこの変数に関数名をセットす
る。

	$MTI_COST_EVAL_HOOK

HOOK

2.7	トラフィックの最大値

MTIのおまけの機能として評価関数を Σ 1 と取ると単純に単位時間辺りの記
事数になる。これを評価し、あるLIMITを越えたら reject する。
単位時間は $MTI_EXPIRE_UNIT (default 3600 sec.) である。

	$MTI_DISTRIBUTE_TRAFFIC_MAX

時間あたりの投稿数の最大値。

	$MTI_COMMAND_TRAFFIC_MAX

時間あたりのコマンドメール数の最大値。それぞれについて独立に設定できる。

2.8	その他

	$MTI_EXPIRE_UNIT

cache life time.

	$MTI_APPEND_TO_REJECT_ADDR_LIST

bomber と判定されたアドレスを $REJECT_ADDR_LIST ($DIR/spamlist) にも加
えるか？否か。デフォールトは NO 。というのは必ずしも From: のアドレス
ではないので $REJECT_ADDR_LIST に入れることに意味があるかどうかは不明
のため。

2.9	ファイルなど

	$MTI_DB
	$MTI_HI_DB

	$MTI_DIST_DB
	$MTI_HI_DIST_DB
	$MTI_HI_COMMAND_DB
	$MTI_COMMAND_DB

cache files.

	$MTI_MAIL_FROM_HINT_LIST

$DIR/mti_mailfrom.hint というファイルにMTIのログをヒントとして残す。こ
れをどう使うかはまた別の問題。例えばこれを sendmail に check_mail のデー
タとして渡すなどの応用が考えられる。

2.10	カスタマイズ関数とハッシュデータ

ベータテストなので、後で仕様が変わるかもしれなひ:)

    $fp = $MTI_COST_EVAL_FUNCTION || 'MTISimpleBomberP';
    &$fp(*e, *MTI, *HI, *addrinfo, *hostinfo);

	%Envelope	Envelope
	%MTI		アドレスと時刻
	%HI		ホストと時刻
	%addrinfo	来たメールのヘッダから解析した address 
	%hostinfo	Received: から割り出したホストの通過時間
			でも評価関数で使ってない;D

2.11	perl 5 tie 

	$MTI_TIE_TYPE

$MTI_TIE_TYPE に DB_File などを定義すると perl 5 の tie 
を使った hash へのバインディングを行なう。
perl 4 では使えない(当り前:-) 
使える引数はOSに依存する。各自マニュアルを参考にしてください
e.g. DB_File, NDBM_File, ...

2.12	警告の negative cache

１時間に１度しか警告メールを管理者に通知しない。mail bombのそれぞれの
メールに対しそれぞれ警告メールを出すと自分で自分に爆撃してしまうことに
なってしまう。

2.13	DB type

	$MTI_TIE_TYPE

$MTI_TIE_TYPE に DB_File などを定義すると perl 5 の tie を使った hash 
へのバインディングを行なう。perl 4 では使えない(当り前:-) 使える引数は
OSに依存する。各自マニュアルを参考にe.g. DB_File, NDBM_File, ...

3	いろいろなサイズの制限

3.1	投稿メールのサイズの制限

あまり大きいメールを送られてもサーバもメンバーの端末でも負荷が高くなる
だけです。ＭＬサーバーが受けとる時に切り捨てます。コマンド、投稿を問わ
ずチェックされます。デフォールトは制限なしで、サイズは byte 単位で

		$INCOMING_MAIL_SIZE_LIMIT

で指定します。なお0は無限大を意味します(デフォールト)。

		$NOTIFY_MAIL_SIZE_OVERFLOW (default 1)

が設定されていれば送り主に fml が拒否した旨をメールで返します。
経験的には知らせないと何度も非常に大きいメールを送ってくるので
非常に迷惑です。

message/partial はばらばらにされて送られてくる分の合計のサイズを推定し
てその値と $INCOMING_MAIL_SIZE_LIMIT を比較します。
(最後の一通が突破する可能性はある)

		$ANNOUNCE_MAIL_SIZE_OVERFLOW (default 0)

を 1 に定義すると、ＭＬに「でっかいメールをＭＬへ投げた人がいる」とさ
らしものにする:)。＃本人に警告すれば十分だとおもうんだが…

3.2	ＭＬのメンバー数制限(自動登録の時)

	$MAX_MEMBER_LIMIT

でメンバーの最大数を制限する。認証するメンバーのリストではなく、配送の
リストをチェックしています。もっとも自動登録の時はほとんど同じことですが

3.3	HOOKの例:ある行数を越えるメールは廃棄する設定

We discard mail with over 1000 lines. Today please use
$INCOMING_MAIL_SIZE_LIMIT for incoming mail size upper limit.
See also: 3.1 

$START_HOOK = q#
    if ($Envelope{'nlines'} > 1000) {
	&Warn("Discarded on the behalf of too Large Mail", &WholeMail);	
	$DO_NOTHING = 1;
    }
#;

3.4	$START_HOOK でＭＬメンバーの人数制限をする

ファイル $LIMIT_OVER_FILE にごめんなさいの文章を書いておく。
Ref: START_HOOK => hooks 3.1

$START_HOOK = q%;

$MAX_MEMBER = 100;

$LIMIT_OVER_FILE = "$DIR/limit.over"; 

sub WC
{
    local($f) = @_;
    local($lines) = 0;

    open(TMP, $f) || return 0;
    while (<TMP>) { 
	next if /^\#/;
        $lines++;
    }
    close(TMP);

    $lines;
}

if (&WC($ACTIVE_LIST) > $MAX_MEMBER) {
    &SendFile($From_address, 
	      "Sorry, the mailing list member exceeds the limit $ML_FN", 
	      $LIMIT_OVER_FILE);
    $DO_NOTHING = 1;
}

%;


		INDEX

$ANNOUNCE_MAIL_SIZE_OVERFLOW               ...   3.1 
$INCOMING_MAIL_SIZE_LIMIT                  ...   3.1 
$MAX_MEMBER_LIMIT                          ...   3.2 
$MTI_APPEND_TO_REJECT_ADDR_LIST            ...   2.8 
$MTI_BURST_HARD_LIMIT                      ...   2.5 
$MTI_BURST_MINIMUM                         ...   2.6 
$MTI_BURST_SOFT_LIMIT                      ...   2.5 
$MTI_COMMAND_DB                            ...   2.9 
$MTI_COMMAND_TRAFFIC_MAX                   ...   2.7 
$MTI_COST_EVAL_FUNCTION                    ...   2.6 
$MTI_COST_EVAL_HOOK                        ...   2.6 
$MTI_DB                                    ...   2.9 
$MTI_DIST_DB                               ...   2.9 
$MTI_DISTRIBUTE_TRAFFIC_MAX                ...   2.7 
$MTI_EXPIRE_UNIT                           ...   2.4 2.8 
$MTI_HI_COMMAND_DB                         ...   2.9 
$MTI_HI_DB                                 ...   2.9 
$MTI_HI_DIST_DB                            ...   2.9 
$MTI_MAIL_FROM_HINT_LIST                   ...   2.9 
$MTI_TIE_TYPE                              ...   2.11 
$NOTIFY_MAIL_SIZE_OVERFLOW                 ...   3.1 
$START_HOOK                                ...   3.3 3.4 
