まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2013/11

先日の、不正請求と思われる Google Wallet での決済に関する続報です。
過去のエントリはこちらこちら

Google Wallet チームからメールが届きました。内容は「銀行やカードの会社から chargeback(返金)してもらえ」というもの。つまり不正利用された分が請求されることが確定したらしいとのこと。 実際にカード会社のオンライン明細を確認すると確かに記録されていました。ふーん・・・「Google 側に問題はなかったのか?」と、なんとなく釈然としない所もあったけど、とりあえずはカード会社に電話連絡、と。

今回の不正請求で自分が購入したことになっている、と明細に記録されていたのは "Clash of Clans" などのゲームを制作・販売している SuperCell というゲーム会社の製品でした。1つ謎だったのはどこかにいる犯人は何を狙っていたのか、ということです。仮に情報をハックできていたとしても、僕のクレジットカードを使って購入したら商品は僕の元に届くわけで、それで一体何の狙いがあったのか謎でした。なお以前のブログエントリで僕が購入したことになっている商品が "Gems" だと記載しましたが、これもゲームの名前だったことがわかっています。

とりあえずカード会社経由で請求分をキャンセルするか、あるいは返金するような手続きを取っていただけることになりました。が、その会話の中で分かったのですが、「この SuperCell という会社からの不正請求報告が最近増えている」のだそうです。それは聞き捨てならんな・・・

というわけで「Google Supercell 請求」あたりでググってみると・・・、確かに同様の Supercell 絡みの被害報告がたくさん見つかります。全て Google Play 絡み、ということはカードの情報そのものが流出したというよりも、Google のアカウントがハックされたと考えるべき??

また犯人の狙いも少し分かった気がします。この Clash of Clans というゲームはいわゆる「アイテム課金」型のゲームで、リアルマネーを払うことでゲームを有利にすすめるためのアイテムが購入できます。つまり僕のカードを使って購入したものは物理的なアイテムではなく、ネットゲーム内で使える課金アイテムの購入に充てられた可能性があります。それなら住所が僕のものになっていても(犯人は既にアイテムを入手しているでしょうから)不思議ではありません。ちょっと納得できた気がします。

と、日本でも多く報告されている類似事例や、Google Play で扱っているゲームの課金アイテムの購入に充てられた可能性を考えた場合、やはりクレジットカード情報が流出したというよりは、Google アカウントがハックされたか、Google アカウントが流出し、そこから Google Play にログインして、Google アカウントに紐付けられたクレジットカードを使って、課金アイテムなど配達不要のものを購入した、という可能性を考える方が筋も通って現実的な気がしています。

一応念のため今のクレジットカードは解約して新しいカードを発行して、Google アカウントに紐づくクレジットカード情報も新しいものに更新すれば大丈夫かな・・・と思っていたのですが、よく考えたら何が怖いって、もし上記の推測が正しく Google アカウントそのものがハックされている場合(または流出していた場合)、アカウントに新しく発行したクレジットカードを紐付けても、その直後からすぐに使われてしまう可能性がある、ということです。 これを自力で予防するにはアカウントにカードを紐付けないようにするしかないんですが、でも AppEngine とか各種 API とか、有料か無料かはともかくクレジットカードを登録しないと使えない Google サービスもあったりするので、そこがまた悩ましいというか・・・

とりあえず Google アカウントのパスワードはより複雑なものに更新しておきました。単純ですが、アカウントがハックされていたのだとしたら、これも有効な対策になりえるので。


 

前回のエントリの続きです。
日本語では対応してもらえなさそうだったので英語で攻めてみました。英語が苦手な人の役に立てばと、自分の場合の対処手順を紹介します:

なんとなくですが今回の対応が正解っぽかったです。Google Wallet のヘルプページから「問題のトラブルシューティング」 - 「払い戻しと覚えのない請求」を選択。「オンライン購入」をクリックしてから、ステップ4の「こちら」と書かれたリンクをクリック。すると「お客様の言語ではサポートを提供していない」と書かれたページに移動します。意を決して "English" をクリック。

gw01

するとこんな英語の払い戻しフォームが表示されるので内容を埋めていきます。英語が苦手な人のために簡単な意訳を赤字で併記しておきます:

gw02


名前と苗字、メールアドレスは問題ないとします。問題の取引のあった日、時刻、額、決済相手、そしてオーダー番号は Google からの取引を知らせるメールに記載されているので、その内容を入力します。日は日本式の YYYY/MM/DD フォーマットではなく MM/DD/YYYY フォーマットで指定します。

