とかさんざんdisっておきながら、結局DovecotのSieveプラグインを入れてるというこのザマね。
念のため言っておくと、配送時に特定条件でIMAPフラグをいじる方法が現実問題として他になくて、仕方なく入れたんだからね。言語仕様はやっぱりどうしようもなく気持ち悪いし、implicitな挙動があれこれあって念入りに sieve-test しないと怖くて使えたもんじゃないし、実装毎の独自拡張がざらにあったりする時点でお察しですよ。まぁsyntaxの気持ち悪さという点ではProcmailも相当だけど、俺的にはProcmailの方が全然食える。
とまぁ誰得なヘイトを撒き散らした (もしくは自分が如何に古臭い人間かを晒した) ところで、導入メモ。
要件整理
大きな要件は以下の二つ。
-
ベイジアンフィルタ (具体的にはBogofilter ) でspam判定されたメールをJunkフォルダに振り分ける。
-
ヘッダ・本文中の文字列パターンに応じてフォルダに振り分ける、もしくはIMAPフラグを立てる。
前者がSieveにとっては鬼門。Procmailなら判定と振り分けをたった2行で書けるのに、Sieveにはそもそも個別のユーザ権限で外部コマンドを叩く術が存在しない。あーはいはい、セキュリティ万歳、アーキテクチャ非依存万歳。ベイジアンフィルタは各ユーザが独自にDB管理できて然るべきだろjk、とか語っても始まらないので、百歩譲って (どうせこのサーバのユーザは俺一人だし‥‥) After-Queue Content Filterの仕組みを使ってPostfixのレイヤーでBogofilterに通し、Sieveではヘッダを見て振り分けることにした。 extprogramsでもイケるのかもしれないけど、できるだけSieveの深みには嵌まりたくない。
後者はさすがに余裕だろ、とか思ってたら落とし穴があって、 少なくともDovecotのSieve実装であるところのPigeonhole (0.3.1) では、bodyを :regexにかけると ^ と $ がいずれかの行の先頭・末尾 ではなく bodyの先頭と末尾にしかマッチしない。あーはいはい、bodyが一つのstringなんですね。もう :containsでいいよ好きにしろ。
設定方法とか
ターゲット環境がDebian wheezy標準のPostfix + Dovecot + Bogofilterであることは大前提。
1. mailbox_command でLDAをDovecotに
2. smtpdを経由するメールがBogofilterを通るように
3. Dovecot Sieveプラグインのインストールと設定
4. ユーザ用Sieveスクリプトの準備と配置
5. (option) 再学習の仕組み作り
Arrange for users to send misclassified mail to a particular mailbox and make sure that the database is updated regularly.
file:///usr/share/doc/bogofilter/integrating-with-postfix
- メールを直に流すなり定期的に拾うなり、何らかの方法でBogofilterコマンドを叩くようにすればいい。
- イタズラされたりしないように多少の考慮は必要 (なのでこっちの手の内は明かさない ;-)
感想
設定が済んでちゃんと動作してるのが無事確認できてしまうと、まぁそこそこの満足感があったりするのがSEとしての悲しい性なのだけど、一方でSieveを導入したことでこれからチョー夢がひろがりんぐ、とは全く思えないので、労力に見合うだけの価値があるかと聞かれれば、否。既にProcmailとかmaildropとかでバリバリ設定作り込んでるユーザが「Sieve、いいなぁ‥‥」とか反射的にヨダレ垂らす類のもの じゃない のはきっと間違いない。Sieveにしかできないことなんてほとんどないし。
要は、ユーザみんなvirtualなんで古き良き手法じゃユーザ個別のフィルタリングとか無理なんですよね、みたいなそこそこデカいメールシステムを作るときにManageSieveとか共通スクリプトとかガンガン使いつつキモいところはUIでうまく隠蔽してほらフィルタリングできますよvacationだって飛ばせますよとか売り込みたい、そんなSIerポジションな皆様向けの機能だと思うんですよね、Sieveって。まぁ知ってたけど。
必要なディレクトリだけcpioなりでアーカイブして、rsync over SSHで吸い出すことにする。
まだ設定してないけど。
88171.net :: FreeNAS稼働開始
というわけで、この鯖 (さくらのVPS) のクリティカルなデータを自宅のNASにバックアップしましょう、と、ようやく重い腰を上げた次第。で、前々から目をつけてたrrsyncがいざ使ってみたらちょいステキだったので軽く紹介してみようかと。
rrsyncとは何ぞや
かの有名なrsyncに付属のプログラム、というか200行ちょっとのPerlスクリプト。名前の由来はRestricted rsyncの略 (のはず) 。
いざインターネット越しでサーバからデータを吸い出す処理を自動化しようと思うと、これが単純に見えて意外とめんどくさい。
--delete とかチョー便利だから、やっぱscpとかじゃなくてrsync使いたいよね。
- インターネットに出るなら通信を暗号化したいから、やっぱ通信はover SSH一択だよね。
- その場合お決まりのパスフレーズなし鍵ペアで公開鍵認証、なんだけど、シェル開けるのはなんか怖いよね。
- えっ?ログイン時に実行するコマンドを公開鍵に設定できるの?でも rsyncのサーバ側コマンドなんてどう決め打てばいいのさ!?
このモヤモヤをさくっと解決してくれるのが、rrsync。
ざっくり使い方と仕組み
まずはrrsyncをサーバ上のどっかに置く。Debian系のパッケージならたぶん /usr/share/doc/rsync/scripts/rrsync.gz にgzip圧縮されたものが、source tarballなら support/rrsync に生スクリプトがあるはず。
次にrsyncしたいアカウントで普通に鍵ペアを作って、公開鍵認証の設定をする。で、ログインできるのを確認したらサーバ側でおもむろにauthorized_keysの command= にrrsyncを設定する。アクセスを許可するサブディレクトリと、必要なら -ro (read-only) オプションも。
これだけで、そのアカウントの権限でSSHログインする際、許可されたサブディレクトリに対するrsyncアクセス ( -ro オプションが付いていればpullなアクセス) 以外は慈悲なく蹴られるようになる。
仕組みとしては、公開鍵の設定で起動されたrrsyncが本来リクエストされたrsyncのサーバ側コマンドライン (OpenSSHの仕様上、 $SSH_ORIGINAL_COMMAND から取れる) と自分の引数を突き合わせて、問題がなければrsyncをexecするというもの。まぁ言ってしまえば単なるラッパなんだけど、これマジメに自分で書こうと思うとかなりめんどいはず。
まとめ
めんどくさいので細かい設定手順とか書かなかったけど、まぁ実際に自分でrrsyncのソースを読んでみてくだせぇ。大した分量じゃないし、設定方法も書いてあるし。
rrsyncを適切に設定できれば、万一秘密鍵を盗まれても被害を最小限に抑えられます。
# まぁ、そもそも秘密鍵を盗まれるという管理体制が問題アリアリなんじゃ、というツッコミもあるけど、それはまた別のお話。
参考文献
- rrsyncのソースコード
- SSHD(8) のAUTHORIZED_KEYS FILE FORMATセクション
2015-03-07追記
どうも2月の頭くらいからバックアップが止まってた様子。いろいろ調べてみたところこのFIXで、crontabにrsyncのコマンドラインを書くときにリモートパスをより一層ご丁寧にクォートするようになったことが原因らしい。
"user"@remote-host:\""remote-path"\"
つまりこれはFreeNASのエンバグか?と言えばそう簡単な話でもなくて、普通はサーバ側のrsyncもシェル経由で実行されるので、シェルがクォートを外してくれるから何ら問題はない。一方でrrsyncは $SSH_ORIGINAL_COMMAND を自力でバラして解釈するので、結果的にクォートを外さずにrsyncにパスを渡してしまい、
rsync: link_stat ""remote-path"" failed: No such file or directory (2)
とか言われるというわけ。そりゃ、ねーわ。
まぁイレギュラーなことしてるのはこっちですよねー、というわけでrrsyncにクォート外す処理を入れて回避。
--- ./rrsync 2015-03-07 00:37:07+09 1.1
+++ ./rrsync 2015-03-07 00:43:58+09 1.2
@@ -180,6 +180,8 @@
s{^$}{.};
die "$0: do not use .. in any path!\n" if m{(^|/)\\?\.\\?\.(\\?/|$)};
}
+ # Remove quotation from args
+ s{^["'](.*)["']$}{$1} if m{^".*"$} or m{^'.*'$};
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
}
}
セキュリティ的に本当に大丈夫かなこれ‥‥。
人生で3度目のカメラブームが来てる。俺の中で。
第1次: 高校生の頃

