Raspberry Piをheadlessで接続するWi-Fiを切り替える


概要

最近ラズパイを触り始めました。
なかなかドンピシャの情報が出てこなかったのでメモしておきます。

この記事では、スマホ・PCでWi-Fiを切り替えるような操作を、SSH接続したターミナルから行う方法を紹介します。
最終的に下のGIFのような感じで切り替えできるようになります(以下)。

  1. PC、ラズパイとも602HWa-527CF0(10.0.0.0/24)に接続した状態でSSH
  2. ラズパイでarrowsRX_8018(192.168.43.0/24)に接続
  3. SSHが途切れるのでPCでも同じWi-Fiに接続して再度SSH
  4. ラズパイで602HWa-527CF0に接続しなおす
  5. 最初のSSHが復帰

こんな環境を最初からheadlessで構築していきます!
(実際は手間取って画面つないでごちゃごちゃやってしまいましたが…)

使用機器

  • Raspberry Pi 3 B+
  • Wi-Fi
    • 602HW(Pocket WiFi)
    • arrows RX(楽天モバイル)

SDカード作成 〜 初回起動・ssh接続

ここらへんは多くの情報があるので、参考ドキュメントと合わせてさらっと。

  1. OSイメージを書き込む。
  2. ssh接続を有効にするため、空のsshファイルをbootパーティションに配置。
  3. 初回起動時に自動でWi-Fi接続させるため、SSIDとPSKを記述したwpa_supplicant.confファイルをbootパーティションに配置。

  4. ラズパイ起動、3で設定したネットワーク内でのIPアドレスを探してSSH接続する。

    • IP Address - Raspberry Pi Documentation
    • ⇑で紹介されてる方法以外にip neigh | grep -i 'B8:27:EB'でもいける。B8:27:EBはRaspberry Pi FoundationのOUI。
    • ルーターによってはLAN内の端末同士で通信するために設定が必要。今回使用しているPocket WiFiでは「プライバシーセパレーター」をオフにする。

NetworkManager 設定

無事ssh接続できたら早速NetworkManagerのインストール・設定を行います。

sudo apt update
sudo apt upgrade -y
sudo apt install -y network-manager

この段階ではdhcpcdが動いているので、まだネットワークデバイスがNetworkManagerの管理下にありません。(下のunavailable)

$ nmcli d
DEVICE  TYPE      STATE        CONNECTION 
eth0    ethernet  unavailable  --         
wlan0   wifi      unavailable  --         
lo      loopback  unmanaged    --   

Do not enable the systemd units shipped with the dhclient and dhcpcd packages.
NetworkManager - ArchWiki

続いてconnectionを追加します。今回はメインWi-FiとサブWi-Fiを切り替えようという趣旨なので、メインWi-Fiの優先度を高くします。

  • メイン
sudo nmcli con add ifname wlan0 type wifi \
con-name pokefi \
ssid 602HWa-527CF0 \
wifi-sec.key-mgmt wpa-psk \
wifi-sec.psk yourpassword \
connection.autoconnect-priority 100 \
ipv4.method manual \
ipv4.gateway 10.0.0.1 \
ipv4.addresses 10.0.0.10/24
  • サブ
sudo nmcli con add ifname wlan0 type wifi \
con-name rakuten \
ssid arrowsRX_8018 \
wifi-sec.key-mgmt wpa-psk \
wifi-sec.psk yourpassword \
ipv4.method manual \
ipv4.gateway 192.168.43.199 \
ipv4.addresses 192.168.43.10/24

オプションやプロパティはman page や以下参照。
NetworkManager Reference Manual: NetworkManager Reference Manual
いくつかピックアップすると、

  • 802-11-wireless-securityの代わりにwifi-secの短縮形が利用可能

nmcli also accepts wifi-sec and wifi strings instead of 802-11-wireless-security.
nmcli: NetworkManager Reference Manual

  • wifi-sec.pskwpa_supplicant.confファイルと同様、生のパスワードでもwpa_passphraseコマンドで生成した文字列でも可
  • connection.autoconnect-priorityで優先度を指定。デフォルトは0。

これで設定完了なので、最後にdhcpcdを無効化して再起動します。

sudo systemctl disable dhcpcd
sudo reboot

現在のSSHは切断されるので、メインWi-Fiのconnectionで指定したIPアドレス(今回は10.0.0.10)で接続できたら成功です。

$ nmcli d
DEVICE  TYPE      STATE        CONNECTION 
wlan0   wifi      connected    pokefi     
eth0    ethernet  unavailable  --         
lo      loopback  unmanaged    --         
$ nmcli c
NAME                UUID                                  TYPE      DEVICE 
pokefi              ae7b29bc-4d0f-4ee2-8bd7-b329eafd40d2  wifi      wlan0  
rakuten             e72eed56-4eb7-4557-a150-9cb15f423992  wifi      --     
Wired connection 1  5c64ba5e-9947-3472-9567-99ed0168eb8e  ethernet  -- 

お疲れ様でした。

Android端末テザリングのDHCPについて

  1. Wi-Fiテザリングでは192.168.43.0 / 24となる(変更不可)
  2. gatewayのIPアドレスは最近のバージョンでランダムになったらしい(変更不可)

上記2.については、テザリングをオンオフすると変わってしまいます。
今回サブWi-Fiとして使うarrowsRXは常に給電しつつテザリングオンの状態なのでそうそう変わらないとは思いますが、ちょっと懸念は残る設定になってしまいました。(いつの間にかgatewayが変わったことに気づかず、「なぜか繋がらない!?」となりそう…)

余談ですが、上述のサブWi-Fiの設定でipv4.gatewayを除いて設定してみました。するとcurlコマンドでURLを指定すると通信するのにIPアドレスを指定すると失敗するという、よく分からない挙動を見せました。
これはこれでハマりポイントになりそうなので、gatewayはちゃんと設定して変わったら都度都度変更するという運用にしようと思います。

あとがき

速度制限が辛い! というのが今回のきっかけでした。
通信はもっぱらPocket WiFi使ってましたが、こいつが一日に3GB通信すると死んでしまったり、勝手に何度も再起動したりする曲者でして。
緊急時はスマホテザリングでしのいだりしてましたが、こちらも格安SIMなのであまり使いたくない…。
そんな折、なんとなく楽天モバイルを契約したので、こいつをサブWi-Fiとして使おうと思い立ち、ラズパイでも任意のタイミングでWi-Fi接続を切り替えられるようにしよう!という経緯です。

自宅、職場・学校などでのWi-Fiをそれぞれ設定するだけであればwpa_supplicant.confに追記していけばいいのですが、同時に複数Wi-Fiが利用可能な状態で切り替える方法についての情報があまりなかったので、ご参考になれば幸いです。

ちなみに楽天モバイルの通信状況はいまのところいい感じです😁