外出時にRaspberry Pi 3を起動すると自動的にホットスポットになるスクリプトを作りました(RPi3_Switchable_HOTSPOT)


Raspberry Pi 3 Model Bをホットスポットにしたいと思っています。方法はすでに多くのサイトでまとめられています。しかし、ホットスポット化の解除まで気を使ってくれる情報がほとんどありません。いつもホットスポットを使うわけではないですよね。

自宅で使う時は通常通りWiFiクライアントとして動かしたい、外出時は自動でホットスポットとして動かしたい、ホットスポットの起動と解除を簡単にできるようにしたい、という私の要求を実現するスクリプトを作ってみました。



Raspberry PiをWiFi ホットスポットにする方法を調べる

Raspberry PiをWiFiホットスポットにする方法は、すでに多くの情報を検索して見つける事ができるでしょう。逆に情報が多すぎ自分のハードウエア、OSにはどの設定を使えばいいかわからないくらいです。使うソフトウエアが異なるパターンもあります。
役に立ちそうな情報の整理をしておきます。

まずは基本的なフォーラムスレッドを押さえておきます。OSのバージョンアップなどで動作が変わったら最初にチェックした方が良い場所です。

[Tutorial] Using the RasPi as a WiFi hostspot (8 Nov 12)

一番最初にホットスポット化の設定手順がまとめられたサイトへの誘導があります。
The tutorial has now been moved to: http://elinux.org/RPI-Wireless-Hotspot
デファクトスタンダードのような手順となるので困ったときの情報も多そうです。
私はこれに従ってやってみます。

ホットスポットの解除はどうやってするのか?

ホットスポット化の情報の多くはホットスポットにする手順だけが書かれています。ではホットスポットを使わず普通に使いたい時はどうしたら良いのでしょうか?OSのイメージから焼けというのでしょうか。
ホットスポットの解除まで気を使ってくれる情報は少ないです。ホットスポット化するだけで頭が混乱するのに、解除の手順なんてもうわからない・・・という方も多いでしょう。
もちろんホットスポット化の手順の意味を理解すれば解除もできるわけですが・・・

自宅のSSIDが無い外出時だけホットスポット化したい

簡易WiFiルータとして外出時にだけホットスポットを使いたい方も多いのではないでしょうか。出張先のホテルなどでホテルのLANとスマートフォンをつないでYouTubeを見たいとか。ホットスポット化専用のSDカードを作っておくのも手です。
しかし、IoTもどきをいろいろな場所でやってみたいと思ってる場合は、外出時だけ自動でホットスポット化したいですね。どうやってやればいいんでしょうか。

Linuxはディストリビューションやバージョンによって設定場所が微妙に異なる場合があって面倒です。極力最近の状況にあった情報を探します。
Raspberry PI 3 Auto WiFi Hotspot if no Internet / Raspberry Connect
My requirements are for when the pi is at home it connects to my home router or other known routers so it is available on the local network. If no router is found when it is started up then it will create a wifi hotspot, which is not rooted to the Internet, so i can SSH to the RPi from another device and control the camera and run other custom scripts.
そうなんですよ。LANが無い時にどうやってRaspberry Piへ接続するか。この方法を確立しないと外でRaspberry Piを使えません。

このサイトの情報では、SSIDに登録されたものがあるか判断し、無い場合はホットスポット化のスクリプトを呼び出す、という事をしているようです。

ですが、この方法はちょっとお行儀わるいようです。
アクセスポイントのスキャンをどこからどうやって動かすかが課題になります。

wpa_supplicantをkillする方法

実験していると良くわからない現象に会いました。ホットスポット化のオン・オフを何度か繰り返すと自宅のAPへ接続しなくなります。APのSSIDとパスワードによる認証が行われなくなるようです。
接続できない時は
wpa_supplicant -B -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
を実行することでAPへの認証が行われ接続できることがわかりました。
これで解決か?と思いましたが今度は別の問題が発生します。

動いているwpa_supplicantの影響でホットスポットが働きません。hostapdを使ったホットスポット化のホームページを検索すると /etc/network/interfaces のwpa-confの行をコメントアウトしろと書いてあります。
なぜコメントアウトしなくてはならないのか?理由が書いてあるページを見つけることができませんでした。どうやらwpa_supplicantが動いているとホットスポットができないようです。
wpa_supplicantの影響でホットスポットが動かない時には
pkill wpa_supplicant
とwpa_supplicantをkillすればホットスポットは動き出すでしょう。

