なぜスマホの位置情報は狂うのか調べてみた

くまがいです。CROSS2016 ご来場ありがとうございました。大盛況で楽しかったですね。会場無線 LAN を CONBU で提供していましたので、繋がらない報告がないか Twitter を追っていたら、こんな投稿を見つけました。

WiFi繋いだら現在地が秋葉原になってる #cross2016

CROSS2016 は横浜ですので、位置情報がおかしいですね。

Wi-Fi測位のしくみ

スマホが現在位置を取得する方法のひとつとして、Wi-Fi の BSSID(MACアドレス) を利用したシステムがあります。端末は、周囲に見えている Wi-Fi の BSSID をサーバに送りつけます。するとその BSSID に対応した位置が返ってきます。

簡単な仕組みですが、これを世界中で実現させるには途方もない労力が必要です。位置とそれに対応する BSSID のデータベースを構築するには、測位したい全ての場所へ行って無線 LAN を受信する必要があり、今後も更新していかなければなりません。

スマホが Wi-Fi AP の位置情報を収集している

Skyhook Wireless(2010年頃以前の iOS での利用で有名)は、ウォードライビング、車で移動しながら無線 LAN を受信することによってデータベースを構築したといわれていますが、現在 Google や Apple は、この情報収集をスマホユーザ自身にやらせています。

たとえば iOS では、近くの Wi-Fi アクセスポイントの情報とその位置を端末に保存しておき、定期的に Apple へ送信しています。

Apple は Wi-Fi 測位に関する API や、誤った位置情報の修正、オプトアウトの手段などの情報を公開していません。iOS 8 および iOS 9 のプライバシーと位置情報サービスについて の「Wi-Fi と基地局の位置情報のクラウドソーシングデータベース」で何をやっているのか書かれていますが、これ以外の公式情報は見つけられませんでした。

本当のところ何を送ってるんだろう

ここまでは比較的広く知られていることかもしれません。が、具体的にどのような情報がやりとりされているのかはあまり知られていません。

試しに、手元の iPhone がどんな情報を送っているのか観察してみようと思います。使ったのは (iPhone5s, iOS8.2.1), (iPhone5, iOS9.2.1), Burp Suite 1.6.32 です。ちょっと古い理由は特になく、たまたま手元にあったからです。

観察・収集編

我々の iPhone で収集された Wi-Fi と位置データが Apple のサーバへ送信されていく様子です。
pbcwloc_270_01
おっ、何か MAC アドレスっぽいものを送っているのを見つけた!?

pbcwloc_270_02
うわー! バイナリかよ、解散~ と思いましたがこれは Protocol Buffers でシリアライズされた何かのようです。JSON や XML のような人間にやさしいエンコーディングではないため一瞬諦めそうになりました。

Protocol Buffers はバイナリエンコーディングのシリアライズフォーマットで、データ構造はエンコーディングに含まれません。データ構造は別途 IDL(インタフェース定義言語) の .proto で定義して使うもので、エンコードされたデータからはデータ構造がよくわからないのです。

ちょっと .proto をでっち上げてみました。中を見ても何だか分からない項目がいっぱいあります。いくつかは iOS7 か 8 で増えたようです。

message WiFiAccessPoint {
  required string bssid = 1;
  optional int32 channel = 2;
  optional int64 signal_dbm = 3;
    message Location {
      required double latitude = 1;
      required double longitude = 2;
      optional int32 unknown3 = 3;
      optional int32 unknown4 = 4;
      optional int32 unknown5 = 5;
      optional int32 unknown6 = 6;
      optional int32 unknown7 = 7;
      optional int32 unknown8 = 8;
      optional int64 unknown9 = 9;
      optional int64 unknown10 = 10;
      optional int32 unknown11 = 11;
      optional int32 unknown12 = 12;
    }
  optional Location location = 4;
  optional string application = 5;
  optional int32 unknown7 = 7;
}
message SmartphoneToAppleRequest {
  repeated WiFiAccessPoint ap = 3;
}

実をいうと、このメッセージは2013年頃(iOS6.0)に一度解析したことがあります。それを使って、今回のブログで気楽なネタにしようと思ったら、内容が丸ごと変わっていて全然気楽じゃありませんでした!!!

この .proto でデコードしてみたところ、以下のような内容を Apple へ送信しているようです。

ap {
  bssid: "74:3:bd:28:xx:xx"
  channel: 4
  signal_dbm: -89
  location {
    latitude: 35.6897295965
    longitude: 139.770113602
    unknown10: -1
    unknown11: 7
    unknown12: 0
  }
  application: "com.google.Maps"
  unknown7: 0
}

