投稿日

ラズパイで作るWi-Fiアクセスポイントと、トラフィック計測 (NAPTパターン)

こんにちは、ソラコムの松下(ニックネーム: Max)です。

IoTはモノとクラウドをネットワークでつなげて、センサーやカメラ画像を用いて現場を共有したり、機器の制御をする技術です。昨今では、試験から本格利用へ進まれる方が多くなってきており、ネットワーク通信量(トラフィック)を把握しておきたい、というお話を伺います。トラフィックが見えてくると、以下が明確になります。

  • 本格利用時で必要となる、通信速度や帯域
  • ビジネス検討における、従量型ネットワーク利用時の見積もり

トラフィックはセンサーや機器の仕様を基に算出できますが、実際には暗号化やシステム連携時のオーバーヘッドも発生することから、実際のトラフィックと乖離する可能性があります。実運用に近づけるには実測が一番なのですが、センサーやカメラ側にトラフィック計測の仕組みが無い場合は実測できません。

そこで本ブログでは、IoTでもよく使われる小型コンピューター Raspberry Pi (通称: ラズパイ)を Wi-Fi のアクセスポイントにして、センサーやカメラからのトラフィックを中継しつつ、ラズパイ上でトラフィック計測ができる仕組みをご紹介します。

概要

ラズパイに「hostapd」と「dnsmasq」をインストールし、ラズパイの無線LANインターフェイス(wlan0)をWi-Fiアクセスポイントとして受けられるように構成します。インターネット側への通信は有線LAN(eth0)を使用します。

ラズパイへWi-Fi接続してきたデバイスへのIPアドレス配布(DHCP)には「dnsmasq」を利用し、ラズパイを通過した通信には「nftables」によるアドレス変換(NAPT)を行うことで通信をラズパイに集約します。そして「pmacct」を使い、無線LANインターフェイスを通過したトラフィックを計測していきます。

NAPTを利用することで、無線LAN側に多数のIoTデバイスが接続されても、有線LAN側に割り当てられたIPアドレス1つで通信できることから、既存環境への影響を最小限にできる利点があります。

アクセスポイントの構築には、NAPTパターンの他にブリッジパターンがあります。構築の手間はほぼ同じですが、構成の違いやそれぞれの利点については、ブリッジパターンをご覧ください。

Wi-Fiアクセスポイントの構築手順 (NAPTパターン)

実際に構築していきましょう。時間はおよそ30分程度です。

今回利用したのは Raspberry Pi 3 model B+です。無線LANと有線LANがついているモデルであれば利用できますが、3 もしくは 4 を推奨いたします。

1. Raspberry Pi Imagerでの書き込み時設定

Raspberry Pi OSを書き込むにはRaspberry Pi Imagerが一般的です。利用方法はこちらのブログをご覧ください。ここでは Raspberry Pi OS Lite (64-bit)を書き込みました。

書き込み時の設定は以下の通りです。

項目設定例備考
ホスト名hostapd-napt任意です。
SSH有効認証方法は任意です。公開鍵認証はSSHキーが必要です。
準備が整っていない場合はパスワード認証を選びます。
ユーザー名とパスワードユーザー名 = hostapd
パスワード = FooBar
任意です。特にパスワードは推測不能な文字列を指定してください。
パスワード生成ツールの利用も有効です。
Wi-Fi設定しない
ロケール設定タイムゾーン = Asia/Tokyo
キーボードレイアウト = us
任意ですが、設定しておくことをおススメします。

2. ラズパイの有線LANからインターネット接続を確認する

ラズパイの有線LANポート(eth0)にケーブルを挿し、インターネットに接続できるようにしてください。また、ここからの作業はSSHによるリモートアクセスでも可能です。

3. 初回起動後のOS最新化

Raspberry Pi OS が起動したら、まずインストールソフトウェア・ライブラリの最新化を行います。再起動して最新化は完了です。

sudo apt update && sudo apt upgrade -y
sudo systemctl reboot

4. dhcpcdによるwpa_supplicant起動の無効化と、wlan0への固定IP割り当て

wpa_supplicantは、Wi-Fiアクセスポイントに接続する際の認証(WPA)を通すためのソフトウェアです。今回は、ラズパイ自体がWi-Fiアクセスポイントになることから、このソフトウェアが動作していると競合を起こすため停止します。また同時に、無線LANインターフェイス(wlan0)に固定のIPアドレスを割り当てます。

wlan0 には 10.0.2.254 というアドレスを使用しました。基本的にはこのままでも問題ありませんが、eth0側のネットワークと競合する場合は変更してください。

# variables
_MY_WLAN0_IP_=10.0.2.254
# main
sudo systemctl stop wpa_supplicant.service
sudo systemctl mask wpa_supplicant.service
cat << _EOT_ | sudo tee -a /etc/dhcpcd.conf
interface wlan0
static ip_address=${_MY_WLAN0_IP_}/24
nohook wpa_supplicant
_EOT_
sudo systemctl restart dhcpcd.service

