古いメールを全文検索できるよう保存する
昔からのメールが溜まってて,検索できる状態で置いときたい.
どんな検索エンジンを使うのがいいかを検討した.
ざっくり言うと
Xapian をバックエンドとするmu でインデックスして,サーバーサイドでmu4e をつかって検索するのがよさそう.
やりたいこと
- 古いメールは,普段目に触れないようにしたい
- 検索したい
- 検索するのはまれなので,常駐プロセスを増やしたくない
候補
- クライアント側で検索
- Mail.app
- Thunderbird
- サーバー側で検索
- Lucene バックエンドなもの (Solr,Elasticsearch など)
- Xapian バックエンドなもの (mu など)
比較
古いメールの一部を使って試す.
- 930MB
- 2.5万通
クライアント側で検索
(MacBook Pro - Retina, Mid 2012)
慣れたメールアプリで検索できるが,インデックスするのにダウンロードが発生する.筋が悪い方法だけど いちおう試してみる.古いメールはIMAP で取ってくる.
インデックス時間 | ダウンロード後のフォーマット | ダウンロード後のサイズ | インデックスサイズ | |
---|---|---|---|---|
Mail.app | 1時間 | .emlx | 1.3GB | 22MB |
Thunderbird | 10分 | mbox | 890MB | 55MB |
Mail.app
-
- インデックス時間も保存メールサイズも現実的
サーバー側で検索
(4 core 3.3GHz + 4GB RAM)
- Lucene ベースのSolr,Elasticsearch はdaemon を常駐させないといけないので,今回の用途には合わない
- Java 書いて直接Lucene 叩けばいけそう (やってない)
- dovecot-lucene はアリかも (libc6 ごとアップグレードする必要があって試してない)
- IMAP SEARCH にも対応できる
- メモリを浪費する可能性ある
- いっぽうXapian は常駐しないタイプのフロントエンドが充実
- 今回はmu を試した
インデックス時間 | ダウンロード後のフォーマット | ダウンロード後のサイズ | インデックスサイズ | |
---|---|---|---|---|
mu | 1分 | - | - | 110MB |
インデックスするには
$ mu index -m ~/Maildir
検索するには,CLI から
$ mu find ipv6
$ mu find from:\*gmail subject:ipv6
のようにするか,mu4e をつかう.
$ emacs -f mu4e
気軽でいい感じ.
インデックス時のスワップに注意
メモリをじゃぶじゃぶ使うタイプのソフトウェアっぽくて,
$ mu index --xbatchsize 1000 -m ~/Maildir
のようにしてメモリ使用量を抑える必要があった.
インデックスの最適化
mv .mu/xapian .mu/xapian.old xapian-compact .mu/xapian.old .mu/xapian rm -rf .mu/xapian.old
インデックスサイズが3.4G → 2.2G まで小さくなった.
まとめ
下のどちらかがいいと思う.
- Thunderbird に食わせて,サーバーからメールを消す
- サーバー側に置いといて,mu か mu4e で検索する
JANOG35 に行ってきた (Day3)
JANOG35 に行ってきた (Day2) に引き続き,JANOG35 レポート.
ほぼ毎回行ってるイベントで,インターネットに関するネットワーク寄りの知見を得られる.参加者はネットワークエンジニア中心.
気になったセッションをいくつか紹介しようと思う.
ところで,この日は駅からこんなバスで送迎してもらった.
ロンドンバス!なぜ! pic.twitter.com/sjKtfxyhuF
— K (@ponytail_68) January 16, 2015
すごい目立ってました...ご通行のかたも「なぜ!」ってなるわ. イベントのホストさん曰く「いや,たまたまバス会社が持ってたんです」なぜこんなの持ってる...
JANOG35会場ネットワークに関して
JANOG35 では,ホストさんとconbu プロジェクトに会場ネットワークを提供していただきました.すごく快適でした!ありがとうございました.
このセッションでは,会場ネットワークを設計 / 構築するにあたり conbu が何を目指して,どうネットワークを作ったかが紹介されている. 知見が溜まっているようで,興味があるひとは結構いそう.
やりたいこと
- 会場側にすでにあるルーターは家庭用のものが多いが,トラブルの原因になりがち
- NAT テーブルが小さい
- 設定を変えられない
- 会場に持ち込むハードウェアを少なくしたい
どうやったか
- 会場からのtraffic を全部VPN でくるむ
- 1つの大きな通信に見えるから,会場ルーターにやさしい
- 他方のVPN 終端はクラウド環境 (物理かも?) にあって,そこからInternet に抜ける
- サーバー類はすべてクラウド環境側に置く
こうすることで「会場が変わっても,現地セットを持っていくだけで簡単に会場ネットワークが構築できるし,事前のテストも半日程度になる」とのこと.
conbu の背景
イベントが多い首都圏などでは,会場ネットワーク運営のニーズはかなりありそう. 「conbu ってなに?」という方には,JPA Thanks CONBU トークセッション のときのスライドをどうぞ.
BGP Flowspec(RFC5575)
タイトルから想像しづらいが,Arbor Networks が出しているDDoS トレンドレポート(ATLAS Q3 2014 DDoS Attack Trends みたいなやつ) を解説付きで説明してくれているので参考になる.
このセッションの主旨は「DDoS を止めるためにBGP Flowspec を使えるかも.なのであらためて紹介します」
感想
- RFC5575 自体はけっこう古くて,2009 年にpublish されたもの
- 私の印象ではあまり注目されてなかったのだが,なぜ今Flowspec を取り上げたのか気になった (が,聞くの忘れた)
セッション中では「Intra-AS ルーティングで使う想定」と言っていたが,RFC を読むとInter-AS もスコープ内に見える
Additionally, it defines two applications of that encoding format: one that can be used to automate inter-domain coordination of traffic filtering, such as what is required in order to mitigate (distributed) denial-of-service attacks, and a second application to provide traffic filtering in the context of a BGP/MPLS VPN service.
経路のoriginator がFlowspec spec のoriginator である必要がありそう
A flow specification NLRI must be validated such that it is considered feasible if and only if: a) The originator of the flow specification matches the originator of the best-match unicast route for the destination prefix embedded in the flow specification.
https://tools.ietf.org/html/rfc5575#page-14
便利につかうために議論したいことはたくさんあって,たとえば
- Transit AS がFlowspec を追加 / 変更したい
- Flowspec NLRI を消す = 広報しないことはできそう
- 逆に,出したFlowspec をTransit AS に操作されたくない
- Flowspec を受け取った側が,ポリシーに応じてFlowspec をpermit / deny したい
のような要望がある気がする.(関連I-D 読んでなくて,現状どうなってるのか分かってません)
- Transit AS がFlowspec を追加 / 変更したい
当世MVNO事情
MVNO 事業者 3社のサービス開発の裏側,ネットワークの紹介,トラブル事例,悩みごとの紹介.いわゆる「格安SIM」の裏側の話.
- OCN Mobile One
- IIJmio
- mineo
ネットワーク構成
- MNO とL2 接続することが多い
- 帯域制御など,付加価値をつけやすい
- 他には回線卸,L3 接続がある
- MVNO 事業者は,P-GW / GGSN / PCRF / PCEF を自社で運用
- IIJ ではRCRF(DCCA) を内製
サービス全般
- IIJmio だと,LTE でIPv6 を使える端末がある
- IPv6 利用率: 1.97%
- MNO のtraffic ピークは夜だが,IIJmio のピークはランチタイム
- MNO との棲み分けが今後のキモ
- MVNO 同士の競争は終焉に向かっているように思える
- 端末検証たいへん
- iOS8 にしたら使えなくなった! とか
- 降ってくるキャリアプロファイルの中身が事前に分からない
- サービスのbackend を作るのが大変.あと交換機高い
- MVNO 全体で,シェア1% とか
- 欧米では10% ほど
感想
RPKIやってみませんか?
GREE のラボ環境でOrigin Validation をやってみた結果と課題の紹介.是非RPKI やってみよう! というメッセージ.
- Validation を集中的に Route Reflector でやろうとしたが,できなかった
- iBGP peer では動作しない
- INVALID になってもログに残す機能がない
- ルーターのリブート時の動作が気に入らない
- ゴールはBGPSEC = Origin Validation + Path Validation
- ルーターはROA の正当性を確認できないので,信頼できるROA キャッシュとセキュアなトランスポートを使うべき
- Origin Validation だけでは対処できない問題も起こっている
- bitcoin を不正に増やすためにroute hijack が使われた が,どうやら配下にAS を作ってhijack したっぽい
- Path Validation が必要なケース
- public ROA cache もあります
- ROA キャッシュの位置について
- IX にpublic なものがある.でも最終的には自社ネットワーク内に置くことが望ましい
- ROA キャッシュの位置について
- JPNIC でROA 作成ツール作り込んでます!
感想
- 簡単な設定で動くので,対応ルーターがあれば試してみると面白いと思う
- ルーティングを変えずに VALID / INVALID / UNKNOWN をマークするだけ,とか
- 中央集権的にvalidate できればいいけど,BGP でできるんだろうか…
- validate するだけなら,もちろんできる
- ルーティングに適用しようとすると,AS border では「INVALID な経路をreject しない」ってことだから そいつが使われる可能性あるんでは
- ルーティングに適用しようと思うとハードルが上がる
- AS border ルーターへの投資
- 第三者 (prefix オーナーやRIR / LIR など) の過失によるトラブル増 -> カスタマーサポートコスト
- DNSSEC と同じ構図
Path Validation で検証できるのは「その経路が AS_PATH どおりに伝搬してきたこと」だと理解してるんだけど,bitcoin のケースを検知するには「Path Validation できない経路をINVALID 判定」しないといけなくて,それはBGPSEC 普及率がかなり高くないとダメなのでは
- 最近の議論を追ってないので,間違えているかもしれません.その際にはご指摘いただけるとうれしいです
JANOG35 に行ってきた (Day2)
先日,JANOG35 というネットワーク系イベントに行ってきた.Day1 は参加してない.
ほぼ毎回行ってるイベントで,インターネットに関するネットワーク寄りの知見を得られる.参加者はネットワークエンジニア中心.
気になったセッションをいくつか紹介しようと思う.
運用から見た研究、研究から見た運用
趣旨は
stateman: A network-state management service
- SIGCOMM2014
- Microsoft
ネットワーク運用の自動化サービス
- OS アップグレード,設定変更,TE
- タスクを渡すと自動で
- タスク間の依存関係を解決
- スケジューリング
- 実行
- 確認
をやってくれる
Azure 内で稼働中
Revisiting Routing Control Platforms with the eyes and muscles of Software-Defined Networking
- SIGCOMM2012
- SDN controller にeBGP を実装し,inter-AS ルーティングを実現しようという話
Google B4: Experience with a Globally Deployed Software Defined WAN
- SIGCOMM 2013
- "before" のように発音するらしい
SDN をつかってWAN 回線の有効利用を実現しました,という話
Google 内で稼働中
- 30~40% だった平均回線利用率が,多くの回線で100% 近くまで使えて平均でも70% になった
SDX: A software Defined Internet Exchange
- SIGCOMM2014
- SDN をIX に適用しようという話
- ポリシー記述言語を作り,OpenFlow に適用する
- multi-latral peering のようなアーキテクチャ
- 利用例
- アプリケーション単位でpeering
- inbound traffic 制御
- LB
- anycast で吸いこんで,dst IP address を書き換える
- firewall,ddos mitigation
感想
ネットワークに話題を限定するので「まあまあ枯れているこの技術,なんで普及しないの? 問題はなんだろう?」「困っていることがあるんだけど,どうしたらいいと思う?」といった運用面での問題解決が中心になる.
事業者間で協調しないとネットワーク全体として動かないので 運用についてガッツリ話すのはいいことなんだけれど,ステークホルダーが多すぎて長期的に取り組むことになる = その場で解決しなかったり,ヒントすらなくてモヤモヤ感が残る.
一方で,技術的に「スゲェ」と思う新しいネタはワクワクできるし,わかりやすい. キーワードを拾うだけでもためになるので,こういうセッションはありがたい.
なぜ、IPv6 対応したくないのか
10年以上同じ話題について議論しているが,主体がコンテンツ事業者に移ってきた.
からみたIPv6 の話.シンプルに言うと
- IPv6 を導入するメリットがない
- サービスに付加価値をつけられる,という類のものじゃない
- ユーザーからの要望がない
- デメリットはある
- 投資,開発コスト,ユーザーサポートコストが増える
最後の登壇者,さくらインターネットは 全サービスでIPv6 ready だそう.すごい.
IPv6 後押し意見 (参加者から)
- IP 放送,VoD でIPv6 を使っている
- 余裕のあるaddressing ができるから
- IPv4 = CGN に頼るという構図になるが,NAT の制約のせいで使えないサービスがあるかも
- WebRTC とか大丈夫?
- 発展途上国ではIPv6 しか選択肢がない
- IoT を考えると,IPv6 スタックしかないデバイスが出るかもしれない
- 個別にアドレスがつくと,TLS のための証明書を発行しやすい
- 試行錯誤が必要なので,ユーザーが少ないうちから始めて知見を溜めたい
- IPv6 アドレスは取得しやすい
感想
長いことIPv6 の議論をしているが,主体が徐々に変わっている.
- IPv4 アドレス枯渇が遠い未来だったころは,Transit ISP の問題だった (~2008)
- どうdual stack を設計/運用する? とか
- IPv4 アドレス枯渇が目前になって,Access provider ISP の問題になった (2008~2012)
- ISP でIPv6 の目途がたったら,サーバーインフラ事業者,モバイルキャリアの問題になった (2012~)
日本ではこんなかんじの経緯だと思う.
私は10年ほどISP + IX でネットワークエンジニアをやっていたが,「無理にIPv6 推進しなくていいのに」というスタンス.「どっちでもいいなら,IPv6 やろうよ」とか「知らないのはヤバいから情報収集しとこう」レベルのことは言うが,基本 「必要になったらやればいい」と思っている.
なので,最後に残ったコンテンツ事業者は「次,おまえの番ね」と言われるかもしれんが,まあ継続的に検討してタイミングがきたら着手すればいいんじゃないかな.CGN やIPv6/IPv4 トランスレーターを運用している事業者にとっては,移行期が長くなると辛いかもしれないが.
ただ,IPv6 でサービスしていないのに「ユーザーがIPv4 ばっかり」というのはおかしいので,ときどきIPv4/IPv6 ともにアクセスできるダミーURL を踏ませるとかして,IPv6 潜在ユーザー数を計測しておくといいかもしれない.
GnukトークンでSSH
SSH 用の鍵をUSB トークンに保存しておいて, two-factor auth できるよ!という話
オープンなライセンス
- hardware design: Creative Commons 3.0
- firmware: GPLv3
面白そうだったのに,見せてもらうの忘れた!
DNSの可用性と完全性について考える。
DNSSEC を導入するpros / cons と,運用して取れた統計データの紹介.
- ccTLD,gTLD の70% 以上は署名している
- cache DNS のうち,4.76% "も" DNSSEC validate している*1
QTNet がcache DNS でDNSSEC validation を運用した経験では
- validation fail するquery は0.05%
- ユーザーからの問い合わせは,ほとんどない
会場サーベイでは「DNSSEC 導入することで可用性が下がる」のを気にするひとが多数派 (2/3 程度)
- DNSSEC validation 環境下でも,NS にcache poisoning されたら乗っ取られる
- cache poisoning を100% 検知できるわけではない
懇親会
かなりいい会場でマグロ解体のような出し物もあり,日本酒バーとか富士通レタスも堪能しました. ホストの特定非営利活動法人ふじのくに情報ネットワーク機構さんありがとうございました!
懇親会なう。 #janog pic.twitter.com/IIF62lSXJJ
— 池田武 (@zeldaudon) January 15, 2015
マグロの解体ショー! #JANOG pic.twitter.com/kFm1hSa1fz
— Yamaha SoundNetwork (@yamaha_sn) January 15, 2015
昨晩の #janog 35 Meeting懇親会でいただいた、富士通製!レタス。朝ごはんに美味しくいただきました。そのまま食べてもかなりいける。 pic.twitter.com/dFVaceMpys
— kinoSi / きのし (@i7kinosi) January 16, 2015
ものづくりの理想郷 を読んだ
著者の山本さん から頂きました.ありがとうございます.
この本は,平和酒造 という酒蔵が抱えていた組織的な問題をどうやって解決したか,蔵元の視点で書かれている.斜陽の日本酒業界にあって,昔はうまくいっていた
- 蔵(職人たち) が酒を造り,蔵元(経営者) が売るという分業制
- トップダウンで意思決定される硬直した組織
が時代に合わなくなって「さあどうしよう」という苦悩と,「こうすればうまくいった.お酒も売れた」という成功体験が書いてある.
日本酒業界に携わる人はもちろん,日本酒好きの人にオススメの一冊.蔵元視点の本なんてあまり見ないし,バックグラウンドを知って飲む酒は旨いはず.
- 作者: 山本典正
- 出版社/メーカー: dZERO(インプレス)
- 発売日: 2014/12/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
平和酒造
ここ数年いろんな賞を取ったり,メディアに取り上げられることが多くて注目していた.
- IWC Regional Trophy
- SAKE COMPETITION 2014
- WOWOW ドキュメンタリー
- 雑誌,書籍 (なぜかプレイボーイにまで)
- 中田英寿さんがブラジルで手がけたN-Bar に出品
- JAL 国際線ビジネスクラスに搭載
ここまで認知されるようになったのは ホントこの数年だと思う.「なにをしたんだ」というのがずっと疑問で,期待して読んでたんだけどマーケティング / 広報など「売る」ところについてはあまり触れられてなかった.残念.
ただ,「やりたいことをやるために まず認知度を上げる必要があるから,回り道でも名刺代わりになるブランドを持て」というくだりは,なるほどなーと思った.
杜氏ってエンジニアっぽい
「職人気質だった杜氏に,部下をマネージメントし 育成することの重要性をわかってもらうまで5年かかった」「杜氏の持つ技術をマニュアル化する必要があった」「酒造のプロセスを計測 / 数値化し,カンバン方式を取り入れた」という描写がある.
本では経営者側の視点だけれど,エンジニアなら「わかるわー,杜氏の気持ちわかるわー」とニヤニヤして読めると思う.
僕はエンジニアで,最近まで大きな企業で働いていた.「苦労して得たノウハウを共有するモチベーションが湧かない」という気持ちはよくわかる.IT 業界だと,今でこそ「情報発信することが自分の市場価値を高める」という空気感があるけれど,これは「情報の鮮度が長続きしないから,隠しとく意味ないよね」という条件と,OSS のような考え方があればこそ.
杜氏のように腕一本で渡っていける業種で,同業者は職人っぽいやりかたでそれなりにうまくやっている中「自分がマネージメントすれば組織が成熟して,そうすると自分も成長できて市場価値が高まる」とか「情報共有すれば回りまわって自分を助けてくれる」という発想にはなかなか至らない.経営者が懇願しても,行動に移すのに疑問はあったはず.
これまでいろんな葛藤があったんだろうなあと思うと,お会いしたことはないが,もしいつかご一緒できたら,この方とはたぶん旨い酒が飲めると思うな.
SpamAssassin が何をしてるか
スパムフィルターをSpamAssassin に変えてから,DNS クエリーが増えた.
「なにこれ」と思ってだいぶ放置してたんだけど,あらためて何をしているか調べた.
ざっくり言うと
SpamAssassin は多数の外部ブラックリストサービスに依存しており,DNS クエリーを使って問い合わせる.スパマー側のMTA 構成やメール本文にもよるが,かなりクエリーを吐く.手元のメールでは 1 通を評価するのに50~70 クエリーほど.
SpamAssassin って?
Perl で書かれたアンチスパムソフトウェア.Wikipedia 読めばだいたい分かると思う.
$ spamc -R < path_to_a_spammail ... Content analysis details: (4.1 points, 4.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.0 RCVD_IN_CSS RBL: Received via a relay in Spamhaus CSS [123.57.40.62 listed in zen.spamhaus.org] 0.0 T_URIBL_SEM_FRESH_10 Contains a domain registered less than 10 days ago [URIs: ncsoft1.com] 0.0 T_URIBL_SEM_FRESH_15 Contains a domain registered less than 15 days ago [URIs: ncsoft1.com] 0.0 HTML_MESSAGE BODY: HTML included in message 0.8 BAYES_50 BODY: Bayes spam probability is 40 to 60% [score: 0.5158] 1.4 RCVD_IN_BRBL_LASTEXT RBL: RCVD_IN_BRBL_LASTEXT [123.57.40.62 listed in bb.barracudacentral.org] 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS
こんな感じで,いろんなルールに基づいてスコアを加算し 閾値を超えたらスパムと判定する.
実際には,Postfix だとコンテンツフィルターに組み込む とか,procmail などでフィルターとしてspamc をくぐらせる.
何をしてるか
- spamc (クライアント) は,spamd (サーバー) に
PROCESS
やREPORT
などのコマンドを送る.その後メールヘッダ + 本文も送る - spamd は設定やルールに基づいてメールをスコアリングし,スパム判定
- spamd はspamc に,実行結果を送る.コマンドにより実行結果の前にリターンコードを送る場合がある
ルール定義は/usr/share/spamassassin/
などにあり,ルールにマッチした場合に加算されるスコア設定も同じ場所にある.
ルール実装はPerl module になっている場合も.
Rules
$ grep -hr loadplugin /etc/spamassassin
これで ロードしているプラグインが一覧できるので,動かしてみたり,コード読んだりして調べた.
- Mail::SpamAssassin::Plugin::URIDNSBL
- Mail::SpamAssassin::Plugin::Hashcash
- Mail::SpamAssassin::Plugin::SPF
- Mail::SpamAssassin::Plugin::Pyzor
- Mail::SpamAssassin::Plugin::Razor2
- Mail::SpamAssassin::Plugin::SpamCop
- Mail::SpamAssassin::Plugin::AutoLearnThreshold
- Mail::SpamAssassin::Plugin::WhiteListSubject
- Mail::SpamAssassin::Plugin::MIMEHeader
- Mail::SpamAssassin::Plugin::ReplaceTags
- Mail::SpamAssassin::Plugin::Check
- Mail::SpamAssassin::Plugin::HTTPSMismatch
- Mail::SpamAssassin::Plugin::URIDetail
- Mail::SpamAssassin::Plugin::Bayes
- Mail::SpamAssassin::Plugin::BodyEval
- Mail::SpamAssassin::Plugin::DNSEval
- Mail::SpamAssassin::Plugin::HTMLEval
- Mail::SpamAssassin::Plugin::HeaderEval
- Mail::SpamAssassin::Plugin::MIMEEval
- Mail::SpamAssassin::Plugin::RelayEval
- Mail::SpamAssassin::Plugin::URIEval
- Mail::SpamAssassin::Plugin::WLBLEval
- Mail::SpamAssassin::Plugin::VBounce
- Mail::SpamAssassin::Plugin::ImageInfo
- Mail::SpamAssassin::Plugin::DKIM
- Mail::SpamAssassin::Plugin::FreeMail
Mail::SpamAssassin::Plugin::URIDNSBL
メール本文に含まれるURI について,下のようなURI DNSBL サービスにDNS プロトコルで問い合わせる. ブラックリストに含まれていたら加点.
- multi.surbl.org
- multi.uribl.com
- dob.sibl.support-intelligence.net
- urired.spameatingmonkey.net
- uribl.spameatingmonkey.net
- fresh.spameatingmonkey.net
- fresh15.spameatingmonkey.net
- fresh10.spameatingmonkey.net
- dbl.spamhaus.org
どれもRFC5782 に基づいて実装されている.
DNS Blacklists and Whitelists (RFC5782)
かんぺきに脇道にそれるが,RFC5782 がおもしろいので簡単に紹介する.
たとえば doms.example.net というDNSBL サービスがあって,そこでは invalid.edu がブラックリスト入りしているなら
invalid.edu.doms.example.net A 127.0.0.2 invalid.edu.doms.example.net TXT "Host name used in phish"
という2つのレコードが登録される.
- A が返すアドレスは何でもいい
- TXT の中身はブラックリスト入りした理由
- A はMUST だが,TXT はSHOULD
ここまではギリギリわかるとしても,multiple sublists encode のムリヤリ感がすごい.
multi.surbl.org などがそうで,一発のクエリ
$ drill example.com.multi.surbl.org
で,6 ブラックリストの検索結果を返せるよう
2 = comes from SC 4 = comes from WS 8 = comes from PH 16 = comes from MW 32 = comes from AB 64 = comes from JP
のようなビットマスクを定義しておいて,IPv4 アドレスなら末尾1オクテットにエンコードする.
example.com.multi.surbl.org A 127.0.0.4
だったら「WS (sa-blacklist web sites) に登録されてるんだな」とわかるし
example.com.multi.surbl.org A 127.0.0.6
だったら「SC (SpamCop web sites) と WS (sa-blacklist web sites) に登録されている」とわかる.
「クライアントがデコードしないと意味を読み取れないなんて,強引なやつだ」と思うかもしれないが
- A レコードが存在 → どれかのブラックリストに登録されていることがわかる
- さらに興味があれば,ビットマスクをデコードしてリストを特定できる
- UDP なので通信コスト低
- リゾルバーが適度にキャッシュしてくれる
これはこれで良くできている.ちなみにRFC5782 はInformational.
Mail::SpamAssassin::Plugin::Hashcash
X-Hashcash
ヘッダーがついていたらHashcash に基づいて評価.
パスすれば減点.
Mail::SpamAssassin::Plugin::SPF
SPF に基づいて評価. パスすれば減点,失敗すれば加点.
Mail::SpamAssassin::Plugin::Pyzor
Pyzor を使って評価.Pyzor サーバー/クライアント間の通信はUDP. スパムデータベースに含まれていたら加点.
Pyzor クライアントがインストールされてなければ,テストされない.
Mail::SpamAssassin::Plugin::Razor2
Razor を使って評価.Razor サーバー/クライアント間の通信はHTTP. スパムデータベースに含まれていたら加点.
Razor クライアントがインストールされてなければ,テストされない.
Mail::SpamAssassin::Plugin::SpamCop
SpamCop へのレポート用プラグイン.スコアリングには関係ない.
spamd を-l
オプションで起動しておき,
$ spamc -C report < path_to_a_spammail
のようにしてレポートする.
Mail::SpamAssassin::Plugin::AutoLearnThreshold
スコアが高い(かなりスパムっぽい) or 低い(かなりハムっぽい) メールを,ベイズデータベースに自動登録する.
通常はsa-learn
コマンドなどを介して学習させる.
Mail::SpamAssassin::Plugin::WhiteListSubject
whitelist_subject
, blacklist_subject
が設定されていた場合,Subject とマッチすればそれぞれ減点,加点.
Mail::SpamAssassin::Plugin::MIMEHeader
MIME ヘッダーを扱えるようにするためのプラグイン.スコアリングには関係ない.
Mail::SpamAssassin::Plugin::ReplaceTags
正規表現パターンにタグを付け,タグでパターンを呼び出せるようにするプラグイン.スコアリングには関係ない.
Mail::SpamAssassin::Plugin::Check
テストの呼び出し元.スコアリングには直接関係ない.
Mail::SpamAssassin::Plugin::HTTPSMismatch
本文がHTML で,リンク先ホスト名とアンカーテキスト内のホスト名が異なる場合,加点.
<a href="http://foo.example.com">http://bar.example.com</a>
のようなやつ.
Mail::SpamAssassin::Plugin::URIDetail
本文に含まれるURI をパターンマッチにより評価できるようにするプラグイン.ルールを定義しないのでスコアリングには直接関係ない.
Mail::SpamAssassin::Plugin::Bayes
ベイジアンフィルターを実現するためのプラグイン.ベイズスコアは9段階に分類され,高いほうがよりスパムと判定されやすい. (0~1%: 減点,99~100%:加点)
- 0~1 %
- 1~5 %
- 5~20 %
- 20~40 %
- 40~60 %
- 60~80 %
- 80~95 %
- 95~99 %
- 99~100 %
sa-learn
コマンドを使って学習させる.
Mail::SpamAssassin::Plugin::BodyEval
本文の内容により評価する.
text/html
パートとmultipart/alternative
パートの差分が大きければ加点text/html
パートとmultipart/alternative
パートの単語数比が閾値を超えたら加点
Mail::SpamAssassin::Plugin::DNSEval
メールを送信してきたMTA のアドレスについて,下のようなRBL サービスに問い合わせる.
- bl.score.senderscore.com
- zen.spamhaus.org
- psbl.surriel.com
- list.dnswl.org
- bl.spameatingmonkey.net
- bb.barracudacentral.org
- bl.spamcop.net
- sa-trusted.bondedsender.org
- sa-accredit.habeas.com
- dnsbl.sorbs.net
- iadb.isipp.com
Envelope From のドメイン部分について,RHSBL サービスに問い合わせる.
- rhsbl.ahbl.org
ブラックリストに含まれていたら加点.
また Envelope From のドメインが A かMX レコードを持っているかどうかを調べ,持ってなければ加点.
Mail::SpamAssassin::Plugin::HTMLEval
本文のHTML にスパムっぽい点がないか評価し,該当すれば加点.
- 短すぎるコメントがある
- embedded オブジェクトがある
- 閉じタグが多すぎる
- フォントがでかい
- フォントのコントラストが低い (背景にまぎれている)
- フォントが文字ではない
- action がmailto: なフォームがある
- サイズの小さいimage タグがある
- 難読化している部分がある
- bgsound タグがある
- 不正なタグがある
- HTML が短すぎる
など.
Mail::SpamAssassin::Plugin::HeaderEval
ヘッダーにスパムっぽい点がないか評価し,該当すれば加点.
- To: がない
- Date: がずれている
- Subject: に,To: のローカルパートが含まれる
- Subject: が大文字
- 宛先に,似たアドレスが並んでいる
など.
Mail::SpamAssassin::Plugin::MIMEEval
MIME ヘッダーにスパムっぽい点がないか評価し,該当すれば加点.
- 添付ファイルがある
- 外国語のメール (よく受信する言語は設定で決めておく)
- multipart のほとんどがtext/html
など.
Mail::SpamAssassin::Plugin::RelayEval
MTA のスパマーっぽさを評価し,該当すれば加点.
- Received: にparse できない行がある
- HELO にIP アドレスが使われ,Received: を名前解決したリスト中に該当アドレスがない
- HELO にIP アドレスが使われ,Received: にIP アドレスのまま載っている
- Received: が偽装されている
- HELO の逆引きがない
など.
Mail::SpamAssassin::Plugin::URIEval
本文中のURI を評価し,スパムっぽいリンクがあれば加点.
など.
Mail::SpamAssassin::Plugin::WLBLEval
送信元,送信先アドレスがブラックリストにあれば加点し,ホワイトリストにあれば減点.
ブラックリスト,ホワイトリストはblacklist_to
, whitelist_to
, more_spam_to
, all_spam_to
などで設定する.
Mail::SpamAssassin::Plugin::VBounce
bounce しているメッセージでも,Received: にホワイトリストに含まれるホスト名があれば減点.
ホワイトリストはwhitelist_bounce_relays
で設定する.
Mail::SpamAssassin::Plugin::ImageInfo
添付画像のスパムっぽさを評価し,該当すれば加点.
- 画像数
- 画像フォーマット
- 画像サイズ
など.
Mail::SpamAssassin::Plugin::DKIM
DKIM に基づいて評価.DKIM-Signature: がついていて,invalid なら加点.
Mail::SpamAssassin::Plugin::FreeMail
メール中にフリーメールのアドレスが含まれていた場合,スパムっぽければ加点.
- Envelope From がフリーメールアドレス
- Reply-To: がフリーメールアドレス
- Subject: にフリーメールアドレスが含まれる
- Reply-To:, From:, body に異なるフリーメールアドレスが含まれる
だいぶ古い3.3.2 で試しました
Debian wheezy に入っていたものをそのまま使ったが,最新の3.4.0 にすれば結構うれしいことありそう.
- ベイズデータベースにredis が使えるので,SpamAssassin が複数ホストで動いていても大丈夫
- IPv6 対応が進んでいる
ブラックリストサービスへの問い合わせ,DNS でいいの?
DNS ゾーンの乗っ取りやキャッシュへの毒入れが流行っているので心配になるが,「多数のサービスを串刺し検索して使っているから大丈夫」って判断なのかな? よくわからない.
スパムは止まってる?
閾値の調整 + デフォルト設定 + ベイズデータベース学習で,ほぼ判定できている. false positive に振るか,false negative に振るかは好みかな.
required_score 4
いまはこんな閾値.時代に合わないルールもあるので,ブラックリスト系とベイジアンフィルターの重みを上げてもいいかもしれない.
Yosemite でSCR3310-NTTCom をつかう
e-Tax などでおなじみの公的個人認証サービス(JPKI) に必要なICカードリーダーのうち,鉄板だという「SCR3310-NTTCom」が生産終了になるらしい ので1つ買ってみた.
ざっくり言うと
OSX10.10 (Yosemite) で使うには
- メーカー製のドライバーには触れるな
- 必要なドライバー のインストール
これでOK.JPKI 利用者クライアント はそのまま使える.
NTTコミュニケーションズ 接触型ICカードリーダー・ライター e-Tax Win&Mac対応 SCR3310-NTTCom
- 出版社/メーカー: NTTコミュニケーションズ
- 発売日: 2007/07/24
- メディア: Personal Computers
- 購入: 94人 クリック: 2,093回
- この商品を含むブログ (41件) を見る
メーカー製のドライバーには触れるな
メーカーサイト に純正ドライバーがあるが,Yosemite では動かない.
動かないばかりか 標準のCCID クラスドライバーを削除して,アンインストール後も元に戻してくれない.やってしまったらバックアップ等から /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle
を戻すしかない.
必要なドライバー のインストール
Apple サポートサイト
You must obtain the driver (Tokend) installer necessary to support the type of smart card in use from one of several open source or commercial third-party providers. For more information on tokend installers, smart cards, and smart card software updates, or for discussion and support, see the SmartCard Services project on the Mac OS Forge website.
(http://support.apple.com/kb/PH19083?viewlocale=en_US)
にあるとおり,必要なドライバー をインストールする.インストールしておけば住民基本台帳カードを挿したときにJPKI.tokend
が自動で起動する.
スマートカードに対応したtokend を入れとかないと カード内のトークンをsecurityd
に渡してくれず,使えない.
ちなみに,JPKI.tokend
なしでJPKI利用者ソフト.app
の "動作確認" 機能を使ってみるとこんな感じになる.
SCardEstablishContext OK SCardListReaders OK Reader01:NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader SCardGetStatusChange OK SCARD_READERSTATE->dwEventState : 0x00000022 SCARD_STATE_PRESENT SCARD_STATE_CHANGED SCardConnect OK SCardStatus NG return :SCARD_E_INSUFFICIENT_BUFFER(0x80100008) SCardDisconnect OK SCardReleaseContext OK
SCR3310-NTTCom を買ってきて,何も考えずにYosemite に接続したらこの状態のはず.
JPKI 利用者クライアント はそのまま使える
Java ですから.
まったくどうでもいいが,「公的個人認証サービス」を英語では「Japanese PKI」と言うらしい.だれも気にしないと思って大きく出たな!
やってみよう NETCONF
知ったかぶりしない NETCONF に続く, NETCONF エントリーです.
今回はNETCONF の実装をいくつか試す.
前のエントリーでは「NETCONF 便利そうだけど, データモデル*1 が共通じゃないので使うのつらそう. 特にいろんな種類のものがある場合は」というようなことを書いた.
一方で「できる範囲でいいから物理ルーター/スイッチを自動管理したい」ニーズはあるので, 今回は「現状どんなことができるの?」を確認しようと思う.
たくさん試したわけではないので, 他に便利アプリがあるかもしれない.
オススメ情報があったらぜひ教えてください.
- 2014-11-04 追記
管理対象 (Netconf Server)
今回はJuniper Firefly Perimeter (junos-vsr-12.1X46-D-10-domestic) を使ってみる.
- NETCONF の設定は省略
- 詳しくはJuniper ドキュメント 参照
A Ruby gem for NETCONF
- https://github.com/Juniper/net-netconf
- BSD 2-Clause License
- Juniper Networks 製の NETCONF client ライブラリー
- NETCONF を使って設定を取得/変更する
- デバイス管理機能はない
- Ruby 向け
実装されている機能
NETCONF Standard RPCs
- get-config, edit-config
- lock, unlock
- validate, discard-changes
Flexible RPC mechanism
- Netconf::RPC::Builder to metaprogram RPCs
- Vendor extension framework for custom RPCs
( 引用: https://github.com/Juniper/net-netconf )
- RPC mechanism はモジュールによって抽象化されているが, 実装はJuniper 用のみ
使用例
インストール
$ gem install netconf
設定取得
password は環境変数に入ってるとして,
require 'net/netconf' Netconf::SSH.new(target: '192.168.0.74', username: 'codeout', password: ENV['PASSWORD']) do |device| config = device.rpc.get_config {|x| # 以下の <rpc> message を送信 x.configuration { x.system { x.services } } } # <rpc> # <get-config> # <source> # <running/> # </source> # <filter type="subtree"> # <configuration> # <system> # <services/> # </system> # </configuration> # </filter> # </get-config> # </rpc> puts config # 以下の設定が取得できる (Nokogiri::XML::Element オブジェクト) # <data> # <configuration xmlns="http://xml.juniper.net/xnm/1.1/xnm" junos:commit-seconds="1413833291" # junos:commit-localtime="2014-10-20 19:28:11 UTC" junos:commit-user="codeout"> # <system> # <services> # <ssh> # </ssh> # <netconf> # <ssh> # </ssh> # </netconf> # <web-management> # <http> # <interface>ge-0/0/0.0</interface> # </http> # </web-management> # </services> # </system> # </configuration> # </data> puts config.xpath('//services/netconf').to_xml # xpath を用いてフィルターできる # <netconf> # <ssh> # </ssh> # </netconf> end
使うには JUNOS 設定の構造を知っていなければならない.
状態取得
require 'net/netconf' Netconf::SSH.new(target: '192.168.0.74', username: 'codeout', password: ENV['PASSWORD']) do |device| puts device.rpc.get_firmware_information # 以下の <rpc> message を送信 # <rpc> # <get-firmware-information/> # </rpc> # 以下の状態が取得できる # <firmware-information xmlns="http://xml.juniper.net/junos/12.1X46/junos-chassis"> # <chassis junos:style="firmware"> # <chassis-module> # <name>FPC</name> # <firmware> # <type>O/S</type> # <firmware-version>Version 12.1X46-D10 by builder on 2013-12-05 15:05:41 UTC</firmware-version> # </firmware> # </chassis-module> # <chassis-module> # <name>FWDD</name> # <firmware> # <type>O/S</type> # <firmware-version>Version 12.1X46-D10 by builder on 2013-12-05 15:05:41 UTC</firmware-version> # </firmware> # </chassis-module> # </chassis> # </firmware-information> puts device.rpc.get_interface_information(interface_name: 'ge-0/0/0', terse: true) # 以下の <rpc> message を送信 # <rpc> # <get-interface-information> # <interface-name>ge-0/0/0</interface-name> # <terse/> # </get-interface-information> # </rpc> # 以下の状態が取得できる # <interface-information xmlns="http://xml.juniper.net/junos/12.1X46/junos-interface" junos:style="terse"> # <physical-interface> # <name> # ge-0/0/0 # </name> # <admin-status> # up # </admin-status> # <oper-status> # up # </oper-status> # <logical-interface> # <name> # ge-0/0/0.0 # </name> # <admin-status> # up # </admin-status> # <oper-status> # up # </oper-status> # <filter-information> # </filter-information> # <address-family> # <address-family-name> # inet # </address-family-name> # <interface-address> # <ifa-local junos:emit="emit"> # 192.168.0.74/24 # </ifa-local> # </interface-address> # </address-family> # </logical-interface> # </physical-interface> # </interface-information> end
- 動く
- パラメーターは, JUNOS XML API そのまま
出力は JUNOS 仕様のXML
method-missing
のしくみを使って 動的にXML を生成- JUNOS XML API に対応するメソッドがいちいち存在するわけではない
- ヘルパー的な便利動作は少ない
2014-11-04 追記
「show
コマンドが分かっていれば | display xml rpc
でXML を調べることができる」と教えてもらいました.
例:
> show chassis firmware | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1X46/junos"> <rpc> # <get-firmware-information> # ここを使う </get-firmware-information> # </rpc> # <cli> <banner></banner> </cli> </rpc-reply>
設定変更
require 'net/netconf' Netconf::SSH.new(target: '192.168.0.74', username: 'codeout', password: ENV['PASSWORD']) do |device| puts device.rpc.lock(:candidate) # 以下の <rpc> message を送信 # <rpc> # <lock> # <target> # <candidate/> # </target> # </lock> # </rpc> # 結果 # <ok/> puts device.rpc.edit_config {|x| # 以下の <rpc> message を送信 x.configuration { x.interfaces { x.interface { x.name 'ge-0/0/0' x.description 'foo' } } } } # <rpc> # <edit-config> # <target><candidate/></target> # <config><configuration><interfaces><interface><name>ge-0/0/0</name><description>foo</description></interface></interfaces></configuration></config> # </edit-config> # </rpc> # 結果 # <ok/> puts device.rpc.validate(:candidate) # 以下の <rpc> message を送信 # <rpc> # <validate> # <source> # <candidate/> # </source> # </validate> # </rpc> # 結果 # <commit-results> # </commit-results> puts device.rpc.commit # 以下の <rpc> message を送信 # <rpc> # <commit/> # </rpc> # 結果 # <ok/> puts device.rpc.unlock :candidate # 以下の <rpc> message を送信 # <rpc> # <unlock> # <target> # <candidate/> # </target> # </unlock> # </rpc> # 結果 # <ok/> end
- 動く
- パラメーターは, JUNOS 設定の構造をXML で表現したもの
- 変更対象を指定するためのキーを知っておく必要がある
- たとえば, <interface> を特定するためのキーは<name>
想像だけでXML を作るのは難しい. 戦略としては次のような感じになると思う.
- <get-config> して設定を取得
- キーを推測
- <get-xnm-information> しておけばXSD が手に入る -> 2. は不要
- 変更したい部分をXML で記述
結局, これは何?
NETCONF のwrapper
CLI をparse するより安全そう
Netopeer
- https://code.google.com/p/netopeer/
- New BSD License
- アーキテクチャー
の3つから成る. IAサーバーなどでnetopeer-agent + netopeer-server を常駐させ, netopeer-cli / gui からのSSHを終端する. その上でnetopeer-cli / gui (NETCONF クライアント) からnetopeer-server(NETCONF サーバー) 経由でIA サーバーを管理する.
( 引用: https://code.google.com/p/netopeer/ )
管理対象として 現時点ではLinux をターゲットにしているようだけれど「NETCONF に準拠していれば ルーターでもある程度動くんでは?」という淡い期待のもと, Netopeer-GUI を試してみた.
実装されている機能
- persistent connection to multiple NETCONF servers via backend process
- presentation of state and configuration information from datastores using YIN (/Yang) models
- creation of configuration with advisor of possible information in current context
- asynchronous NETCONF notifications using HTTP websockets
- calling model defined RPC methods
( 引用: https://code.google.com/p/netopeer/ )
- “persistant connection” をどうやって実現しているかというと, mod_netconf というapache module が常駐してSSH を終端
- GUI 本体はphp + symfony + DB
これが動いたらすごいですよね!
GitHub wiki を見てもらえると, ワクワク感が伝わるかもしれません.
使用例
インストール
Debian jessie にインストールした.
をソースからビルドする.
ビルド用スクリプトにパッチしたり, Firefly 向けにNETCONF capability の名前空間を変えたりする必要があったが, 今回のポイントではないので省略.
デバイスを登録
Firefly は, SSH ポート(22/tcp) もしくはNETCONF ポート(830/tcp) で登録できる.
きちんとcapability の交換ができている.
それ以上, ぜんぜん動かない…
データモデルに差があるとはいえ「初手では動かないだろうけど, 送るXML のテンプレート + XML を読むparser に手を入れたら動くだろう」くらいに思ってた… が, かなりつらい.
なにがつらいかというと, NETCONF の3+1 レイヤーのうち
Layer Example +-------------+ +-----------------+ +----------------+ (4) | Content | | Configuration | | Notification | | | | data | | data | +-------------+ +-----------------+ +----------------+ | | | YANG ---------------------------------------------------------------------------- | | | NETCONF +-------------+ +-----------------+ | (3) | Operations | | <edit-config> | | | | | | | +-------------+ +-----------------+ | | | | +-------------+ +-----------------+ +----------------+ (2) | Messages | | <rpc>, | | <notification> | | | | <rpc-reply> | | | +-------------+ +-----------------+ +----------------+ | | | +-------------+ +-----------------------------------------+ (1) | Secure | | SSH, TLS, BEEP/TLS, SOAP/HTTP/TLS, ... | | Transport | | | +-------------+ +-----------------------------------------+
Transport + Messages レイヤーはapache module, Operations + Content レイヤーはsymfony アプリとして実装されているが,
- XML parser のふるまいを変えるのに apache module とsymfony 両方の面倒をみる必要があって, 時には情報の橋渡しをしてあげないとダメだったり…
- NETCONF に使うXML 構造が, symfony 上でテンプレート化されていない…
予想どおりだけど, できたのは<hello> の交換までだった. 「デバイス種別+メーカーに応じてXML を出し分ける」とか 現時点では厳しそう.
まとめ
Juniper Firefly をコントロールするため, いくつかの実装を試してみた.
(ちなみにNETCONF WG のサイト から 他の実装も探せる)
上位レイヤー(Operations + Content) のモデル化が進んでいない現状では, 下位レイヤー(Transport + Messages) を薄くwrap するライブラリーを使うのが良いと思う. 上位レイヤーは, 自分たちが必要な範囲内で, 自分たちで抽象化する.
「なんだNETCONF 単体じゃあできないのか」というガッカリ感が先行するけれど, CLI を相手にするのも面倒だし.
リッチなアプリケーションはレールから外れたときに痛い目を見るし, ネットワークデバイス側は融通が効かない分 レールに乗せるための制約が大きすぎるとも感じた.
一方で, Netopeer のようなアプローチも “将来的には” 成功する可能性があると思っている. Netopeer 本来の使いかたであれば, netopeer-server が管理サーバー内で上位レイヤーの抽象化を担ってくれる. たとえば クライアント - サーバー間のAPI を厳密に規定する代わりに, サーバー内でnetopeer-server API を作ったほうがうまくいく場合もあると思う.
MBaaS のようにSDK を配ってAPI を呼んでもらうやりかたも一般的になってきたし, PyEZ みたいなやつで抽象化レイヤーを作れるかもしれない.
少しずつではあるが, NETCONF データのモデル化が進んできている ことにも注目したい. モデルが標準化されれば, 状況は変わってくると期待している.