カメラ欲しいなと思い立ったものの、当時重度なマニアック志向と金欠を拗らせていたために、
カメラ雑誌の通販広告か何かで見かけて安かったZenit-122に飛び付いた。
既に根っからのメガネ野郎だったので、ファインダーとの隙間から入る光のせいで露出計
(そんな立派な機構でもなかったけど) が全っ然アテにならず、電池抜いてフルマニュアルでバシバシ撮ってた。
修学旅行で普通に中国に持って行って、クラスの連中から軽く引かれたりもした。
結果的に写真の (というか露出の) イロハをこのZenit-122に教えてもらったわけだけど、
今になって思い返せば、最初に使うカメラのチョイスとしては如何なものか、と我ながら思う。
第2次: 大学生の頃

現役のZenit使い、しかもフルマニュアルに抵抗がない人間の興味がいわゆるソビエトカメラ全般に向かうのは最早必然で、
結果的にSMENA 8MにZarya、Zorkiを入手した。
中でもZaryaは、FED-2からレンジファインダーを取っ払ってピント目測、
という至極漢気溢れる仕様だった割に、一番扱いやすくて好きなカメラだった。
シャッターリボン切れちゃって以来、修理にも出さずに放置しちゃってるけど。
ちなみに、ダークレス使ってモノクロネガの自家現像とか手を出してたのもこの頃。
まぁ深く追い求める気にはならなかったけど。
第3次: なう

デジタルな時代の流れには抗えず、
IXY DIGITAL 25 ISとか何となくメインで使ってたものの、
型落ちのさらに販売終了目前で安くなってたのに釣られて
(ついでにM2の新機能に全く魅力を感じなかったので)
EOS Mのダブルレンズキットを衝動買いしたのが去年の秋。
台湾に持って行って久しぶりに街角スナップとかしてて気付いたのは、
やっぱAF遅いなぁ、ということ。
図ったかのようなタイミングでAF性能がガチ強化されたEOS M3が発表されたのは見なかったことにして、
MFで満足に使えるレンズとしてEF28mm F2.8を中古で入手。
AFは言うほど遅くない代わりに (ホントに) ジーコジーコうるさくてビックリしたけど、
どうせMFでしか使わないからいいかな、と。
まぁ今日CP+ 2015でM3の実機触らせてもらったら、
AFめっちゃ速いしダイヤル操作楽だしグリップ快適だしで正直ちょっとだけ いいな なんて思っちゃったんだけど、
まぁ買いませんよ。
Mを使い潰しますよ。