2011年09月の日記です

メールアドレス隠蔽の戦略  2011-09-05 15:18:44  COMP

後日追記


この日記に書いた内容、バージョンアップして詳細を別ページに書きました。



WEB でメールアドレスを公開しながら、スパム用のメールアドレス収集ボットには見つかりたくない。
でも、ボットではなく人間に対しては、できるだけ使いやすくしておきたい。

…非常にわがままな要求です。
誰でも使えるように公開しておいたら、ボットにも公開されるのは当然のこと。
でも、現実問題として「ボットに見つからないようにしながら、使いやすく公開したい」需要はあるのです。


というわけで、仕事上のクライアントから相談を受けました。
いままで、自分の(この)WEBサイトでは、画像でアドレスを公開していましたが、これだけでは要求を満たせないのは事実。

で、研究して作ってみました。



「たぶん」スパム収集ロボットには収集できない。
でも、人間の使い勝手は「わりと」よい。
(範囲選択してコピー、ができないのが残念)


以下のフォームで、javascript 部分を生成できます。
表示されているメールアドレス部分は画像なので、そこは自分で作ってください (^^;
(あとに作り方の参考を書きますので、読んでね)




---

以下、技術話。

メールアドレス収集ボットは、HTML ファイルを取得して、その中から「メールアドレスらしい部分」を探し出し、収集します。

HTML ファイルの中から、なので、そのままのテキストではなく html エンティティにすればよいとか、mailto: リンクを url エンコードすればよいとか、javascript でリンクタグを生成すればよいとか、外部ファイルにメールアドレスを入れて link タグで読み込ませればよいとか言われるけど、それはダメ。

だって、いまどきブラウザもオープンソースの時代だから。
ブラウザがページを最初に開いたときに、エンティティを解釈したり、url エンコードを解釈したり、javascript を実行したり、外部ファイルを読み込んだりするところまでやらせて、出来上がった「表示直前の」データを取得すれば、メールアドレスはばれてしまう。


Javascript でリンクタグを生成するのではダメ、というのは、こちらのページで実験することができます。


残る方法は二つです。

1) 画像で表示する。

クリックしてもメーラーは開かないし、コピーもできない。
メールが欲しいからメールアドレス公開しているのに、メールしようと思っても「長いアドレスを手で間違えずに入力しないといけない」という、事実上メールを送ることを拒否した状態になってしまう。

2) メールを送ろうとした瞬間に、Javascript でアドレスを生成する。

これなら「表示直前のデータ」にもアドレスが入りません。
でも、それは「表示できない」ことを意味します。
メーラー起動しない場合、メールアドレスが存在していることを教えられません。
もちろん、Javascript が実行されない環境の人にもメールアドレスを教えられません。

1 は、メールアドレスは教えられるがメーラーに渡すことができない。
2 は、メーラー起動はできるが、メールアドレスを人間に見せられない。

というわけで、2つの方法は綺麗に補完関係にあります。
なので、組み合わせれば問題なし! …といいたいところだけど。

---

OCR の噂。

いまどき、OCR ソフトもオープンソースで存在します。
メールアドレスを画像化しても、OCR してアドレス収集するボットがいる、と言う噂もあります。

でも、これは OCR の癖を知っていれば対処可能。
人間にも読みにくい画像にしてしまえば、OCR はまず読めない。

いや、そこまでしないでも、「人間には読めるのに OCR はできない」画像を作るのは難しくない。

今作るメールアドレス画像は、「クリックすればメーラーが起動する」ことを教えるためのもの。
ならば、普通のリンク部分と同じように、アンダーバーをつけてはどうでしょう?

これだけで、文字の区切りが不明瞭になり、OCR には非常に読みづらくなります。
フォントも、読みづらくない範囲でデザイン性が高いものを使うと、なお OCR されにくいでしょう。

作り方は、別に特別なソフトはいりません。
WEB でメールアドレス公開したい、と悩んでいる人なら、HTML くらいは書けるはずだし、簡単な画像加工ツールくらい持っているでしょう。

なので、メールアドレスをリンク状態にしたタグを書いて、ローカルでブラウザに表示させます。
font タグで face="~" を使えば、フォントも変えられます。
どうせアルファベットなので、フリーのフォントは山ほど配布されています。

あとは 画面キャプチャして、適当に切り出せば終了。
出来上がったら、本当に OCR できないのか確認しましょう。

WeOCR Projectといものがあり、WEB ブラウザから画像をアップロードすると、OCR 結果を返してくれるサーバーがたくさん集められています。
検索すると、サーバーのアドレスとともに、どのような OCR エンジンを使用しているかも教えてくれます。
複数のエンジンで読み込ませてもうまく認識できない「メールアドレス画像」であれば、ボットに収集される可能性は低いと考えてよいかと思います。