この現象をさらに分かりにくくする原因に、RPi起動後の最初のifdownではwpa_supplicantが終了する、というのがあります。うまくいった!と喜んでいると次は動かない。

ポイントが絞れてきました。wpa_supplicantをどうやって終了させるか。プロセスからkillしちゃえば解決じゃん。と思われるでしょう。お手軽にはそれでいいです。
ですが別の問題が生じます。WiFiインターフェースを複数使っている場合にwpa_supplicantをkillしていいのでしょうか。WiFiアダプタを2つ付けて動作させる事はあり得ますよね。wpa_supplicantを単純にkillすると使いたい方のWiFi認証も切断されちゃうのでしょうか。

課題がはっきりしてきたので検索し直します。するととても良い情報が書いてあるスレッドを見つける事ができました。
Need to restart network interfaces and kill wpa_supplicant, how to fix?answered Nov 9 '12 at 13:49 nofrills
Just create a configuration file and edit your /etc/network/interfaces this way:
auto lo
iface lo inet loopback
auto wlan0
iface wlan0 inet dhcp
    pre-up wpa_supplicant -B -Dwext -i wlan0 -c/etc/wpa_supplicant.conf
    post-down killall -q wpa_supplicant 
If you like doing things neatly, as an alternative to the generic killall command, you can use the WPA specific tool wpa_client:
wpa_cli -i wlan0 terminate
nofrillsさん、ありがとう!

何か先の路が見えた感じがしました。
これですよね。開いたら閉じる。使ったら片づける。プログラムなら当たり前の事です。RPiというお手軽コンピュータの場合は後片付けをしない使い方が多いようです。

/etc/wpa_supplicantフォルダにスクリプトファイルがあり、その中にいろいろありますね。使い方がわかりませんけど。ifupdown.shで自動的にやってくれそうな感じがするのですがプロセスが生きてたり起動しなかったりでよくわかりません。

ということで、/etc/network/interfacesは次のように書いておきます。
iface wlan0 inet manual
    post-up wpa_supplicant -B -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
    pre-down wpa_cli -iwlan0 terminate
複数のWiFiインターフェースがあるときに使いたい方のwpaが動くのかは試していません。

調べた手順を踏まえてホットスポット化をしてみる

以上の調査と実験でLinuxのネットワークを動かす仕組みがだんだんわかってきました。ネットワークに必要な操作は/etc/network/interfacesで行うのがスマートな方法のようです。
interfacesの文法を理解するのに1週間かかりました。

とにかくLinuxのいろいろな設定方法を調べるのはとても大変です。OSバージョンによる微妙な違い、ネットワーク周りの非推奨なコマンドと代替コマンドなど似たようなコマンドの数々。互換設定とsystemdの関係。操作を便利にしてくれそうな隠れたスクリプト。何が何だかわからなくなってきます。
できるだけ最新の状況に合う方法にしたいです。そうしないとせっかく作った方法がOSのバージョンアップですぐに使えなくなってしまうでしょう。

最初に紹介したデファクトスタンダードとも言える手順に沿います。
OSはRASPBIAN JESSIE WITH PIXELを前提とします。jessieなら以前のOSイメージでも同じ手順でできると思います。
Raspberry Pi 3 Model Bの内蔵WiFiで動作させます。

RPi3_Switchable_HOTSPOT

ホットスポットをインストールするスクリプトを作りました。
素のOSで動かすことを想定しています。有線LANに固定IPアドレスを割り当てる等、既に何かネットワークまわりの設定をしている場合は上書きされますので注意してください。

RPi3_Switchable_HOTSPOT / GitHub
私のホットスポット化の特徴を紹介しておきます。基本は素のRaspbianのネットワーク環境を維持しています。
  • 登録したESSIDが見つかれば通常のWiFクライアントiとして動く。
  • 登録したESSIDが見つからなければアクセスポイントとして動く。
  • コマンドでいつでもホットスポット化と解除ができる。
  • ホットスポット化の強制ができる。
  • PIXELのWiFi設定と干渉しない。(たぶん・・・)
  • USB WiFiドングルにも対応できる。(はず・・・)

インストール

インストールの仕方を説明します。
まずはリポジトリのパッケージを更新しておきます。
sudo apt-get update
sudo apt-get upgrade