このケースでは、収集した約300個の BSSID が Apple へ送信されたのを観察できました。無線LANについては BSSID, チャネル、電波強度らしきものが送信されていて、SSID は送信されていないようです。_nomap は考慮されていないようで、ssid_nomap という SSID を出してみたところ普通に送信されていました。Apple に関しては _nomap は効いていないようです。

lat/lng の座標以外には、位置情報をリクエストしたであろうアプリの Bundle ID らしきものが入っています。自分の場合は他に com.protogeo.Moves や com.google.ingress などが入っていました。

その他に、端末の機種名と OS のバージョンも送っていますね。端末を個別に識別するようなものはなさそうです。HTTP ヘッダにも怪しいものはありません。認証もなく、匿名で突然送りつけているようです。

位置情報が狂う原因

AP を持ってオフィスの引越しをすると、引越し前の位置が表示されてしまうことがあります。オフィスに設置していた AP の BSSID に対応する位置情報が更新・収集されていないのが原因ですが、オフィスはともかく、最近は個人宅ではあまり聞かない現象のように思います。なぜオフィスの引越しでよく起こるのでしょうか?

オフィスには複数の AP があり、複数の BSSID が受信できるとします。すると、引越し以前から近隣にある AP よりそれらを優先して使われてしまうのかもしれません。また、都心のオフィスでは空が開けていない場所が多く、GPS の電波が受信しにくいため、BSSID と位置情報が更新されにくいのかもしれません。

更新に関しても、端末の識別もなく収集しているため、ある程度のデータが溜まって確信度が高くならないと有効にならないはずです。

収集されたデータがどのように運用されているのかは調べようがなく、曖昧な記述になってしまいましたが、きっと大きく外してはいないと思います。

観察・利用編

普通に現在位置を取得するパターンです。iOS で現在位置を取得するアプリ(ここでは Google Maps)を起動してみます。

clls_01_03
BSSID らしきものを送っていますね。これらの BSSID は確かに現在、周囲に見えているものです。

clls_02_03
位置情報が含まれたレスポンスが返ってきました。結構大きいようです。送った BSSID の他にも大量に何かがくっついています。例によってバイナリですが、これも Protocol Buffers ですので解析してみます。

でっちあげた .proto です。

message WiFiAccessPointResp {
  required string bssid = 1;
    message Location {
      required int64 latitude = 1;  // * 10e-9
      required int64 longitude = 2; // * 10e-9
      optional int32 unknown3 = 3;
      optional int32 unknown4 = 4;
      optional int32 unknown5 = 5;
      optional int32 unknown6 = 6;
      optional int32 unknown7 = 7;
      optional int32 unknown8 = 8;
      optional int32 unknown9 = 9;
      optional int32 unknown10 = 10;
      optional int32 unknown11 = 11;
      optional int32 unknown12 = 12;
    }
  optional Location location = 2;
  optional int32 channel = 21;
}

message AppleToSmartphoneRequest {
  optional int32 unknown1 = 1;
  optional WiFiAccessPointResp ap = 2;
  optional int32 unknown3 = 3;
  optional int32 unknwon4 = 4;
}

message AppleToSmartphoneResponse {
  repeated WiFiAccessPointResp ap = 2;
}

収集編での構造と同じかと思いきや微妙に違う………。lat/lng は float じゃなくて固定小数点に変わっているしタグもずれています。。これも 2013 年頃解析したものとは違います。

デコード結果は以下です。

ap {
  bssid: "10:6f:3f:6:xx:xx"
  location {
    latitude: 3565078352
    longitude: 13972113022
    unknown3: 42
    unknown4: 0
    unknown5: 21
    unknown6: 14
    unknown11: 62
    unknown12: 69
  }
  channel: 3
}

位置情報を取得するのに送信した周囲の BSSID の位置情報は、このようにして返ってきました。lat/lng 以外にも何かついてきているようです。

このケースでは、リクエスト時に BSSID を複数(12個)送信しています。レスポンスには、リクエスト時に送信した BSSID 以外にも周辺の BSSID と位置情報が100個ほど含まれていました。iOS, locationd がこのレスポンスから実際の位置情報をどのように計算しているかはわかりません。

BSSID から位置情報を取得したいならもっと簡単な方法がある

Apple のこれを使えば BSSID から位置情報を取得できる!と思うかもしれませんが、そんな面倒でグレーなことをしなくても、もっと簡単で正当な方法があります。

Google Maps Geolocation API で BSSID から位置情報を取得できます。
geolocation
ブラウザからも使われています。

プライバシーの問題