WEB 上にも、メールアドレスの画像化をしてくれるサービスがいくつかあります。

でざいんめーる
きゃっとまーくめーる
E-Mail Icon Generator
E-Mail Icon Generator (有名ドメイン専用)

---

最初に設置した Javascript のタグ生成器が生成するタグの説明。

img タグ1つ。ただそれだけです。

src 部分には # と書いてありますが、これをご自分のメールアドレス画像の url に変えてください。

style 指定は、この画像上でマウスカーソルを「クリック可能」を意味するものに変えるように指示しています。これで、一見普通のリンク文字と変わらないように見えます。

で、クリックすると onClick に書かれた Javascript が起動し、暗号化(簡単なシーザー暗号ですが)されたメールアドレスを復号して、メーラーを起動します。

暗号化された文字の「エスケープ」は考慮していません (^^;;
メールアドレスに $ 9 ; | } ~ などが入っていたりすると、ちょっと困ったことになるかもしれません。
(暗号化された文字が、特別な意味を持つものに変わるため)

---

大切なのは、この方法が「それほど有名にならないこと」。
有名になるとボット作成者に対処されますからね。

自分がボット作者なら、明らかにメールアドレスを隠蔽している部分のタグを見つけ出して、そこの Javascript だけ実行させてみます。
そういう意味では、「img に付いた onClick で、最後が location.href に代入しているもの」は明らかに怪しい。


なので、別案も示しておきます。

・img タグに直接 onClick を指定するのではなく、周囲に別のタグをつける。
 a タグで href に mailto: だけ指定すると、Javascript を使えない/使わない環境の人でも、とりあえずメーラー起動してくれます。
 (この場合、onClick の最後に ;return!1 をつけること。そうしないと、href が優先的に動作します)

・もちろん、a タグではなく form でも 、div でも span でも font でも、どんなタグでもよい。onClick が付けばなんでも。

・onClick が怪しまれるかもしれないので、onMouseDown でも onMouseUp でもよい。
 (厳密に言えば、クリックとは「ボタンが離されたとき」に完了するので、onMouseUp のほうが違和感は少ないです。)

・location.href=d するのではなく、clipboardData.setData("Text",d) する。
 こうすると、メーラーを開くのではなく、アドレスをクリップボードにコピーします。
 (ただし IE 限定)

・onClick などのイベント属性と Javascript プログラムがセットになっていると、「メーラーを起動している可能性が高い」などと判断しやすいかもしれません。
 なので、プログラムを関数にして、別の箇所に置く。これだけでもボットを出し抜ける可能性はあります。
 (もっとも、対応付けは難しくないので、自分がボットを作る立場なら検査させるかも知れません)



Javascript プログラムは近年多用されている傾向にありますし、場合によってはゲームなどが動作してしまうため、ボット作成側も「何でもかんでも動作させてみる」というわけにも行かないでしょう。
なので、ある程度の「きめうち」が予期されます。

対策する側としては、きめ打ちされない程度に方法が分散し、撹乱できればよいわけです。



同じことは、表示画像に使用するフォントに対してもいえます。
皆が同じフォントを使っていれば、すぐに対処されちゃう。

この日記の冒頭に示した画像では、Monotype Corsiva フォントを使用しています。
(日記執筆時…画像は後で変えるかもしれない)

このフォントは、読みにくくない程度に装飾が施され、なかなか OCR しにくいように思います。

Windows 標準フォントで言えば、Mv BoliとかSegoe printとか、結構いいかもしれません。
MacOS 標準フォントだと、Apple Chanceryあたりかな?

究極は、自分の手書きを画像化することか…
でも、OCR できないことを目指しすぎて、人にもわかりにくくなっちゃだめ。微妙なところです。

この記事単体へ


名前 内容

節電終了  2011-09-26 16:20:26  COMP MYHOME
電力使用制限令自体は、9月9日に終了している。

が、我が家としては政府の節電サイトの景品欲しさに、もう少し節電していた。

それも、電力使用量のお知らせが着たから終了。9月は35%の節電だった。
これで、サランラップがもらえる。かもしれない。

---

節電を終了したからどうするか、と言ったところで、別に無駄に電気を使おうとは思わない。
もともと、我が家では節電を心がけてはいたのだ。

…3ヶ月で、27%、38%、35% も節電できていて「心がけていた」も無いものだが、本当だ。
湯沸しポットは3年以上使っていないし、電気掃除機も年に1~2度しか使わない。

今回の節電は、仕事で必要なサーバーを停止して、2台使用しているのを仮想化して1台にまとめた効果が大きい。
24時間運用していたのを、2台から1台に半減させたのだからね。

でも、これによって2台でお互いにバックアップを取り合う体制も停止していた。
仕事で使っているのに、バックアップが無いのは、本来はダメなのだ。
この点、「無理して節電していた」ので、節電終了で早期に復旧。


