かずひこさんの努力を生かすためにも、mod_rubyの練習をかねて、ちょっと書いてみました。といっても、shugoさんのパクリなのですが。
iptablesやApacheレベルで設定したいのですが、rubyで書きにくく、deployしにくいので、mod_rubyでtry。
reject-spam.rbをRubyパスに置いて(たとえば、/usr/local/lib/site_ruby/1.8/i386-linux)、
<Directory "/home/hoge/public_html/diary/">
RubyRequire "reject-spam"
RubyAccessHandler RejectSpam.instance
</Directory>
とすればOK。TestCaseはこれ。
ただ、きちんと機能しているか不安(というか、確認してない時は動いてないと思った方がよい)。debug messageの出し方が難しい(Apache::Serverのログか、Syslogかなぁ)ので、きちんと落としているのか確認できない。SPAMが来ているのかも、よくわからないし。Apache::Connection#remote_ipで、source ipを取れると思っているのですが。
IPによるマッチングよりも、Referer文字列によるマッチングの方がよい気がしました。IPだと白か黒か一見分かりませんが、Refererの方であれば、人間が見てすぐに分かりますので。
かずひこさんリストがどのように作られているのか興味あります。おそらく、既存のフィルタをかいくぐってきたものだと思うので、「既存のフィルタ」部分も反映させないといけない。
フィルタのない裸状態のサーバをおとりとして用意して、そこに溜った上位20は自動的にBlack Listにするとか。
DoS Referer SPAMは悪質で、Apacheのステータス(403や404)に関わらず続けてくるので困ります。そこで、Black ListにはFORBIDDENを返すのではなく、1MBくらいのdummy HTMLを200で返してあげるというのはどうでしょう。みんながそう返すようにしたら、向こうの回線がパンクすると思うのですが。
いくつか気づいたリファラから IP のリストを作って、次にそれらの IP からのアクセスのリファラを集めて作っています>リファラリスト<br>なので、既存のでひっかかって 403 になったものも含めてリストに入っています。
ADSLだとこっちの上りが先にパンパンになってしまいそうな気がするんですが。(被害者が同一局に複数いる場合)
数字に根拠はなくて、100KBでも10KBでもよくて、Statusを返すだけでは軽すぎるかなと。ただ、向こうも、データ全部を受け取っているとは限らないので、効果はないかもしれませんね。
ステータスを返すまでにいくらかスリープする、というのはどうでしょう? 向こうのロジックにもよりますが、その間こっちはTCPポートひとつ消費するだけでCPUもネットワークも消費しない。少なくともDoSのペースは落とせると。
Apacheプロセス数が増えるので、その分のメモリの余裕がサーバにあれば可能です。うちではだめです(T.T)。
うーん、いいアイデアだと思ったんだけどなぁ。だめですか、残念です。
Apacheの手前にプロクシというかフィルタを置いて、そこで該当するIPアドレスからsynを受けたらackだけ立てて返す(synは立てない)とすると効果的かも。
htaccess で referer 文字列マッチではじいて,そこでできた error.log を parse して iptables に噛ませています.referer 文字列と IP アドレスによるハイブリッド形式.いまのところうまくいってます.<br><br>spammer によってこちらの(CPU time and memory)リソースが喰われるのはとーってもイヤなので,ひっかかったヤツはいきなり iptables でまとめてドーン(DROP)ですよ.<br>かなりたくさんのパケットが iptables で引っかかります.kern.log の容量がかなり増大してアレなんですけどね^^;
apache で wait を噛ませるというのは DoS の隙を作ることになるため,避けた方が無難です.<br><br>ab -n 10000 -c <MaxClients より多い数> URL<br><br>とかやられたら,それで DoS 成立ですよ….
そうか、勉強になります。