Wi-FiのMACアドレスはもはや住所と考えるしかない 高木浩光@自宅の日記 2011年11月26日

個人で設置している AP の MACアドレス(BSSID) から位置情報が引けるとなると、BSSID は住所に相当するのではないかという指摘があります。これに対し、Google Maps Geolocation API は「2つ以上のBSSIDが含まれないリクエストでは位置情報を取得できない」としています。

The request body’s wifiAccessPoints array must contain two or more WiFi access point objects. macAddress is required; all other fields are optional.

特定の BSSID から位置を調べようとした場合、その近隣の BSSID なんて事前に分からないので、位置情報が取得できません。これで多少は安全になります。一つの AP が複数の BSSID を吹いているなど、推測されやすい状況はありえますが。

結論

一般的に AP が設置されてもすぐに位置情報に反映されるわけではありませんが、カンファレンスやイベントなどで一時的に設置された AP でも、その情報がたくさんの来場者のスマホから送信されてしまい、それなりに確信度の高い位置情報として扱われてしまうのかもしれません。AP は複数台設置されるため、測位の場合でも優先されてしまうのかもしれません。

今回は Wi-Fi 測位のみを扱いましたが、その他 GPS(GNSS)や携帯電話基地局での測位とハイブリッドになっていることがほとんどであり、その挙動は多様です。大きく位置が狂うことが有り得るのは Wi-Fi 測位の特徴といえます。

他の測位手法については、他の機会に触れたいと思います。
それと Android も調べたかったのですが力尽きました。

YAPC::Asia Tokyo2015 の会場ネットワークをCONBUが構築しました

まだまだ新人ツチノコのkumaです。CONBUの一員として参加してまいりました。

Perl…に限らないエンジニア達の巨大な祭り YAPC::Asia 2015 が東京ビッグサイトで開催されました。CONBUは会場ネットワーク構築を担当しました。

同時接続数 約1,200,通算接続端末数 約3,600, UTP配線長約1.6km, アクセスポイント約36台。会場の広さもさることながら、各トラックの部屋がほぼ立ち見の満員御礼で、無線LAN環境としてはハードなものでした。さらにこれらを設営する時間はわずか90分弱、非常にハードでした。事前にAPと譜面台とUTPケーブルのキットを作っておき、よーいドンで一気に配備とケーブルの養生ができるようにチームを計画しました。

LT

動画を、音声ありでごらんください!

Day2のLTでCONBUの設営&撤収デモを行いました。LTが始まってCONBUの紹介後、号令とともに大勢のCONBUスタッフが舞台袖から一斉に出現、舞台上に無線APをライブ設営するという前代未聞のLTで、会場は一気に沸き上がり、一時 Twitter のトレンド入りも果たしたようです。

APIとヒートマップ

assoc-6f-7f
各アクセスポイントごとの接続端末数やトラフィックを眺めていると、来場者の動きがつかめます。たとえば、このグラフ(zabbix)は ある時間帯の 7F, 6F の接続端末数です。縦軸が接続端末数、横軸が時間です(色は各アクセスポイントごと)。最後のメインホールでのセッションが終わると、来場者はホールを出ますので 7F ロビーの接続数がいったん増え、さらに6Fへ移動していくのがわかります。東京ビッグサイト会議棟の構造は上から 7F → 6F → 長いエスカレータ → 2Fとなっていて、いったん6Fを経由するのです。

こういった数値をAPIとして提供し、自由に可視化できたら面白そうだと、つねづね思っていました。手が空いたら片手間に作ろうと思いつつ、毎度ネットワークの構築で手いっぱいになってしまっていたので、今回は片手間ではなくAPIチームを結成してちゃんと作りました。

会場ネットワーク情報取得API「CONBU-API]について

会場毎+AP毎に接続端末数を返すシンプルなAPIです。会場のどこにアクセスポイントが設置されているかを公開していますので 、その付近にどれくらいの端末が接続されているかを見ると、その付近におおよそどれくらいの人がいるのかわかります。

heatmap_sequence
ヒートマップとして可視化したものを、試しにアニメgif化してみました。Day1 の6Fのセッションがクローズし7Fの大きな会場へ来場者が集まっていき、やがて7Fもクローズし懇親会会場へ降りてゆく様子が見えます。

トラフィックもAPIとして提供できれば、Network WeatherMap のような可視化、あるいは、より高精度なヒートマップも実現できそうです。

カンファレンスネットワークの作り方

CONBUよりカンファレンスネットワークの作り方というトークをさせていただきました。CONBUの裏側、カンファレンスネットワークを作ってみたい方、API をいじってみたい方、ご参考にしていただければ幸いです。