あと、7年前の PC を買い換えたのも大きいと思う。
こちらは、節電終了してもそのままなので、今後も家計費節約になるでしょう。

でも、以前は PC のバックアップも、夜中に自動的にとっていたのだよね。
これも復活させないといけないけど、新マシンにバックアップソフトを入れたりといった体制作りはまだできていない。

こちらはそのうち設定する予定。
バックアップは壊れてからでは遅いので、こまめにとらなくては。

この記事単体へ


名前 内容

Location ヘッダと 302 ステータス  2011-09-28 15:09:28  COMP
仕事で、とあるサイトに接続する必要があった。

一般的なサイトではなく、仕事上の機密情報を扱うサイトだ。

サイト管理者から渡された「証明書」をインストールしていないとアクセスできないし、セキュリティを固めるために、いろいろな細工が施してある。

ActiveX を使用しているので、IE でしかアクセスできない。


必要だからアクセスしたいのに、なぜか Windows7 + IE9 でアクセスできない。
証明書の確認までは行くのだが、その後「Internet Explorer ではこのページは表示できません」となる。

とりあえず、非常用のノートPC で XP + IE8 でアクセスできたが、いろいろと不便。

---

Windows7 + Chrome で試すと、アクセスできる。
もっとも、アクセス後 ActiveX が使えないので何もできない。

しかし、証明書のインストールに失敗しているわけではなさそうだ、ということは確認できる。

IETester を入れてみて、IE7 でアクセスしたがやっぱりダメ。

FireFox + IETab2 、というのも試してみたが、これは単に IE9 を Tab 内で開いているだけなので当然ダメ。


いったい、何が原因で動かないのか。
とりあえずアクセスできる chrome と、IE9 の違いはどこにあるのか。


chrome で Javaコンソールを開き、アクセスして、ネットとのやり取りしたデータを覗く。
IE9 で開発者ツールを開き、アクセスして、ネットとのやり取りしたデータを覗く。

…比較して、違いに気がついた。

chrome では、認証フォームの内容を POST すると、HTTP ステータス 302 が帰ってきてリダイレクトして、次のアクセスは GET になっている。
IE9 では、同様にリダイレクトして、次のアクセスは POST 、しかも「中断」と表示されて実際のアクセスが行われていない。

何でこんなことになるんだ? と、HTTP の仕様を確認してみる


もし 302 ステータスコードが GET や HEAD 以外のリクエストのレスポンスとして受信されたら、リクエストが発行された時点の条件から変わっているかもしれないため、ユーザエージェントはユーザに確認されなければ、リクエストを自動的にリダイレクトしてはならない



…POST アクセスから、302 でリダイレクトしちゃいけないんだ。恥ずかしながら、知らなかった。
しかも、


注: RFC 1945 や RFC 2068 では、クライアントはリダイレクトするリクエストのメソッドを変えてはならないと明確に述べられている。


POST でアクセスされたのに、リダイレクトで GET に変えちゃいけないんだ。これも恥ずかしながら、知らなかった。


参考までに、僕は恥ずかしながら知らなかったが、2006ごろからこの手問題を指摘している人はいたようだ。
古くて新しい問題なんだな。



というわけで、わかったのは、「サイトのつくりが悪い」ということ。
アクセスできないのが当然の作り方をしているのだ。

IE9 が悪いのではなかった。濡れ衣だ。ごめんよ。
IETester も、「見た目」を確認するためのツールなので、HTTP アクセスは OS 標準(今回は IE9)のプログラムを使用しているのだろう。


とはいっても、現実問題として 302 のときは GET に切り替えてアクセス、というブラウザがほとんどで、正しく仕様に従ったのは IE9 が初めて、ともいえる。


実のところ、302 でなく、303 を返せばいいらしい。
この場合は、GET でリダイレクトされなくてはならない、と決まっているから。

ただし、ブラウザが HTTP 1.1 を理解できないと、303 は使えない。
…いまどき、1.0 のブラウザなんて無いでしょ?

---

翻って、自分の仕事の話。

PHP で作っているプログラムで、Location なんてしょっちゅう送っている。

そして、PHP では Location を送出すると、暗黙のうちにステータスコード 302 を返す。

…これ、問題あるね。PHP の仕様がバグっている、ということだ。
もっとも、ステータスコードは指定できるので、直前が POST のときは、明示的に 303 にしなくては。

ただし、303 と 302 は意味が違うので、単に POST アクセスからリダイレクトしたい、と言う理由で使うのは間違い。
ちゃんと意味を理解して使わないと。

HTTP 1.1 が前提であれば、307 というのもある。
こちらだと、POST アクセスの次は、POST で返してくれるそうである。
ただし、この場合も「自動的にリダイレクトしてはならない」という、302 と同じ制約は付く。


この記事単体へ


名前 内容


戻る
トップページへ

Loading