« あー、昨日のソースちょっと違うなあ | メイン | Linux Kernel2.6.17.10がきてます。 »

2006年8月23日

MovableTypeのTrackBackの処理を変えてみる。多分最終版 >>MovableType 

MovableTypeのTrackBackの処理を変えてみる。で初版リリースをした上で、
あー、昨日のソースちょっと違うなあ で、追記をしましたが、大きな問題ではありませんが、ロジック的に納得いかないものなどもありましたので、書き換えました。おそらくこれが最終版・・・だと思います。

Comment.pmの方でも使われていた
$ipban->commit();
は、ipbanのソースにメソッド(オブジェクト?)が存在しないため、そもそもバグです。

今回はこねくり回しているので、結構改変要素が大きいです。
何をするかというと
1.Trackback用のスロットルコントロール秒を指定する。
1~2の追加がそう。
ThrottleSecondsと同様のままでよければ(テストしてないけど)、特に追加はしなくても良い。
一応普通に操作しているユーザを想定するなら長めでいいはず。ただ、大手のblogサービスなんかから大量にpingが来るような場合がもしあるのなら、120(2分)は長いのかもしれない。

2.トラックバックのスロットルコントロール本体の変更
3~4がそう。
A.トラックバックデータ内に、ThrottleSecondsPings秒の間に同一IPからのpingが来たら除外をする。
注意しなければならないのは、pingを除外した場合(Commentでも同じことなんだけれども)その間、そのIPからのデータはトラックバックデータ中に存在しないため、そのままだと、その間だけやり過ごせばpingを送ることが可能になるということ。
エラー用のデータを1つ持っておいて、最後のエラーから+2分というような処理ではない。

エラー用のデータを持たせて、投稿->1分0経過->再投稿->ここから2分待たなければならない という処理が本来はロジック的には理想だけれども、そのような構造で作られていません。
投稿->とにかく投稿...->2分以降で一旦禊が済んだ時点で受け入れがされてしまう。

※そこまで改変すると、次のバージョンアップとかが来た際に大事になると困るのでやれるけどやってません。ま、大きなところではデータを残すことがデータ増加による負荷増ということにもなりますから、この辺りもどう考えるかっていうところですけれどもね。個人的にはいつもそうするので、テストの際面くらいましたけども。あーあー、そうなのね、という感じ.....。

B.更にIPBANのための処理
ThrottleSecondsPings x 10 - 1秒(120と指定していれば、1200秒で20分)の間に4回トラックバックがデータとして残っていれば(ここも、トラックバックがSPAM LookupでSPAMと見なされていようがなんだろうが、「トラックバックデータに残っているものが対象」になることに注意) IPBANの対象とみなし、IPBANを行った上で、ログに残し、メールを送る。20min/4 なので、5分に1回ですから、大手blogサービス等から送られてくる場合のことがちょっと心配ではありますが・・・。
(コメントの場合は、200秒間に8回でBANにするように定義されています。)
ログを残すようにしましたので、動作状況を見ながら変えてみてください。
ま、無駄なもんはばんばんBANしちゃえばいいんじゃないの、と。Proxyほいほいにも使えるかもしれないしね。

ここいらもconfigに分離してもよかったんですけどねえ。

C.その他メモ
コメントは書いておきましたが、
もしも複数のblogをホストしていて、個別のblogに対してのipを排除の条件にしたければ、blog_id => $tb->blog_idのコメントアウトを外してください。
但し、SPAMユーザの行動から考えると、同一のドメインのサブドメイン等に対して並列的にアタックをかけるでしょうから、コメントアウトすべきではないと考えます。

MT3.31Jaでしか試してませんので、他のバージョンではうまく動くかどうかわかりません。

では、ソース等。
その1、その2はがんばって書き換えてください。
その3、その4は、Trackback.pm丸ごとのソースを置いておきます。>これ

その1
mt-config.cgiにThrottleSecondsPings 120
を追加します。