キャンセルの理由欄では近い理由を選択しますが、「身に覚えのない取引」だとしたら一番上の "I don' recognize this charge" を選択します。またその下の説明欄にはその他の補足(私の場合はその前に行った 日本の Google Play チームとの咬み合わないやり取りの内容を記述しました)を入力します。また添付ファイルには該当の取引が表示されている Google Wallet 画面のスクリーンショットを取って添付しました。最後にチェックを入れて "Submit" ボタンで送信、以上です。

今回は担当外ではなかったらしく(苦笑)、数時間後に英語でメールが送られてきました。自分が受け取った内容では「まだ詳しく調査している」との内容で、まだどうなるか分からないのですが、そんな「調査中」であるという事実を知らせてもらうまでに3日を要してしまいました。

でもとりあえずこちらの意図が伝わったことは確認できたと思います、「担当外です」って言われるよりは数倍安心。


自分のタイムラインでも他の知り合いに同様の不正利用請求があったらしく、もしかすると大規模なトラブルがあったのかもしれません。将来も含めてそんな人の参考になれば。


 
 

先日、Google から立て続けにメールが届きました。

タイトルは全て同じで "Your Google Play Order Receipt from Nov 22, 2013" というもの、内容も似ているけどほぼ同じで、僕が11月22日に Google Play から購入した商品の確認メールでした。いや何も買ってないけど。。

Google Wallet の様子はこんな感じ。11月22日に6つの商品を購入したことになっています。この画面では詳細は分からないのですが、この6回の購入が4分の間に立て続けに行われていました。
gwallet

この件で Google に問い合わせた所、最初の1件は「今回のみ例外措置でキャンセルする」と連絡がありました(何で上から目線なのか分からないけど・・・)。 また最後の2つはおそらく Google の判断で(もしかしたらこの時点でおかしいと気付いていた?)トランザクションがキャンセル扱いになっていました。が、残る3つの購入は今も有効になっています。