RPiのホームディレクトリで良いので、次のコマンドを入れます。
git clone https://github.com/SignalFlagZ/RPi3_Switchable_HOTSPOT.git
cd RPi3_Switchable_HOTSPOT
./install.sh

インストールが終わったら自宅WiFiのessidを登録しましょ。これをしないと常にホットスポット状態になってしまいます。
ファイル/etc/network/interfacesを開きます。
sudo nano /etc/network/interfaces
"map YOUR_ESSID1"と書いてある行を探してください。
"YOUR_ESSID1"を自宅のessidに書き換えます。
保存します。

ホットスポット化した時のRPiのessidとパスワードは、
Default HOTSPOT essid : My_AP
Default HOTSPOT password : My_Passphrase
となっています。
/etc/hostapd/hostapd.confファイルで変更できます。

RPiを再起動します。
sudo reboot

再起動するとWiFiをスキャンし、登録した自宅のessidが見つかればいつも通りに立ち上がるでしょう。
essidを間違えたり、essidが見つからなかった時はホットスポットとして立ち上がります。スマートフォンでWiFiを見てみましょう。
有線LANの設定は何も変わりません。接続できなくなったら有線LANで確認しましょう。
ネットワークインターフェースの状態は
ip a
で確認できます。wlan0があるか、IPアドレスは割り当てられているか確認しましょう。

/etc/network/interfaces

今回のホットスポット化の肝は/etc/network/interfacesです。
これの書き方を調べるのにめちゃくちゃ時間かかりました。未だにわからない。

少し説明します。
スクリプトでは/etc/network/interfacesを丸ごと上書きしてしまいます。
変更の中身はwlan0の設定を変えているだけです。他のインターフェースには影響しませんので、既に何か設定をしていた方はインストール後、再度設定してください。
installスクリプトでは上書きですが、次の記述を追加しているだけです。
allow-hotplug wlan0
mapping wlan0
  script /usr/local/bin/apscan.sh
  map YOUR_ESSID1 home
  map hotspot0

iface home inet manual
    post-up wpa_supplicant -B -i"$IFACE" -c/etc/wpa_supplicant/wpa_supplicant.conf
    pre-down wpa_cli -i"$IFACE" terminate

iface hotspot0 inet static
  address 192.168.42.1
  netmask 255.255.255.0
  pre-up sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
  pre-up iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  pre-up iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
  pre-up iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
  post-up service hostapd start /etc/hostapd/hostapd.conf
  post-up service udhcpd start
  pre-down service udhcpd stop
  pre-down service hostapd stop
  post-down iptables -D FORWARD -i wlan0 -o eth0 -j ACCEPT
  post-down iptables -D FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
  post-down iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
  post-down sh -c "echo 0 > /proc/sys/net/ipv4/ip_forward"
ホットスポット化には今回追加したapscan.shというスクリプトが必須です。このスクリプトでWiFiスキャンしネットワーク設定名を決めています。

mappingとある行の下にmapから始まる行があります。mapに2つ引数を書くと、ESSIDと対応する設定名として解釈します。設定名と一致するifaceスタンザの設定が行われます。
mapに1つの引数を書くとホットスポット用の設定名として解釈します。
これらの解釈はapscan.shでの解釈でありmap文の動作では無い事に注意してください。今後の更新で大きく変えるかもしれません。本記事公開日時での動作です。

YOUR_ESSID1とある部分を自宅などのアクセスポイントのESSIDに替えてください。このESSIDが見つかると設定名homeの設定が適用されます。つまりホットスポット化しません。
ESSIDが見つからない時は設定名hotspot0が適用されます。

APへの認証処理には関与していません。APにつなぐ処理は行っていません。RPiのデスクトップで、表示されるAPのパスワードを入れるのが簡単でしょう。
wlan0をダウンさせるとwpa_supplicantが停止します。wpa_supplicantの挙動を把握していないので、他のインターフェースで認証処理が必要な使い方をしている方は気を付けてください。

DHCPの提供アドレスを変えた方は設定名hotspot0のaddressとある行のIPアドレスを/etc/udhcpd.confに合わせて変えます。

使い方

RPiを起動するとアクセスポイントをスキャンして、WiFiクライアントとしてアクセスポイントに接続するか、RPi自体がアクセスポイントとして動作するか切り替わります。 自宅のAPを登録していれば、自宅にいる時は通常のWiFiクライアントとして、外出時はRPiがアクセスポイントとして動きます。

