Mackerelで家庭内ネットストーカーシステムを作ってみた

本エントリはMackerel Advent Calendar 2017の23日目の記事です。


自宅の無線LANの利用状況をMackerelで監視するようにしたところ、予想以上にキモい仕組みができました。たとえば、家族の誰か(正確には誰かのスマートフォン)が外出するとSlackに通知を飛ばすことができます。



同じことをしている人は多くないと思うので、その知見を紹介します。

システム概要

まずは我が家のネットワーク構成を紹介します。



インターネットに接続しているブロードバンドルータがあり、無線経由でスマートフォンやPCがぶら下がっているような、ごく普通のネットワーク構成です。唯一変わっている点は、ブロードバンドルータ上でLinuxおよびMackerelエージェントが動いていることでしょう。


このルータの詳細は本稿では省きますが*1、ザックリ言うとRaspberry Pi 3を無線LANアクセスポイント兼ブロードバンドルータとして運用している環境が一番イメージしやすいと思います。

iwコマンドの出力をMackerelで監視する

Linux無線LANアクセスポイントとして動かす場合、無線LANの利用状況がiwコマンドで確認できます。下記は私のブロードバンドルータ上での出力です*2

# iw dev wlan1 station dump
Station 00:00:5e:f0:07:87 (on wlan1)
        inactive time:  1600 ms
        rx bytes:       6216368
        rx packets:     50296
        tx bytes:       4006367
        tx packets:     30159
        tx retries:     1159
        tx failed:      2
        rx drop misc:   17
        signal:         -50 [-49, -57] dBm
        signal avg:     -50 [-49, -56] dBm
        tx bitrate:     243.0 MBit/s MCS 14 40MHz
        rx bitrate:     216.0 MBit/s MCS 13 40MHz
        expected throughput:    53.557Mbps
        authorized:     yes
        authenticated:  yes
        associated:     yes
        preamble:       long
        WMM/WME:        yes
        MFP:            no
        TDLS peer:      no
        DTIM period:    2
        beacon interval:100
        short slot time:yes
        connected time: 195122 seconds


このように、iw dev station dumpで現時点でアクティブなWi-Fiクライアントのネットワーク利用状況が取得できます。同じネットワークに5台のクライアントがぶら下がっている状態であれば同様の内容が5台分それぞれ表示されます。


今回、上記の情報を記録するMackerelプラグイン hnw/mackerel-plugin-iw を作成してみました。


以下、mackerel-plugin-iwによって得られる情報を紹介します。

Wi-Fiセッションの生死がわかる

iwコマンドでは接続中の端末のMACアドレスごとの通信状況が表示されます。つまり、MACアドレスごとのエントリの有無を1分に1回記録することで、どの端末が現在ネットワークに参加しているかがわかります。


これをグラフ化することで、自宅でいつPCを開いていたかがわかるようになりました。PCを開いている時間は常にWi-Fiセッションが維持されるので、セッションが切断されたということはPCをスリープさせたということになります。


また、特定のスマートフォンを持った人が外出したかどうかの判断にも利用できます。というのも、大半のスマートフォン端末は画面オフ時もWi-Fiセッションが切れません*3。つまり、スマートフォンWi-Fiセッションが切れたときは外出したと判断できるのです。


次のグラフは筆者がMacBookを閉じ、iPhoneを持って外出したときのものです。両者のWi-Fiセッションが同時間帯に切れていることから、9時頃に家を出たことがわかります。



ちなみに、mackerel-plugin-iwでは利便性向上のためにMACアドレスの前3桁からわかるベンダー名をラベルの先頭に追加しています*4。こうしておけばMACアドレスだけ表示するより端末の判別が容易ですし、万一見慣れない端末がネットワークに参加していればすぐに気づくことができます。

端末ごとのネットワーク転送量がわかる

iwコマンドでは送受信した累積バイト数がわかるので、これを1分ごとに記録することでネットワーク転送量をグラフ化することができます。これにより、各端末でどんな操作をしているか想像することができます。


たとえばYouTubeで動画を見ている場合には転送量のグラフは横ばいになりますが、Webページを閲覧している場合には凸凹が多いグラフになります。


他にもアプリケーションによっては特徴的なグラフになることがあります。下記のグラフは私がNintendo Switchスプラトゥーン2ナワバリバトルを6回遊んだときのものです。ナワバリバトルは同じ部屋にプレイヤーが集まるのを待ち、8人揃ったら3分間の通信対戦を行うまでが1セットになっています。実際、グラフを見ると約3分間一定量の通信を行って1分ほど通信が落ち着くという繰り返しになっているのがわかります。


電波強度から端末と親機の距離が推定できる

無線LANの電波強度は-30dBから-100dBといった値で表されます。この数字は小さくなればなるほど電波強度が弱く、親機と子機の距離が離れている可能性が高いという意味になります。


電波は人体やその他でも遮蔽されるのでそこまで正確な位置検出はできませんが、Wi-Fiルータと同じ部屋にあるか別の部屋なのか、くらいは判断ができそうです。


下記のグラフは私がWi-Fi親機のある部屋でスマートフォンを操作していて、電池残量が減ってきたので隣室でUSB充電をはじめたときのものです。両者は直線距離ではそれほど変わらないのですが、隣室まで壁を挟んでいるせいか約-40dB*5から約-60dBと電波強度が大きく減衰していることがわかります。


仕組みのキモさと対策

これまで紹介してきた情報は、同じ無線LANにぶら下がっている全端末についてグラフ化されています。自分の端末の情報を自分が把握できるだけであれば何の問題もないのですが、同じ無線LANネットワークを利用している家族の情報も取れてしまうわけですから、非常にキモい状態だといえるでしょう。本稿の最初で例示したように、家族の誰かが外出するたびに管理者に通知が飛ぶような設定もできるわけで、家族間であってもプライバシー侵害のような問題になりかねないような気もします。


一方で、このような仕組みを作れるのは我々自身が情報をまき散らしているからこそです。これらの情報が家族内でさえ知られて困るのであれば、ネットワークを分離したり常時4G回線を使ったりといった対策が必要になるでしょう。

まとめ

iwコマンドの出力をMackerelで監視することで、端末ごとの詳細なネットワーク利用状況の可視化が実現できました。また、状態変化に対してアラートを流せるようになりました。


この仕組みは自宅で利用していると非常にキモいのですが、たとえば会社所有スマートフォン端末の管理・棚卸しに使うなど、実用的な利用方法もありそうだと考えていますので、もう少しブラッシュアップしていきたいと考えています。

*1:詳細に興味がある方は「BHR-4GRVにLEDEをインストールしたメモ」をご覧下さい。

*2:MACアドレスは加工してあります

*3:一部のAndroid端末にはスリープ中にWi-Fiセッションを維持させない設定があるようですが、全iOS端末および大半のAndroid端末ではスリープ中もWi-Fiセッションが維持されるようです。また、両OSとも省電力モードのときはWi-Fiセッションの接続・切断を繰り返すようです

*4:hnw/wsoui というライブラリを自作しました

*5:現在のMackerelの仕様ではマイナスの値をグラフ化できないため正負反転して記録しています