Raspberry Piでパケットキャプチャできるようにする
自身の研究で、802.11acで規定されてるCSI(Channel State Information)を取得する必要があったのだけど、Raspberry Piでパケットキャプチャできるようにするまでの流れがかなりしんどかったので、まとめておきます。まとめるつもりが、まとめても大ボリュームなのでめちゃくちゃ暇と興味のある人向け。使用するのはNexmonという、Broadcom製のWifiチップ向けのファームウェアパッチです。
[!注意!]
この記事は内容の検証が十分ではありません。後日加筆修正を加える可能性がありますので、下記の作業は、作業者の責任において実行してください。特にWifiチップのファームウェアパッチを適用するという作業は、ハードウェアのサポートが受けられなくなる可能性がありますので注意してください。
必要なもの
- Raspberry Pi 3B+/4
- 重要なのはBroadcom製のBCM434355c0というWifiチップを積んでること
- Raspbianが動作しているものに限る、liteでもdesktopでも大丈夫
- SDの容量は8GBあれば十分っぽいけど余裕がある方が良い
手順
基本的にはNexmon公式のインストラクションに従いますが、一部記述のないパッケージを入れないと先に進まないところがあったので、その補足も書いておきます。「パケットキャプチャできるようにする」過程と「CSIを取得する」過程に分けて説明します。
パケットキャプチャの準備
無線をキャプチャするためには、デバイスのNIC(Network Interface Card)をモニターモードに変更しなければなりませんが、現状Raspberry Piにはモニターモードに移行させるオプションが実装されていません。そのため、以下の手順を踏んで、モニターモードに移行できるようにしていきます。
特に補足のないところはコマンドを上から順に実行すればOK。
sudo su
apt update && apt upgrade
apt install raspberrypi-kernel-headers git libgmp3-dev gawk qpdf bison flex make
-
apt install libtool-bin automake texinfo
1 git clone https://github.com/seemoo-lab/nexmon.git
-
cd nexmon
で5.でクローンしたディレクトリに入る -
cd buildtools/isl-0.10
,autoreconf -f -i
,./configure
,make
,make install
,ln -s /usr/local/lib/libisl.so /usr/lib/arm-linux-gnueabihf/libisl.so.10
を順に実行し2、親ディレクトリ/nexmon
に戻る -
cd buildtools/mpfr-3.1.4
,autoreconf -f -i
,./configure
,make
,make install
,ln -s /usr/local/lib/libmpfr.so /usr/lib/arm-linux-gnueabihf/libmpfr.so.4
を順に実行し3、親ディレクトリ/nexmon
に戻る -
source setup_env.sh
,make
を順に実行 -
cd patches/bcm43455c0/7_45_189/nexmon/
,make
,make backup-firmware
,make install-firmware
を順に実行4
ここまでうまくいっていれば、モニターモードのインターフェースを追加できるようになっているはず。sudo権限で
iw phy `iw dev wlan0 info | gawk '/wiphy/ {printf "phy" $2}'` interface add mon0 type monitor
と実行して、モニターモードのインターフェースmon0
が追加されていたら成功。
再起動後も動かすために
Nexmonは既存のファームウェアを上書きしてるわけじゃないので、このままだとラズパイを再起動すると元のWifiドライバが読み込まれて使えなくなってしまう。ので、以下の手順を踏んで、再起動後もNexmon経由にできるようにする。
-
modinfo brcmfmac
を実行し、冒頭のfilename:以降に記述されているパス(.../brcmfmac.ko
)をコピーする mv "<PATH>/brcmfmac.ko" "<PATH>/brcmfmac.ko.orig"
cp /home/pi/nexmon/patches/bcm43455c0/7_45_189/nexmon/brcmfmac_4.19.y-nexmon/brcmfmac.ko "<PATH>/"
depmod -a
ここまでできたら再起動して、上述のインターフェース追加のコマンドが動くかどうか確かめる。もしも再起動後にコマンドが通らなくなったら、「パケットキャプチャの準備」の2, 3, 4, 5を飛ばしてやり直せば戻せる。はず。
CSIの取得
ここからの説明におけるCSIは、厳密にはCompressed Beamforming Reportと呼ばれるバイナリで、例えば802.11n CSI Toolで取得できるような生のCSIとは異なるものです。いわゆるrawなCSIの取得方法については調査中。Compressed Beamforming Reportについて詳しく知りたい方は、IEEE公式のドキュメントを参照してください。
基本的にはtcpdumpやwiresharkなどを使って無線をキャプチャするだけ...なのですが、キャプチャ後の処理がかなり複雑なので、その処理についてまとめておきます。ちなみに後述の理由で環境によって得られる結果が違うので、サンプルコードなどを載せるのではなくキャプチャした中身の解析手順についてのみ書くことにします。
Compressed Beamforming Report
802.11acでは、MIMO通信におけるビーム形成のためにチャネルの情報をAPとSTAでやりとりしていて、これをBeamforming Reportと言います。MIMOのストリームごとに生の情報をやり取りするのはオーバーヘッドがかかるので、チャネルの情報を数学的処理5で圧縮して、いくつかの**「角度の情報」**に変換して送信しているようです。
今回はキャプチャした中身をWiresharkを使って取り出していきます。
ちなみに下の例では、aa:bb:cc:dd:ee:ff
というMACアドレスのデバイスからAPに向かってBeamforming Reportを送っている状況を想定します。
pcap → json
tcpdumpでもwiresharkでも、パケット時にその内容をpcapファイルに出力することができます。このpcapファイルを、jsonファイルに書き下します。絶対jsonに直さないといけないというわけではないと思いますが、後々の作業を簡単にする意味で変換しておきます。
手順は簡単で、例えばtest.pcap
というファイルをtest.json
に変換するにはターミナル等で
tshark -nr test.pcap -Y 'wlan.fc.type_subtype == 0x000e' -T json > test.json
を実行するだけです。ちなみにsubtype 0x000eというのは、Compressed Beamforming ReportやSNRの情報が入っているAction No Ackというフレームのサブタイプを指しているみたいです。
json → アンテナ数/Beamforming Report
前の段階で得たjsonを解析して、通信しているAPとデバイスのアンテナ数を取得し、角度情報のビット数を調べて、Beamforming Reportを取り出します。jsonの構造において必要な値がどのキーに含まれているかも書きますが、なんと**pcapからjsonへの変換を行った環境によって、jsonの構造が必ずしも同じじゃないことがあるみたいです(めんどくせぇ...)。**なので、以降で括弧書きしているところは自分の環境にどちらかが合うと信じて、どちらかで使ってください。
アンテナ数を確認するのは、アンテナ数の組み合わせによって、Beamforming Reportで送信される内容に変化があるからです。
上の表はIEEE公式のドキュメントから持ってきたものですが、$Nr$と$Nc$がデバイスのアンテナ数を表しています。表の通り、アンテナ数の組み合わせによって得られる角度情報の数量が変わってきます。
$Nc$はjsonの_source → layers → wlan_mgt (wlan_1) → Fixed parameters → wlan.vht.mimo_control.control_tree → wlan.vht.mimo_control.ncindex
に、$Nr$は_source → layers → wlan_mgt (wlan_1) → Fixed parameters → wlan.vht.mimo_control.control_tree → wlan.vht.mimo_control.nrindex
に値があります。
2020/03/29 : 続きを執筆中
-
公式の説明には書いてなかったけど、おそらく必須のパッケージ。 ↩
-
ここで
/usr/lib/arm-linux-gnueabihf/libisl.so.10
なるファイルの存在確認するよう書いてあるが、大抵存在しないのでいきなりこの手順を踏む。 ↩ -
脚注2に同じ。
/usr/lib/arm-linux-gnueabihf/libmpfr.so.4
というファイルの存在確認をするよう指示してるけど、こいつも大抵ない。 ↩ -
make系のコマンドが
Makefile:3: /firmwares/bcm43455c0/7_45_189/definitions.mk: No such file or directory
というエラーで動かない時がある。その時は、/nexmon
まで戻ってもう一回source setup_env.sh
すれば良い ↩ -
特異値分解とギブンス回転 ↩