確認

以下のコマンドで、先の設定が完了しているか確認します。

sudo systemctl status wpa_supplicant.service | grep Active:
#=>     Active: inactive (dead) since Sun 2022-05-08 15:28:16 JST; 2min 47s ago
ps h -C wpa_supplicant
#=> <何も表示されないのが正解>

5. hostapdによるWi-Fiアクセスポイント化

hostapdは、Wi-Fiアクセスポイントサーバーソフトウェアです。このソフトウェアによって、ラズパイの無線LANインターフェイスをWi-Fiアクセスポイントとして動かすことができます。

ここでは SSID = TESTWLAN0 、パスワード = Aihei2oB と設定しています。これらは変更して利用してください。

# variables
_SSID_=TESTWLAN0
_WPA_KEY_=Aihei2oB
# main
sudo apt install -y hostapd
sudo systemctl unmask hostapd.service
cat << _EOT_ | sudo SYSTEMD_EDITOR=tee systemctl edit hostapd.service
# Ref: /lib/systemd/system/raspberrypi-net-mods.service
[Service]
ExecStartPre = /bin/sh -c '/bin/rm -f /var/lib/systemd/rfkill/*.mmc*wlan'
ExecStartPre = /usr/sbin/rfkill unblock wifi
_EOT_
cat << _EOT_ | sudo tee /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=${_SSID_}
hw_mode=g
channel=11
macaddr_acl=0
ignore_broadcast_ssid=0
auth_algs=1
ieee80211n=1
wme_enabled=1
country_code=JP
wpa=2
wpa_passphrase=${_WPA_KEY_}
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
wpa_group_rekey=86400
_EOT_
sudo chmod 600 /etc/hostapd/hostapd.conf
history -d -8 # erase "_WPA_KEY_" in history
sudo systemctl start hostapd

確認

以下のコマンドで、先の設定が完了しているか確認します。

sudo systemctl status hostapd | grep Active:
#=>     Active: active (running) since Sun 2022-05-08 12:39:54 JST; 11min ago

6. dnsmasqによるDHCPサーバー

dnsmasqは軽量DNS/DHCPサーバーソフトウェアです。今回はDHCP機能を利用することで、Wi-Fiアクセスポイントへ接続してきたデバイスへのIPアドレス割り当てを行います。

配布するIPアドレスの範囲は 10.0.2.100 ~ 10.0.2.109 の10個のアドレスとしています。また、DNSサーバーは、それぞれGoogleとCloudflareが運営するパブリックDNSサーバーのアドレスを配布するようにしています。アドレス数、DNSサーバー共にこのままでも問題ないと思いますが、IPアドレス数が必要だったり、組織で利用すべきDNSサーバーアドレスがあれば変更してください。

# variables
_MY_WLAN0_IP_=10.0.2.254
_LEASE_RANGE_="10.0.2.100, 10.0.2.109"
_DNS_SERVERS_="8.8.8.8, 1.1.1.1"
# main
sudo apt install -y dnsmasq
cat << _EOT_ | sudo tee /etc/dnsmasq.d/wlan0.conf
interface = wlan0
dhcp-range = ${_LEASE_RANGE_}, 255.255.255.0, 24h
dhcp-option = option:router, ${_MY_WLAN0_IP_}
dhcp-option = option:dns-server, ${_DNS_SERVERS_}
listen-address = 127.0.0.1
log-queries
log-dhcp
_EOT_
sudo systemctl restart dnsmasq

確認

以下のコマンドで、先の設定が完了しているか確認します。

sudo systemctl status dnsmasq | grep Active:
#=>     Active: active (running) since Sun 2022-05-08 12:39:55 JST; 11min ago

7. nftablesによるNAPTゲートウェイ化

nftablesはIPパケットフィルタミドルウェアで、iptables等を統合したものです。今回はwlan0とeth0間の通信に対してアドレス変換(NAPT)を適用するのに利用します。また、wlan0とeth0間で通信ができるように net.ipv4.ip_forward を有効化もしています。

# main
cat << _EOT_ | sudo tee -a /etc/nftables.conf
# Ref: https://wiki.archlinux.jp/index.php/Nftables#.E3.83.9E.E3.82.B9.E3.82.AB.E3.83.AC.E3.83.BC.E3.83.89
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname "eth0" masquerade;
  }
}
_EOT_
sudo systemctl restart nftables.service
cat << _EOT_ | sudo tee /etc/sysctl.d/10-ipforward.conf
net.ipv4.ip_forward = 1
_EOT_
sudo systemctl restart systemd-sysctl

確認

以下のコマンドで、先の設定が完了しているか確認します。

sudo nft list ruleset | grep "table ip nat"
#=> table ip nat {
sudo sysctl net.ipv4.conf.all.forwarding
#=> net.ipv4.conf.all.forwarding = 1