その2
ConfigMgr.pm(lib/MT/ConfigMgr.pm)に以下を追加
['ThrottleSecondsPings', { Default => 20 }],
mt-configで指定せず、ここで、120としても構いません。

その3
TrackBack.pm(lib/MT/App/TrackBack.pm)を書き換える。
_builtin_throttleを前回のように別名にしておいて、以下に書き換える

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

#If ThrottleSeconds is set to Ping, please set it as ConfigMgr.pm.
#Furthermore, if a variable is defined on mt-config.pm, cannot receive Ping from the appointed
# number of seconds, and this IP, and it can be carried out.

my $throttle_period = $app->{cfg}->ThrottleSecondsPings;
my $retcode = 1;

if ($throttle_period eq "" || $throttle_period <= 0)
{
my $throttle_period = $app->{cfg}->ThrottleSeconds;
}

return 1 if ($throttle_period <= 0); # Disabled by ThrottleSeconds 0

# This comment will be meaningless if you have not acted as a host of two or more blog(s).
#
#If it is acting as a host of two or more blog(s) and you want to make ip to individual blog
# into the conditions of exclusion, please remove comment out of blog_id => $tb->blog_id.
#
#However, if it thinks from a SPAM user's action, since an attack will be applied in parallel to
# the sub-domain of the same domain etc., I will think that it should not comment out.

my $eh = shift;
my $app = shift;

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} })) {

$retcode = 0;
}
else
{
$retcode = 1;
}

@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,
#blog_id => $tb->blog_id,
created_on => [$from], },
{ range => {created_on => 1} });

#It is a case noting that it is Ping which exceeds the appointed number limit of ThrottleSeconds
# seconds from the last track back.

#IPBAN will be performed if the track back is seen off in less than
# [ ThrottleSeconds * 10 second ] more than as for the number of specification.

if ($count >= 4)
{
require MT::IPBanList;

my $ipban = MT::IPBanList->new();

#Please comment out, if IPBAN is set only to the appointed blog.
$ipban->blog_id($tb->blog_id);
$ipban->ip($user_ip);
$ipban->save();

#Bug. There is no method called commit.
#Whether there is any object or there is nothing grasp, and it is solved.
#$ipban->commit();

require MT::Log;

$app->log({
message => "IPBAN " . " IP:" . $app->remote_ip . " banned because Trackback pings rate exceeded 8 comments",
class => 'ping',
category => 'new',
blog_id => $tb->blog_id,
level => MT::Log::INFO(),
metadata => $user_ip,
});

require MT::Mail;
my $author = $entry->author;
#my $author = $tb->author;

$app->set_language($author->preferred_language)
if $author && $author->preferred_language;

my $blog = MT::Blog->load($tb->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 Trackback pings"));
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);
}
$retcode = 0;
}
return $retcode;
}

その4
TrackBack.pm(lib/MT/App/TrackBack.pm)を書き換える。
sub ping の_builtin_throttleを呼んでいるとこの直下。

my $passed_filter = MT->run_callbacks('TBPingThrottleFilter',
$app, $tb,$entry);
のように、$entryを追加する。(メールを送信する処理のために追加が必要)

その下。403Throttledが起こった際、ログに記述するための処理を追加する。

if (!$passed_filter) {

my($title, $excerpt, $url, $blog_name, $enc) = map scalar $q->param($_),
qw( title excerpt url blog_name charset);
require MT::Log;

$app->log({
message => "Ping Coming 403 Throttled Occurred." . " IP:" . $app->remote_ip,
class => 'ping',
category => 'new',
blog_id => $tb->blog_id,
level => MT::Log::INFO(),
metadata => $url,
});

return $app->_response(Error => $app->translate("You are pinging trackbacks too quickly. Please try again later."), Code => "403 Throttled");
}

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

投稿者 debizoh : 2006年8月23日 05:49



トラックバック

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


コメント

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