_ 先週ごろから画像を JPEG やなんかの画像フォーマットではなく、PDF につっこんでくる spam が届いてる。OCR なテクニックで画像から文字列を抽出するフィルタでも、そもそも画像ファイルじゃなければ効果なし、という発想かな。最近のかっちょええ spam フィルタは使ってないので spammer の目論見があたってるのどうかはわからんけど。
_ PDF って Postscript に毛の生えたようなもので、つまり一種のスクリプト言語なわけなのですよ。画像が1枚張りつけてあるだけの単純な PDF であってもいきなり画像本体のデータからはじまるわけではなく、書式設定とか初期化とか必要なのね、たぶん(よく知らんのでてきとーに書いてる)。この PDF spam は画像の中身は例のごとく毎回異なってるんだけど、ありがたいことに画像データにたどりつくまでの PDF としての入れ物部分がほとんど共通で、これが数百バイトある。つーわけで、この共通部分を見つけたら spam だと判定してやればいいね。もしいつもの GIF や JPEG だったら共通してるのはヘッダの数バイトだけなので、こんな手は使えない。
_ つーわけで、これまでに手元に届いた12通の PDF spam すべてに共通する部分。メールに添付されたそのまま、つまり Base64 エンコードされた状態で行単位で完全一致するもの。
冒頭15行は完全一致しなかったところでも8割ぐらいは同じ。で、後述するように共通部分のいちばん最後を使う。postfix の body_checks で以下を書いてやってズババン。1 JVBERi0xLjMgCjEgMCBvYmoKPDwKPj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL0NhdGFsb2cK 2 L1BhZ2VzIDMgMCBSCj4+CmVuZG9iagozIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovS2lkcyBbIDQg 3 MCBSIF0KL0NvdW50IDEKPj4KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCAz 4 IDAgUgovUmVzb3VyY2VzIDw8Ci9Gb250IDw8IC9GMCA4IDAgUiA+PgovWE9iamVjdCA8PCAvSW0w ... 8 L0ltMCBEbwpRCmVuZHN0cmVhbQplbmRvYmoKNiAwIG9iagozMQplbmRvYmoKNyAwIG9iagpbIC9Q 9 REYgL1RleHQgL0ltYWdlSSBdCmVuZG9iago4IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBl 10 IC9UeXBlMQovTmFtZSAvRjAKL0Jhc2VGb250IC9IZWx2ZXRpY2EKL0VuY29kaW5nIC9NYWNSb21h 11 bkVuY29kaW5nCj4+CmVuZG9iago5IDAgb2JqCjw8Ci9UeXBlIC9YT2JqZWN0Ci9TdWJ0eXBlIC9J ... 14 Ugo+PgpzdHJlYW0KgAAgUDgkFg0HhEJhULhkNh0PiERiUTikVi0XjEZjUbjkdj0fkEhkUjkklk0nprocmail や maildrop や他のツールはそれぞれてきとーにルールを作ってくださいまし。/^Ugo\+PgpzdHJlYW0KgAAgUDgkFg0HhEJhULhkNh0PiERiUTikVi0XjEZjUbjkdj0fkEhkUjkklk0n$/i DISCARD_ ちなみに、アンチウイルス未対応のウィルスの感染が急拡大しているときに、ベンダーから対応パターンがリリースされるまでの一時しのぎに同じ方法が使えることがある。ウィルスのバイナリは同じことが多いので。毎回異なるバイナリを生成して送りつけてくるウィルスには無力なので、その場合は素直にあきらめるか、別のところで共通部分を見つけてください(ヘッダとか)。
_ この手を使うときの注意点。ファイルの先頭部分は使わないこと。先頭数バイトはほぼ確実に固定ヘッダだし、その後の数十バイトも PDF なり実行バイナリなりを生成したツールによっては固定になることが多い。つまり、まっとーなプログラムでもウィルス作者と同じコンパイラを使っていたらファイルの冒頭が一致して false positive となる可能性がある。よって、できるだけうしろの方のそれぞれの spam なりウィルスなりで固有の共通部分を探してそれを body_checks でひっかける(ただしあんまりうしろ過ぎると探す負荷になるし、body_checks_size_limit を越える範囲はそもそも無視される)。こんな Base64 エンコードされた行単位のマッチングじゃなくてもっとまともなチェックをしたければ clamav でパターンを自作するとよろし。もちろんその場合でもファイル先頭は使うな。
_ lang_ja で RFC1033 を I'm Feeling Lucky。なんでそんなところに飛ぶんだ。つーかなんでそんな名前を:-)
_ うーん、ありがたいんだけど、どうせやるのならもっといろんなショートカットを使えるようにしてほしいなぁ。vi 使いなら1行ずつちまちまと j/k で移動するやつなんていないよ。数値プレフィックスとか CTRL-F/B とか使えないと。あと、検索窓に移動するというショートカット(/)が Firefox の find as you type とかぶってるのがアレ。いや、/ 以外のどんなキーで検索するんだと言われたら返す言葉がないんだけど。
_ というわけで、google ネタ3連発。本の中身が検索できちゃうよ、の日本語版がはじまりましたよ、と。
_ 実はかなり期待してたんだけど、うーん、現時点ではこれはちょっと使いものにならない。検索にひっかかる本が少なすぎる。これに尽きる。
_ 本の中身をスキャンさせてくれる出版社が少ないのは、これはまあしかたない。でも、それができない場合でも ISBN とか著者名とかの書誌情報は著作権とはまったく関係ないでしょ。その最低限の情報すら満足に教えてくれないんじゃもう使う価値はない。 早川書房2006年がたったの29冊、 2007年だと1冊もないってのはどうよ。
_ それから、検索対象を和書限定にできるようにして。アルファベットで検索すると洋書ばっかり見つかるけど、いや、それはちょっと……。
_ あと細かいことなんだけど、ISBN で検索するときは 4-1234-5678-9 ではダメで 4123456789 のようにいちいち手でハイフンを削らないと google が情報を持ってる本でも検索結果に出てこない、ってのは人にやさしくない。なんだこの手抜きは。
_ 中身を見せてくれる本については、その表示内容は申し分ないんだけどねぇ。スキャンした画像中に含まれる検索文字列をハイライト表示してくれるのには正直感嘆した。でも、自分の探しているものが検索対象になっていないのならば、そのスゴさもまったく意味がない。将来、書籍のデータベースが大きくなったらかなりありがたいサービスになるかもしれないけど、少なくとも現時点においてはどうしようもなくダメ。検索にひっかからない検索サービスなんてなんの意味もない。
_ メンテナンス画面を簡単に出してみる。なんかムダなことやってるような気がする。
_ apache で 503 エラーを出すのにいちばん簡単なのは Redirect を使うこと。
これで /hoge/* へのアクセスが 503 エラーになって 503.html が表示される。rewrite も PHP もいらない。Redirect 503 /hoge ErrorDocument 503 /503.html_ もうひとつ、こういう方法もある。要 mod_asis。
503.asis の中身はこんな感じ。AddHandler send-as-is asis Redirect /hoge /503.asisつまり、CGI で 503 を出力する場合と同じものをそのままファイルに入れておくだけ。特殊なステータスコードや特殊なヘッダを吐きたいけど、コンテンツ自体は静的、という場合には CGI や PHP なんかを使うよりも send-as-is の方がはるかに軽くて速い(それどころか default handler と比べても速かったような記憶があるんだが勘違いかも)。Status: 503 Service unavailable Content-Type: text/html <html> <head> ..._ Redirect 503 を使う場合は別のディレクティブで替えは効かない。mod_asis を使う場合はそこに飛ばすことさえできれば Redirect でなくても手段は問わない。2年前の某イベントのサーバで実際に使ったときは Alias だったし、もちろん mod_rewrite を使ってもいい。
とーぜんこんなのも可。<Files hoge.html> SetHandler send-as-is </Files>_ それから、もしかしたら
なんて方法でも可能かも。試したことないけど。<Files 503.html> Header set Status "503 Service unavailable" </Files>_ 見りゃわかるけど、もちろんこの方法で 503 以外のステータスも吐けるので念のため。
_ つーか、みんな mod_rewrite が好きだねぇ。オフィシャルのドキュメントに mod_rewrite は黒魔術だとか sendmail だとか書いてあったのは知ってるのかしら。みんな sendmail は嫌ってるくせに、rewrite は平気で使うんだから。mod_rewrite でいろんなことができるのは事実だけど、何をするにもまっさきに rewrite を使うことを考えてしまうのは矯正した方がいいと思う。
私が昔やっていた方法はメンテナンス画面表示専用ノートPCを用意する方法です。ノートPCにApacheを入れて超軽量メンテナンス画面データを置いておきます。メンテ時間になったらロードバランサーの向き先を切り替えるか、LANケーブルごとぷちっと差し替えることでメンテナンス画面に切り替えます。この場合でも 200 ではない適切なステータスコードを返すように設定しておかないと、メンテはとっくに終わってるのにブラウザやプロクシがメンテ画面のキャッシュを返し続けてしまうことがあるので注意。少しでもサーバ負荷を減らすために、HTTP Response headersを書き換えてWEBブラウザのキャッシュに残るようにした。200 のステータスでやってるのであれば、これはよろしくない。正常の表示ではないことをブラウザ表示ではなくステータスコードで明示しておかないと、たとえば後日 google で検索するとメンテ画面がキャッシュされているかもしれない。503 で応答した上で、メンテが終わるまでリトライするな、と Retry-After: ヘッダで伝えるのが正解。Retry-After を正確に解釈するブラウザがどれだけあるのかは知らない。
_ きのうの 503 の件は、 asis のページに Redirectしちゃダメだな。いったん 302 で飛んで、その先が 503 になるだけだ。寝ぼけてた。 Redirect 503は問題ないけど。
_ mod_rewrite を使わずに正しく asis の 503 ページに飛ばすには、こう。
エイリアス先の末尾スラッシュ重要。/hoge/fuga へのリクエストが 503.asis/fuga にエイリアスされる。pathinfo を受け取るようにしてあるので、こういうリクエストが来ても not found にならない。いや、もちろんそんなことを気にしなくて済むようにAlias /hoge/ /somewhere/503.asis/ <Directory /somewhere> AcceptPathInfo on </Directory>としてもいいんだけど。AliasMatch /hoge/.* /somewhere/503.asis_ Header ディレクティブで Status: 503 を返すのは、試してみたけどダメだった。ふつーに Status: 503 というヘッダが返ってくるだけで、CGI のようにこれをステータスコードに翻訳してくれたりはしないみたい。残念でした。