2006年7月11日

[postfix-jp: 2149] sleep中にコネクションが切断されたことを検出したい

さとうです。

 Postfix2.3で、動的IPと思われる接続に対してsleepで遅延を掛けることで、
スパム対策を行っています。
Starpitでほぼ誤検出無く98%のスパムを排除
http://d.hatena.ne.jp/stealthinu/20060706/p5

 遅延を掛けるため、通常ならすぐに処理の終わるセッションが残るため、スパ

ムの可能性が99%近い動的IPからの接続のみに掛けても、普通にsmtpdが起動して
いるプロセス数のだいたい倍くらいのプロセス数に増えてしまいます。
 そのほとんどはsleepしているだけなのでCPU負荷は無いのですが、メモリは食っ
てしまいます。

 そこで、遅延している間に相手が接続を切ったら、smtpdもすぐに終了すれば
メモリの節約が出来るだろうと考えました。
 そこで、ソースを見たところ、smtpd_check.c の generic_checks 関数で
sleep(atoi(*++cpp)); としている行が遅延を掛けていたため、ここで例えば1秒
ごとにポーリングして、切断されているかを確認すれば良いだろう、と思いまし
た。

 そこでどうやって切断を確認しているのか見たところ、smtpd.c の
smtpd_proto 関数で vstream_setjmp(state->client) の戻り値が SMTP_ERR_EOF
で見ており、vstream_longjmp で SMTP_ERR_EOF を返しているのは smtp_stream.c
の smtp_fgetc 関数などで、vstream_feof や vstream_ferror などで判定して
いるようなので、smtpd_check.c の generic_checks 関数でsleepしているとこ
ろを以下のように修正してみました。

/* sleep(atoi(*++cpp)); */
int sleep_time = atoi(*++cpp);
int i;
for ( i = 0; i < sleep_time; i++ ) {
sleep( 1 );
if (vstream_feof(state->client) || vstream_ferror(state->client)) {
msg_warn("lost connection during sleep %d", i+1);
break;
}
}

 telnetで25に接続し、そのプロセスをkillして切断が検知できるか確認してみ
たのですが、残念ながらこれではクライアントの切断を検出できませんでした。

 それで質問なのですが、vstream_feof や vstream_ferror では、接続が切れ
たことを確認することは出来ないのでしょうか。
 socketでの通信を考えると、送信側がshutdownしてくれないと切断を検知する
ことが出来ないような気もします。
 (切断テストをしたプロセスのkillではなく)selectでタイムアウト時間を設定
している場合には、shutdownがされると考えて良いのでしょうか。


--
佐藤 潔 (SATOH Kiyoshi) http://d.hatena.ne.jp/stealthinu/

_______________________________________________
Postfix-jp-list mailing list
Postfix-jp-list@xxxxx
http://lists.sourceforge.jp/mailman/listinfo/postfix-jp-list

投稿者 xml-rpc : 2006年7月11日 14:21
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/39357
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。