トークの感想

実は… 個人的には、聞きたいと思っていたセッションのリストも事前になんとなく考えていたのですが、やはり当日はCONBUで手が空かず、無線状況の測定中に聞くのが精一杯でした。動画が上がるのを心待ちにしております!!

Blogに書くまでがYAPCです。YAPCは無事終了しました。次は 9/5 LL Ring Recursive だ!!

YAPC::Asia Tokyo2015 カンファレンス無線ホットステージ

去年のYAPC::Asia Tokyo2014 に引き続きまして 、明日より三日間 YAPC::Asia Tokyo 2015 が開催されます。なんと東京ビッグサイトでの開催です!
 YAPC::Asia Tokyo 2015 の会場で無線LANを提供する CONBU さんのホットステージの模様を一部お伝えします。ブロードバンドタワーさんのご好意により、会議室をお借りできました。

DMM.com ラボ は YAPC::Asia Tokyo 2015 へ協賛しています。
DMM.com ラボはカンファレンスネットワークを構築するチーム CONBU さんを応援しています。

でも今年は都合でDMMかき氷はありません。ごめんなさい!

ケーブル養生の秘密兵器、GAFFGUNを使ってみた!

こんにちは。寒さがぶり返してきて辛いですね。2月よりDMM.comラボにて働き始めたトウマツです。よろしくお願いいたします。拝承。

今回は、ケーブルを床に養生するための治具の紹介、そして使用感をレビューしたいと思います。

DMM.comラボでは、サーバやネットワーク機器の検証を行うために、LANケーブルや電源ケーブルなどを床に這わせることがあります。これらのケーブルを床に這わせる場合、足で引っ掛けてしまう事を防ぐためにケーブルをテープで床に止める(養生する)のが一般的です。
しかし長いケーブルの場合、長さに比例して養生する距離が長くなります。数十メートルの距離を養生するのは、まるで床を雑巾がけしているような感覚で、辛く地道でとても疲れる作業なのです。
そんな苦痛を伴う作業を「やってもいいかな!」と思えるような作業へと昇華させてくれる素晴らしい治具が発売されました。それがGAFFGUNです。

まずは、公式ページの動画を御覧ください。

この動画の通りであるなら、本当にすごい! イケてる! 試したい! そんな風に感動しているうちに、ついつい輸入してしまいました。

ちなみに、今回購入したのはコチラです。
The GaffGun Bundle

 

発送や通関に時間は掛かりましたが、無事到着。ていうかデカい!!

gaffgun1

 

丁寧にスポンジで梱包されており、好印象。本体は金属製です。(たぶんアルミのキャスト)

gaffgun2gaffgun3

 

さまざまなテープの幅に対応できるアタッチメント

gaffgun4

 

公式ページによれば、このGAFFGUNで使えるテープはメーカ純正品、または紙テープや布テープを推奨されています。ですが日本で発売はおろか、国際発送もしてもらえないメーカ純正テープは簡単に入手できませんし、コストも無視できません。また、紙テープや布テープは、接着剤が床やケーブルに残ってしまうので掃除が大変。やはり、慣れ親しんだ養生テープを使いたくなるわけで、ダメ元で使ってみました。

使用した養生テープの幅は50mmのどこでも入手できるものを、そしてGAFFGUNのアタッチメントはサイズSを使いました。

IMG_3860IMG_3861

 

使えるじゃん!

 

IMG_3839IMG_3836

つい、色んな所を養生したくなる!

 

というわけで、このケーブル養生治具”GAFFGUN”は日本でどこでも入手可能な養生テープを用いて、腰を痛めたり、床に這いつくばることなく簡単にケーブルを養生できることが確認出来ました。

そうそう、DMM.comラボはカンファレンスネットワークをサクッと構築するチーム”CONBUさんを応援しています。というわけで、CONBUさんに、GAFFGUNをお貸しして、どの程度の威力を発揮できるかを試して貰おうという思います。おそらく、YAPC::Asia Tokyo2015 あたりで大活躍されるのではないかなと、期待しております。

ついでと言ってはなんですが、本日は2015年2月18日、技術評論社のソフトウェアデザイン3月号の発売日となります。3月号の特集記事第一弾に、「カンファレンスネットワークのつくりかた」が掲載されました。実はこの記事の元ネタの一つであるYAPC::AsiaTokyo2014はDMM.comラボも協賛しており、同時にCONBUさんも応援いたしました。この記事にはCONBUさんの無線LANや、ネットワークに対する愛が詰まった内容です。ぜひご一読ください。