« ネットワークが止まります | メイン | CSR、企業にできる貢献と、削減策 »

2006年8月22日

MovableTypeのTrackBackの処理を変えてみる。 >>MovableType 

T-4さんからご指摘頂いた通りで、MovableTypeで「トラックバックのThrottole」によってトラックバック受付が出来ない状況になっていました。

どういうことかをまず説明します。
mt-config.cgiには、以下の記述を行うことができます。
・OneHourMaxPings
・OneDayMaxPings
Pingsというのは、まあ、簡単に言いますとトラックバックです。

MovableType3.2のマニュアルによりますと
OneHourMaxPings =item * OneDayMaxPings
OneHourMaxPingsは、特定のブログに対するトラックバックについて、1時間に受けつけられる最大値を設定できます。初期値は10です。OneDayMaxPings は、特定のブログに対するトラックバックについて、1日に受けつけられる最大値を設定できます。初期値は50です。これらは、ThrottleSecondsで制御できないトラックバック・スパムを制限することに利用できます。

ということになっています。
このエラーはトラックバックを送ろうとしている相手側に「403 Throttled」のエラーメッセージを表示しますが、受け手側には「エラーログが残らない」ようです。(設定で変更できるのかどうかはわかりませんが・・・)
もし、SPAMが多ければ、OneDayMaxPingsを越えてしまって、トラックバックを受け付けることができなくなってしまいます。しかも、受け手側は一切そのことに気が付きません。さあ、困った。

一応、403 ThrottledでGoogleで調べてみると、ip addressを組み合わせて対応されている方もいらっしゃいます。

ソースを眺めてみます。

package MT::App::Trackback;

sub _builtin_throttle {
my ($eh, $app, $tb) = @_;
my $user_ip = $app->remote_ip;
use MT::Util qw(offset_time_list);
my @ts = offset_time_list(time - 3600, $tb->blog_id);
my $from = sprintf("%04d%02d%02d%02d%02d%02d",
$ts[5]+1900, $ts[4]+1, @ts[3,2,1,0]);
require MT::TBPing;
if ($app->config('OneHourMaxPings')
<= MT::TBPing->count({ blog_id => $tb->blog_id,
created_on => [$from] },
{range => {created_on => 1} })) {
return 0;
}

@ts = offset_time_list(time - $app->config('ThrottleSeconds')*4000 - 1,
$tb->blog_id);
$from = sprintf("%04d%02d%02d%02d%02d%02d",
$ts[5]+1900, $ts[4]+1, @ts[3,2,1,0]);
my $terms = {
blog_id => $tb->blog_id,
created_on => [$from]
};
my $count = MT::TBPing->count($terms, {range => {created_on => 1} });
if ($count >= $app->config('OneDayMaxPings')) {
return 0;
}
return 1;
}
で、「コメント」側・・・は、長いから割愛しますが、「ThrottleSeconds」はIPベースでのDoSに対しての攻撃に対して有効であると考えられます。

しかしながら、トラックバック側は上記のような処理です。
例えば、「閾値(しきいち)」を上げて対応しても、もしかしたら受け取れなくなってしまっているかもしれない。更に、その状態になっているかどうか、管理画面上でぱっと見で判断できません。

とりあえず受け付けておいて処理をすべき「cf. Qmail」なのではないかと思ったりしますが、所詮はメールのように絶対的に届かなくては困るという程のツールではないという扱いなのでしょうか。

・・・さて、まあ、そんなことは置いときまして、連続したIPからのDoSトラックバックを拒否し、IPBanし、更にはメールを送る、というコメントの場合と同様のソースにちょっと書き換えてみました。
この辺り、イロイロとロジック的には考えられるところでしょうし、人各々捕らえ方も違うかなとは思いますけれども、私としてはDoSを防げればよいかな、と、そんな風に思っております。本当に1PingごとにIPローテーションしてきたら、元のでも、これでも、意味を成しませんから。

_builtin_throttleの大本は、何かあったときのために_builtin_throttle_org とか、そんな名前に変更しておきます。
一応、ちょっとしたテストでは動いているようです。同blogに対して複数のTrackBackを送ろうとかするとちゃんと403 Throttledになります。
きっちりIPBANまで動いてくれるのかどうかは、まだうまくチェックできていませんが・・・
mt-config.cgiのThrottleSeconds(デフォルト値20)の間に同一IPからPingが来た場合のみ排除します。 configに変数を追加した上で、もうちょっと長い時間を指定してもいいのかもしれませんが・・・。
とりあえず、これで様子見してみます。
※Movebletype 3.31JPのみでテスト。lib/MT/App/Trackback.pmを書き換えてくださいまし。

お持ち帰り用ソース テキストファイル
以下そーす。...use MT::Utilが重複しやがってますケド...ま、まあとりあえず動いてます(汗

sub _builtin_throttle {
my ($eh, $app, $tb) = @_;
my $user_ip = $app->remote_ip;
use MT::Util qw(offset_time_list);

my $throttle_period = $app->{cfg}->ThrottleSeconds;
return 1 if ($throttle_period <= 0); # Disabled by ThrottleSeconds 0

my $eh = shift;
my $app = shift;
my ($entry) = @_;

require MT::Util;
my @ts = offset_time_list(time - $throttle_period,
$tb->blog_id);
my $from = sprintf("%04d%02d%02d%02d%02d%02d",
$ts[5]+1900, $ts[4]+1, @ts[3,2,1,0]);

#if Existed TB Ping , Goto Error
if (MT::TBPing->count({ ip => $user_ip,
blog_id => $tb->blog_id,
created_on => [$from] },
{range => {created_on => 1} })) {
return 0;
}

@ts = offset_time_list(time - $throttle_period * 10 - 1,
$tb->blog_id);
$from = sprintf("%04d%02d%02d%02d%02d%02d",
$ts[5]+1900, $ts[4]+1, @ts[3,2,1,0]);
my $count = MT::TBPing->count({ ip => $user_ip,
created_on => [$from],
blog_id => $entry->blog_id },
{ range => {created_on => 1} });
if ($count >= 8)
{
require MT::IPBanList;
my $ipban = MT::IPBanList->new();
$ipban->blog_id($entry->blog_id);
$ipban->ip($user_ip);
$ipban->save();
$ipban->commit();
$app->log({
message => $app->translate("IP [_1] banned because comment rate exceeded 8 comments in [_2] seconds.", $user_ip, 10 * $throttle_period ),
class => 'comment',
category => 'ip_ban',
blog_id => $entry->blog_id,
level => MT::Log::INFO(),
metadata => $user_ip,
});
require MT::Mail;
my $author = $entry->author;
$app->set_language($author->preferred_language)
if $author && $author->preferred_language;

my $blog = MT::Blog->load($entry->blog_id);
if ($author && $author->email) {
my %head = ( To => $author->email,
From => $app->{cfg}->EmailAddressMain,
Subject =>
'[' . $blog->name . '] ' .
$app->translate("IP Banned Due to Excessive Comments"));
my $charset = $app->{cfg}->MailEncoding || $app->{cfg}->PublishCharset;
$head{'Content-Type'} = qq(text/plain; charset="$charset");
my $body = $app->translate('_THROTTLED_COMMENT_EMAIL',
$blog->name, 10 * $throttle_period,
$user_ip, $user_ip);
$body = wrap_text($body, 72);
MT::Mail->send(\%head, $body);
}
return 0;
}
return 1;
}

twitterこの記事をTwitterでみんなに教える。

投稿者 debizoh : 2006年8月22日 02:39



トラックバック

現在、この記事はトラックバックを受け付けておりません。


コメント

現在、この記事はコメントを受け付けておりません。