接続するESSIDは/etc/network/interfacesファイルのmap文に書きます。
map YOUR_ID CONF_NAME
と書いておくと、WiFiをスキャンして"YOUR_ID"というessidが見つかると、設定名"CONF_NAME"のiface規定を使ってネットワークを設定します。
map HOTSPOT
と書いておくと、ホットスポット化する際に設定名"HOTSPOT"のiface規定を使ってネットワークを設定します。今回の例ではhotspot0になります。

mpa行にessidを書いたとしてもアクセスポイントへの接続処理は行いません。あくまでWiFiの動作モードを変更しているだけです。
実際の接続にはPIXELデスクトップなどでAPのパスワードを登録してください。普通にRaspbianを使うのと同じです。APへの接続はwpa_supplicantにお任せです。
    コマンドでもWiFiの動作モードを変える事ができます。

    ホットスポットに切り替える

    次のコマンドでアクセスポイントとして動きます。設定名hotspot0でネットワークを構成する例です。
    sudo ifdown wlan0
    sudo ifup wlan0=hotspot0

    WiFiクライアントに切り替える

    次のコマンドでWiFiクライアントになります。設定名homeでネットワークを構成する例です。
    sudo ifdown wlan0
    sudo ifup wlan0=home

    ホットスポット化を強制する

    自宅でホットスポット化したい場合、再起動のたびにコマンドを入れるのも面倒です。最初からホットスポットとして動かしたいですよね。

    このような時は/usr/local/bin/hotspot_varというファイルを作ってください。 そしてファイルの先頭行に"1"と数字1文字を書いてください。
    これで再起動するとホットスポットとして起動します。
    解除するにはhotspot_varの先頭行を'0'にします。

    まとめ

    Linuxの事は良く知らずにネットワークの設定をいじり始めました。しんどかった。

    これで好きな時にRaspberry Piをホットスポットとして動かす事ができるようになりました。 外へRPi3を持ち出した時に、スマートフォンとのテザリング設定を忘れていたり、LANケーブルを忘れても安心です。接続手段がなくて困ることが減るでしょう。ホットスポットへスマートフォンなどで接続すれば何かできますよね。

    ホットスポット化の手順は既にあるので簡単に実現できると思っていました。しかしながら調べてみると満足できる方法は見つけられませんでした。
    RPiの使い方としては最初にやりたくなるような事なのになぁ・・・そんなことない?
    RPiは小型で安く、SDカードだけで簡単にOSを変える事ができます。手軽さゆえに、やりっぱなしみたいな方法の氾濫を許しているのではないでしょうか。
    できるだけ素のRaspbianの状態へ戻るようにしています。ルーティングなど既に行っている方には邪魔かもしれませんが、まぁ簡単に直せるでしょ?

    /etc/network/interfacesの実例がほとんどないので困りました。さらにmappingスタンザの意味が分からずはまりました。map文いらないじゃん・・・と。 実例が無いと理解できない私の頭には難しい動作です。

    ifconfigは使っていいのか?ipにすべきか?さりげに悩みました。
    Linuxはディストリビューションとバージョンの組み合わせが多すぎてコマンドとツールに何が使えるか良くわからないです。似た情報が氾濫して今のRaspbianで使うべき方法との区別ができずググるのも大変です。

    wpa_supplicantの動作をもう少し調べたいです。認証はwpa_supplicantに任せたいです。今回の方法では他のインターフェースでwpa_supplicantを使うのを妨げているかもしれません。停止させないで動かしっぱなしにしたいです。hostapdが動かない原因がはっきりできれば可能かもしれません。そうすれば、家のWiFiにつなぎつつホットスポットとしても動作する設定ができると思うのですが成功してません。

    とにかく、これでいつでもどこでもRPiへつなぐルートができました。
    USB 3G モデムも手に入れたのでいよいよ外でRPiを使う環境が整ってきました。
    こちらもどうぞ:MVNOのSIMをUSB接続できる3GモデムL-02CをWindows 10で使ってみる
    今回の方法なら3Gモデムへの対応も簡単です。

    次回はRPiでUSB 3Gモデムを使ってみようと思います。


    コメント

    最近のコメント

    Threaded Recent Comments will be here.