ちなみに僕が買ったことになっている商品は "gems" 、つまり「宝石」。いらねーっての。 (^^;

困ったことに Google は Google Wallet に関して(少なくとも日本には)窓口がない模様。電話対応はそもそもなく、届いたメールからリンクをたどり、問い合わせフォームからメールを送ったところ Google Play チームに対応してもらうことになったらしいのですが、「担当外です」とか言われる始末。いや、俺だって担当外の人に頼んだ覚えはないよ(苦笑)。

カード会社にも問い合わせしました。カード購入の問い合わせ記録そのものは残っている模様。ただこの購入による請求額が確定していれば、それをキャンセルするかどうかを判断できるが、今の段階では請求額が確定していないのでカード会社では取れる措置がない、とのことでした。ちなみに購入元が「Google です」と伝えたところ、「電話で問い合わせできなくて、メールフォームで問い合わせを繰り返してもらうしかない」とやけに詳しく言われたので、過去にも同じようなことがあったのかも・・・と推測。
なお、今回のこの件以外に身に覚えのない取引はカード会社にも記録されていないようでした。

改めて Google の(担当外の)人に連絡して、何度かのやりとりの結論はこの通りでした:
 「身に覚えのない請求につきましては、下記リンク先でのみ対応させていただいております」(原文まま)
 https://support.google.com/googleplay/answer/2851610?hl=ja

まあとりあえずは担当外での対応ありがとうございました、と。

ただ上のリンクをたどると分かるのですが、結局「Google ウォレットチームに請求について報告」するしかなく、そのリンク先では請求書の詳細項目を記入して(おそらく)払い戻ししてもらうことになるのかな、と思ってます。要はやはり今の段階で何かできるわけではなく、請求額が確定したら教えろ、と。


普通に考えると Google Wallet ないしは Google アカウントに不正アクセスがあって情報が取られた、と考えるべきだよね。で、今の時点では何も打つ手がない、と。。


今回の件があったから言うわけではないけど、Goggle Wallet の問い合わせが日本でできない(しても担当外のチームが対応する)のはちょっと問題なんじゃないかなあ、と感じてます。以前に、その時は不正利用とかではなく、単に Google Wallet から請求された内容について確認したかった時にもなかなか話が伝わらずに苦労した記憶があるので。


さて次の手はどうしよう? 英語で問い合わせすればいいのか? ちと試してみよ。







KVM をはじめとするハイパーバイザーの魅力は、OS環境が必要になった場合、テンプレート的な環境を元にすぐ用意できる、ということ。いわゆる LAMP 環境が必要になったら、LAMP 導入済みの仮想環境があれば、それを複製して新しいLAMPの仮想マシンを作れる、というイメージです。

が、KVM でこれをやろうとすると結構ひっかかるポイントがあります。具体的な環境にも依存するのですが、自分の場合は KVM のゲストOSにはDHCPを適用していました。これが後々大きな問題になりうるとは・・・ 試行錯誤を繰り返してなんとか形になったので、ここにまとめておきます。


そもそもどこでつまづくのか?

おさらいですが、仮想マシンを複製して新しい仮想マシンを作って利用する、ということは以下のような流れになります:
(1) 複製元の仮想ゲスト環境から、新しい仮想ゲスト環境を複製する
(2) 複製後の仮想環境の IP  アドレスを確認する
(3) 複製後の仮想環境にリモートアクセスして利用する

※ (1) のコマンドは、例えば複製元の KVM ドメイン名が guest1、複製先が guest2、複製先のイメージファイルを /var/lib/libvirt/images/guest2.img に指定するとしたら以下のようになります:
# virt-clone --original guest1 --name guest2 --file /var/lib/libvirt/images/guest2.img

この流れの中でつまづく可能性があるのは2点です:

まず自分の環境では DHCP でゲスト環境の IP アドレスを動的に割り振っています。なので (1) で複製したゲスト環境の IP アドレスを事前に想定することができないので、起動してもどうやって (3) のリモートアクセスしていいのか分からないのです。

そのためには (2) の手順が必要になります。具体的には KVM の virsh コマンドを使って親ホストから子ゲストにコンソールログインして IP  アドレスを確認することになります。この手順も含めて紹介しますが、裏を返せば (2) が可能になるように (1) の複製元仮想ゲスト環境を設定しておくことが必要になる、ということです。

※ KVM ホストが RUNLEVEL = 5 の GUI 環境で運用されている場合は、virt-manager の画面から直接目的の仮想環境のコンソールを開いてログインすることも可能ですが、RUNLEVEL = 3 の CUI 環境で運用しているケースを想定し、また最終的にはシェルスクリプト1つで複製からネットワーク設定の変更まで一発で変更できるような処理にしたいので、コンソールログインができるような環境を整えておくことをおすすめします。

もう一点の問題は (1) を普通にコマンドを実行して行っただけでは複製後のマシンのネットワークインターフェースが有効にならない(ループバックインターフェースのみが有効な状態で起動する)、ということです。複製元の環境がDHCPで、MACアドレスを持ってDHCPサーバーに問い合わせた結果のIPアドレスを割り振られています。この辺りは OS インストール前後の設定項目なのであまり意識して設定していない人もいると思いますが、具体的な内容は /etc/sysconfig/network-script/ifcfg-eth0 などに記載されています。

そして KVM の複製コマンドではこれらの情報ごと複製されることになります。つまり複製元の MAC アドレスが書かれた設定ファイルが、異なる MAC アドレスを持つ環境下にコピーされてしまうことになり、このファイルではDHCP サーバーから IP アドレスを正しく 取得することができないのでした。加えて複製元環境にホスト名が設定されていた場合は /etc/hosts や /etc/sysconfig/network なども複製元の情報を保持したままコピーされることになるので、これらのファイルもそのままでは正しくない、ということになります。これらを解決するには複製直後のネットワーク環境に対していくつかの変更が必要になるのでした。


KVM のゲスト Linux 環境にコンソールログインするための設定

こちらは以前のブログエントリで触れておきました。複製元のゲストOS環境にこちらで紹介した設定をして、コンソールログインが可能な状態にしておいてください。


KVM の Linux 環境のネットワーク関連設定ファイル

まずは複製後に変更の必要がある(可能性のある)ファイル4つと、その変更内容を羅列します:

・ /etc/hosts

複製前の環境にホスト名(例えば xxx.host.com)を設定していると、/etc/hosts にこのような記述がされているはずです。
 127.0.0.1  xxx.host.com localhost localhost.localdomain ...

で、この内容が複製先にもそのまま反映されることになります。それで問題ないケースと問題になるケースがあると思うのですが、問題になるケースでは複製先での変更が必要です。

・ /etc/sysconfig/network

上記の /etc/hosts と同じ理由です。/etc/sysconfig/network にはホスト名が記述されています。
 NETWORKING=yes
 HOSTNAME=xxx.host.com

この内容がそのまま複製先に反映されて影響があるケースでは複製先での変更が必要になります。

・ /etc/sysconfig/network-scripts/ifcfg-eth0

この作業の肝になる部分です。/etc/sysconfig/network-scripts/ifcfg-eth0 にはネットワークインターフェースの設定が記述されており、このファイルに関しては複製元の情報をそのまま使うことはできません

具体的には以下のような変更が必要です:
- 固定 IP アドレスで運用する場合は複製先には異なる IP アドレスを指定する
- DHCP で運用する場合は複製元の MAC アドレス情報を複製先のものに書き換える
- 更に UUID については複製元の情報を複製先で使うわけにはいかないため、新たに用意する

(DHCP の例)
DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="XX:XX:XX:XX:XX:XX"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
UUID="nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
  : 

・ /etc/udev/rules.d/70-persistent-net.rules

このファイルにも MAC アドレスが記述されているので、複製先では複製先の MAC アドレスに必ず書き換える必要があります

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="XX:XX:XX:XX:XX:XX", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"


KVM のゲスト Linux 環境のネットワーク関連設定ファイルの変更

なお、以下の説明では guest1 というドメイン名の KVM ゲストから guest2 というドメイン名の KVM ゲストを複製したものとして説明を続けます。guest2 には guest1 のネットワーク設定情報が残っているので変更する必要がある、という状況を想定しています。


まずは KVM のホストからゲスト環境のファイルシステムにアクセスするために、KVM ホストに libguestfs パッケージを導入します:

# yum install libguestfs libguestfs-tools libguestfs-tools-c

libguestfs パッケージが KVM ホストに導入されると KVM ホストから KVM ゲストのファイルシステムに直接アクセスすることが可能になります。なお、その際は目的の KVM ゲストはシャットダウン状態にしておきます。


例えば KVM ゲスト : guest2 の特定のファイル(例 /etc/hosts)を表示するには、KVM ホストから以下のコマンドを実行します。 -d でゲスト環境のドメインを指定します:

# virt-cat -d guest2 /etc/hosts

127.0.0.1  xxx.host.com localhost localhost.localdomain ...

ファイルを編集するには virt-edit コマンドを実行します。パラメータは同じです:

# virt-edit -d guest2 /etc/hosts

/etc/hosts に変更の必要がある場合は適宜変更して保存します。再度 virt-cat コマンドで変更後の内容を確認します。

# virt-cat -d guest2 /etc/hosts

127.0.0.1  yyy.host.com localhost localhost.localdomain ...
(ホスト名を xxx.host.com から yyy.host.com に変更した場合)


ホスト名の変更が必要な場合は 同様にして /etc/sysconfig/network ファイルも編集します:

# virt-edit -d guest2 /etc/sysconfig/network

# virt-cat -d guest2 /etc/sysconfig/network

NETWORKING=yes
HOSTNAME=yyy.host.com
(ホスト名を xxx.host.com から yyy.host.com に変更した場合)


次に複製先の /etc/sysconfig/network-scripts/ifcfg-eth0 ファイルを編集しますが、その前に複製先環境の MAC アドレスを確認します:

# virsh domiflist guest2

Interface Type Source Model MAC
-------------------------------------------------------
- bridge br0 virtio 'YY:YY:YY:YY:YY:YY'
(YY:YY:YY:YY:YY:YY 部分が guest2 の MAC アドレスです)

また複製先用の UUID も uuidgen コマンドで事前に用意しておきます:

# uuidgen

mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm
(8桁-4桁-4桁-4桁-12桁の文字列が guest2 用の新しい UUID です)

guest2 の MAC アドレスと UUID が決まったので、この内容を guest2 の /etc/sysconfig/network-scripts/ifcfg-eth0 を編集して反映させます:

# virt-edit -d guest2 /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="dhcp"
HWADDR="YY:YY:YY:YY:YY:YY"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
UUID="mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm"
  : 


最後に複製先の /etc/udev/rules.d/70-persistent-net.rules ファイルを編集して、複製先環境の MAC アドレスを指定して保存します:
 
# virt-edit -d guest2 /etc/udev/rules.d/70-persistent-net.rules
 
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="YY:YY:YY:YY:YY:YY", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"


これで複製先で変更が必要なネットワーク設定は以上です。これらの変更後に guest2 を起動するとネットワークが有効な状態で立ち上がります:

# virsh start guest2

# virsh list
(guest2 が「実行中」として表示されるようになるまで待つ)


上記「KVM のゲスト Linux 環境にコンソールログインするための設定」が複製元(guest1)で済んでいれば、複製先である guest2 にもその内容が複製されているので guest2 にコンソールログインできるはずです。KVM のコンソールログインについてはこちらのエントリも参考にしてください:

# virsh console guest2


コンソールログインした先で ifconfig コマンドを実行して、guest2 に DHCP で割り当てられた IP アドレスを確認します。eth0 にアドレスが付与されていれば成功!

# ifconfig

eth0   Link encap:Ethernet  HWaddr YY:YY:YY:YY:YY:YY
           inet addr:ZZZ.ZZZ.ZZZ.ZZZ  Bcast:ZZZ.ZZZ.ZZZ.255  Mask:255.255.255.0
             :
(ZZZ.ZZZ.ZZZ.ZZZ 部分が guest2 のIPアドレスです)


なお、コンソールログインから抜けるには CTRL+] を押します:


これで KVM の複製コマンドで複製した仮想マシンでもネットワークが有効になりました。IP アドレスまで確認できているので、後は KVM ホスト経由でなくても普通に ssh などでリモートアクセスすることもできるようになりました。


とりあえず一連の作業としてはこんな感じですが、色々面倒なので自分の環境用に一部をシェルスクリプト化しました。具体的には以下の条件下で使えるつもりです:
・KVM ホストのシェルから実行する前提
・KVM ゲストの複製元も複製先も DHCP 設定
・KVM ゲストイメージはデフォルト設定のまま /var/lib/libvirt/images/ に存在している
・KVM ゲストイメージのドメイン名が XXX のイメージファイルは /var/lib/libvirt/images/XXX.img とする 
・複製先の /etc/hosts, /etc/sysconfig/network は書き換えない
・複製先のMACアドレスを自動取得&UUIDを自動生成して /etc/sysconfig/network-scripts/ifcfg-eth0 と /etc/udev/rules.d/70-persistent-net.rules を書き換える
・複製先の起動は行わない

そのシェルスクリプトはこちらです: clone-guest.sh

この内容についてはこちらの記事を参考にしています:
http://lab.adn-mobasia.net/?p=471


使い方は KVM ホストにコピーして、実行権限付与後に以下のように実行します:

# ./clone-guest.sh guest1 guest2
(guest1 が複製元ドメイン名、guest2 が複製先ドメイン名、guest1 にはコンソールログインの設定が済んでいて、かつ停止中であること)

すると /var/lib/libvirt/images/guest1.img を元に /var/lib/libvirt/images/guest2.img が複製され、そのネットワーク定義ファイルが上記の条件で自動的に書き換えられて、でいつでも起動できる、という状態で生成されます。もし起動まで自動で行いたいのであれば clone-guest.sh の最後に以下の一行を追加すればできると思います:

$cmd_virsh start $clone_domain_name


このサンプルでは /etc/hosts や /etc/sysconfig/network の変更は(しなくても起動まではするはずなので)行っていませんが、絶対に必要になるような環境では中身を参考にしながら変えられると思うので挑戦してみてください。

またこのサンプルはあくまで DHCP 環境を前提にしています。固定 IP にも対応するようなのは、ちょっと面倒な気もしますが、どなたか挑戦してみてください。
 
ともあれ、いろいろ手入力しないといけない状況と比べると格段に簡単になりました。仮想環境が理想に近づきました。 

KVM の virsh console コマンドを使って、(極端な話、ネットワークが有効になっていなくても)ホストOSからゲストOSにコンソールログインすることができる、ことになっています。

が、何も考えずに virsh console (ドメイン名) を実行すると 

ドメイン XXXX に接続しました

エスケープ文字は ^] です

と表示され、ここで Enter キーを押すとログインプロンプトが表示される・・・はずなのですが、なぜか固まってしまいます。 

どうもゲストOS側でコンソールログインをするための設定が必要な模様。結論としては次の2点:

(1) /etc/grub.conf にカーネルオプションを追加設定

kernel /vmlinuz-2.6.18-238.el6 ro root=/dev/***   console=tty0 console=ttyS0,115200n8
(kernel で始まる行の最後に赤字部分を追加、kernel で始まる行が複数ある場合は全てに設定)

(2) /etc/inittab にコンソールモードの設定を追加

S0:12345:respawn:/sbin/agetty ttyS0 115200
(赤字の一行を追加)


これで再起動後に、改めてホストOSから virsh console XXXX でコンソールログインが可能になります。

なお、コンソールから抜けるには CTRL+] です。


ゲストOSが
 ・別のゲストOSを元に複製で作成して、
 ・DHCPでIPアドレス設定するようになっていて、
 ・かつGUIが使えない(virt-manager から参照できない)
ようなケースでは、起動直後のIPアドレスを確認するための手段が「コンソールログインして ifconfig」しかないので、この方法が必要になるのでした。



このページのトップヘ