8. ラズパイで構築したWi-Fiアクセスポイントに接続してみる

以上でラズパイをWi-Fiアクセスポイントとして構築できました。スマートフォンやパソコンから、ラズパイで構築したWi-Fiアクセスポイントに接続してみましょう。

接続できたら https://ifconfig.io といったツールサイトが表示できるかを確認してみましょう。

pmacctによるトラフィック計測

pmacctはトラフィック計測ソフトウェアです。例えば以下のようにすると、Wi-Fiアクセスポイントとして構成されている wlan0 インターフェイスを通過したトラフィック(通信量)を計測できます。

sudo apt install -y pmacct
sudo pmacctd -P print -r 10 -i wlan0 -c src_host,dst_host,dst_port

10秒毎に、以下のように画面へ出力されることでしょう。

SRC_IP                                         DST_IP                                         DST_PORT  PACKETS               BYTES
10.0.2.100                                     1.1.1.1                                        853       21                    1894
10.0.2.100                                     8.8.8.8                                        853       10                    936
1.1.1.1                                        10.0.2.100                                     57240     9                     3774
8.8.8.8                                        10.0.2.100                                     38332     9                     5897
10.0.2.100                                     216.58.220.131                                 80        5                     495
216.58.220.131                                 10.0.2.100                                     56830     5                     370
10.0.2.100                                     142.251.42.132                                 443       9                     1362
142.251.42.132                                 10.0.2.100                                     41126     8                     1485

10.0.2.100(= 確認時に利用したスマートフォン)から、DNSサーバーとして設定した 1.1.1.1 や 8.8.8.8 へ通信している様子、そしてその時の通信量がPACKETSやBYTESとして計測されています。これを利用することで、通信量の把握が可能となるわけです。

ここでは単純に画面に表示するようにしましたが、pmacctはSQLiteといったDB保存もサポートしています。詳細はトラフィック計測ツール “pmacct” の結果をSQLiteに保存するをご覧ください。

今後の運用 ~ ラズパイの安定的な運用を目指して

ラズパイをWi-Fiアクセスポイント化できましたが、こういったものは検証時にのみサクっと動かしたいものです。そこで、ラズパイを安定的に動かす1つの方法として「電源ON/OFFだけで動く仕組み」も検討してみてください。詳細はRaspberry Pi OSのrootfs ROM 化をご覧ください。

セルラー通信のトラフィック確認なら「SORACOM Peek」

ここではWi-Fiデバイスのトラフィックをラズパイ上で計測する方法を紹介しました。
IoTにおいては、Wi-Fi以外にもLTEや5Gといったセルラー通信も利用されます。その場合は、SORACOMプラットフォーム上でIPパケットをキャプチャできる「SORACOM Peek(ピーク)」をご利用ください。

SORACOM PeekはSIM(=通信回線)単位、もしくはVPG(=ネットワーク)単位でキャプチャができ、そのフォーマットはpcap形式であるため、Wiresharkといった標準的なパケットアナライザで解析できます。

詳細はオンデマンドパケットキャプチャ「SORACOM Peek」をご覧ください。

おわりに

IoTの本格利用に向けては、通信量の見積もりが不可欠です。特に昨今ではカメラの利用によって、通信量が増える傾向にあります。一度は計測しておき、必要となる通信速度や帯域を確認しておくことで、安定的なIoTシステム構築ができるのではないでしょうか。

費用も安く抑えつつ構築できますので、是非ご活用ください!

― ソラコム松下 (Max / @ma2shita)

参考資料:

ちょっと裏話

Raspberry Pi OSのベースとなっているDebian/GNU Linuxが刷新されたことで、今回の件を通じていろいろと発見がありました。
まずIPパケットフィルタです。古くからiptablesが利用されてきており、今回も当然のようにiptablesを使おうと思いきや、なんと標準状態でインストールされていませんでした。調べてみるとiptablesを置き換えるツールとしてnftablesが入っていたんです。

また、wpa_supplicantの停止にも一手間かかりました。Raspberry Pi OSを含むLinux OSのほとんどが、プロセス管理にsystemdを利用しているのは多くの方が知るところです。その定義ファイルであるUnitファイルを探してみても、wpa_supplicantに関してはwpa_supplicant.service以外に見つからず、この定義をstopやmask(無効化)しても、wpa_supplicantがなぜか起動するという現象に悩まされました。
結果は dhcpcd が管理している /lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicant が起因だったのですが、これの発見には、ログの確認コマンドである journalctl が役立ちました。クラッシックな手法だと dmesg や /var/log/**.log を見るのもありなんですが、同コマンドならトータルで見ることができるため、すぐに発見できたというものです。

ツールや環境は常にアップデートされており、その目的は利便性や速度向上だったりするわけですので、知識をアップデートして、生産性向上につなげたいものです!