Edited at

Raspberry Piを3GネットワークPPP接続のみで運用(SORACOM Air)

More than 1 year has passed since last update.

これができます

Raspbery Pi ZeroとAKA-020の悪魔合体

2016年8月現在、Raspberry Piを3Gでネットに接続する方法で入手しやすい製品として、「SORACOMスタータキット(3G USBドングル AK-020同梱)」を使う方法があります。

今回は、Raspberry Pi A+ や Raspberry Pi Zero に USB接続の3GモデムAK-020を繋いで、セットに同梱のSORACOM AirでRaspberry Piをインターネットに接続できるマシンを作ります。

注意



  • wvdial ではなくて pon poff によるダイヤルアップ制御1をします。

  • SORACOM Airは通信量従量制で、安価なサービスというわけではない2ので、定額SIM用に別の作例を用意しています。


ざっくり概要

設定とか入る前にざっくりした説明しておきます


動作確認は?

今回のテストにあたり、


  • Raspberry Pi 1 Model B 512MB

  • Raspberry Pi 1 Model A+ 256MB

  • Raspberry Pi 1 Model A+ 512MB

  • Raspberry Pi 3 Model B+

  • Raspberry Pi Zero カメラ端子なし版

  • Raspberry Pi Zero カメラ端子あり版

にNOOBSでインストールした Raspbian Jessie(2016-05-27)で動作確認をしております。


  • Raspberry Pi 1 Model B 512MB

  • Raspberry Pi 1 Model A+ 512MB

  • Raspberry Pi 3 Model B+

にNOOBSでインストールした Raspbian Jessie With PIXEL(2016-11-25)で動作確認をしております。


必要3G-USBモデム・3G SIM

下記セット商品に同梱される3G USBモデム・3G SIMを利用します。

SORACOMスターターキット 3G USBドングル AK-020同梱 [switch-science.com] セット内容写真


  • SORACOMスターターキット 3G USBドングル AK-020同梱 ¥5,980


    • 3G-USBモデム ABIT AK-020(¥4,980)

    • 3G SIM SORACOM Air nano-SIM(¥954)

    • nano-SIM→mini-SIM変換 SORACOM SIM アダプター(¥100)

    • 1,000円分クーポン同梱



Raspberry Piのシステムファイルには、機材固有の設定をします。今回はSORACOM Air/AK-020専用設定となります。


⚠ 制作に入る前に


  • 本稿では、Raspberry Piがインターネットに接続可能になっている状態からセットアップしていきますので、Raspberry PiにRaspbian Jessieをセットアップする作業Raspberry Pi を有線もしくはWi-Fiでインターネットにつなぐ作業は予め完了しておいてください


  • SORACOM Airの nanoSIM のアクティベーションを済ませ、1000円分のクーポンは適用済みにしておいてください。

  • 説明の際、 pi@raspberrypi:~ $ と書いている場所は、コンソールが表示するプロンプトですので、入力しないでください。


  • RaspberryPiのコンソールへコピペ と書いているところは、閲覧しているブラウザ上でクリップボードにコピーしておいて、コンソール上にペーストするとファイルが生成されたりコマンドが実行されるようになっています。最後の行は改行がコピーできていないので、自分でEnterキーを入れてあげてください。


設定

実際に操作を順番に追って設定していきます。


① Raspbianにpiユーザでログイン

以下の方法のいずれかで、Raspberry Piへコンソールアクセスします。


  • Raspberry PiのGUIで、LXTerminal を起動

  • Raspberry PiをDHCP制御下の有線LANにつないで、他のホストからSSH接続して pi ユーザーでログイン

  • Raspberry PiでWi-Fiを使えるようにして、無線LANのネットワークに参加させ、ネットワーク内の他のホストからSSH接続して pi ユーザーでログイン

  • Raspberry PiのGPIOに出ているUARTにシリアル接続


② 3G-USBモデム AK-020を挿入した時のLinuxの挙動を調整

先人達の努力により、


  • 3G-USBモデムを接続すると最初はCDとして認識され、 Eject すると本来の通信デバイスとして認識される

  • Linux側でUSBの認識制御をする usb_modeswitch があって、特定のUSBデバイスが認識されたら eject するまでできちゃう


  • udev により、デバイスの認識とそれに対するふるまいを設定できる


  • Systemd と統合されているためデバイスの認識に合わせて、 Systemd へメッセージを送ることができる

ということがわかっています。

今回使用する3G-USBモデム、AK-020用の特別設定を準備します。


RaspberryPiのコンソールへコピペ

cat << 'EOS' | sudo tee /etc/udev/rules.d/40-ak-020.rules

ACTION=="add",\
ATTRS{idVendor}=="15eb",\
ATTRS{idProduct}=="a403",\
RUN+="/usr/sbin/usb_modeswitch --std-eject --default-vendor 0x15eb --default-product 0xa403 --target-vendor 0x15eb --target-product 0x7d0e"

ACTION=="add",\
ATTRS{idVendor}=="15eb",\
ATTRS{idProduct}=="7d0e",\
RUN+="/sbin/modprobe usbserial vendor=0x15eb product=0x7d0e"

ATTRS{../idVendor}=="15eb",\
ATTRS{../idProduct}=="7d0e",\
ATTRS{bNumEndpoints}=="03",\
ATTRS{bInterfaceNumber}=="02",\
SYMLINK+="ttyAK020",\
ENV{SYSTEMD_WANTS}+="ifup@wwan0.service"
EOS



RaspberryPiのコンソールへコピペ

sudo reboot


これで、Raspberry PiのUSBポートにAK-020を差し込むと、


  • 最初に認識されるCD-ROMデバイスが自動でマウント解除され、

  • 次に認識されるUSBシリアルデバイスにドライバをあてがい、

  • USBシリアルデバイスを /dev/ttyAK020 にリンクします。

  • あと、(あれば)ネットワークインタフェース wwan0 をupします。

実際にAK-020をRaspberry Piにつなぐ前と、つないだ後で比較してみます。


udev調整後、AK-020未接続の/dev/tty*のリスト

$ ls /dev/tty*

/dev/tty /dev/tty21 /dev/tty35 /dev/tty49 /dev/tty62
/dev/tty0 /dev/tty22 /dev/tty36 /dev/tty5 /dev/tty63
/dev/tty1 /dev/tty23 /dev/tty37 /dev/tty50 /dev/tty7
/dev/tty10 /dev/tty24 /dev/tty38 /dev/tty51 /dev/tty8
/dev/tty11 /dev/tty25 /dev/tty39 /dev/tty52 /dev/tty9
/dev/tty12 /dev/tty26 /dev/tty4 /dev/tty53 /dev/ttyAMA0
/dev/tty13 /dev/tty27 /dev/tty40 /dev/tty54 /dev/ttyS0
/dev/tty14 /dev/tty28 /dev/tty41 /dev/tty55 /dev/ttyprintk
/dev/tty15 /dev/tty29 /dev/tty42 /dev/tty56
/dev/tty16 /dev/tty3 /dev/tty43 /dev/tty57
/dev/tty17 /dev/tty30 /dev/tty44 /dev/tty58
/dev/tty18 /dev/tty31 /dev/tty45 /dev/tty59
/dev/tty19 /dev/tty32 /dev/tty46 /dev/tty6
/dev/tty2 /dev/tty33 /dev/tty47 /dev/tty60
/dev/tty20 /dev/tty34 /dev/tty48 /dev/tty61


udev調整後、AK-020接続後の/dev/tty*のリスト

 $ ls /dev/tty*

/dev/tty /dev/tty21 /dev/tty35 /dev/tty49 /dev/tty62
/dev/tty0 /dev/tty22 /dev/tty36 /dev/tty5 /dev/tty63
/dev/tty1 /dev/tty23 /dev/tty37 /dev/tty50 /dev/tty7
/dev/tty10 /dev/tty24 /dev/tty38 /dev/tty51 /dev/tty8
/dev/tty11 /dev/tty25 /dev/tty39 /dev/tty52 /dev/tty9
/dev/tty12 /dev/tty26 /dev/tty4 /dev/tty53 /dev/ttyAK020
/dev/tty13 /dev/tty27 /dev/tty40 /dev/tty54 /dev/ttyAMA0
/dev/tty14 /dev/tty28 /dev/tty41 /dev/tty55 /dev/ttyS0
/dev/tty15 /dev/tty29 /dev/tty42 /dev/tty56 /dev/ttyUSB0
/dev/tty16 /dev/tty3 /dev/tty43 /dev/tty57 /dev/ttyUSB1
/dev/tty17 /dev/tty30 /dev/tty44 /dev/tty58 /dev/ttyUSB2
/dev/tty18 /dev/tty31 /dev/tty45 /dev/tty59 /dev/ttyUSB3
/dev/tty19 /dev/tty32 /dev/tty46 /dev/tty6 /dev/ttyprintk
/dev/tty2 /dev/tty33 /dev/tty47 /dev/tty60
/dev/tty20 /dev/tty34 /dev/tty48 /dev/tty61

後の工程で使うため、AK-020は接続したままにしておきます。


③ USB-3GモデムにAPN設定を入れる

今回利用したUSB-3Gモデム・AK-020は実質APN設定をUSB-3Gモデムに記憶させておく必要がありません。なのでこの工程は飛ばす。


④ RaspbianにPPP設定を作る

ppp 設定用対話型プログラムの pppconfig をインストール。


RaspberryPiのコンソールへコピペ

sudo apt-get -y install pppconfig


pppconfig を起動する。これは、SORACOM AirとAK-020用の接続設定となります。


RaspberryPiのコンソールへコピペ

sudo pppconfig soracom_ak-020


以下の設定を順番に設定する。モーダルインタフェースとなっているから、1項目ごとに入力していくので注意。

Configure Nameservers(DNS):Dynamic

Authentication Method:PAP
User Name:sora
Password:sora
Speed:460800
Pulse or Tone:Tone
Phone Number:*99#
Choose Modem Config Method:No
Manually Select Modem Port:/dev/ttyAK020

Finishedで設定ファイルの書き出しを行い、そのあと、Quitして終了。

Authentication Method(認証メソッド)ですが、pppconfig 2.3.18 のバージョンには、 Raspbian Jessie(2016-05-27)では、認証メソッドに CHAP を選んでも、パスワードが /etc/ppp/chap-secrets に記録されない不具合がある**ので3、認証メソッドを PAP にします。


PPP接続時、デフォルトルートをPPP側に置き換える設定



  • persist:接続維持


  • replacedefaultroute:PPP接続時にデフォルトルートを自動で置き換える設定。
    実質的にこれによって3Gモデムでインターネット接続ができることになる。


RaspberryPiのコンソールへコピペ

cat << EOS | sudo tee -a /etc/ppp/peers/soracom_ak-020

persist
replacedefaultroute
EOS


書き換え後は以下のようになります。


/etc/ppp/peers/soracom_ak-020

# This optionfile was generated by pppconfig 2.3.18.

#
#
hide-password
noauth
connect "/usr/sbin/chat -v -f /etc/chatscripts/soracom_ak-020"
debug
/dev/ttyAK020
460800
defaultroute
noipdefault
user "sora"
remotename soracom_ak-020
ipparam soracom_ak-020

usepeerdns
persist
replacedefaultroute



APN設定・PPP接続用チャットスクリプトの修正

PPP接続時に、モデムとコマンドシーケンスを送受信しますが、それの制御をするチャットスクリプトを調整します。

3G SIMのAPNの設定もこちらになります。


RaspberryPiのコンソールへコピペ

sudo sed -i -e "s/'' ATZ/'' ATH\n\

OK AT+CFUN=1\n\
OK ATZ\n\
OK 'ATQ0 V1 E1 S0=0 \&C1 \&D2'\n\
OK AT+CGDCONT=1,\"IP\",\"soracom.io\"\
/" /etc/chatscripts/soracom_ak-020

書き換え後は以下のようになります。


/etc/chatscripts/soracom_ak-020

# This chatfile was generated by pppconfig 2.3.18.

# Please do not delete any of the comments. Pppconfig needs them.
#
# ispauth CHAP
# abortstring
ABORT BUSY ABORT 'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT 'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
# modeminit
'' ATH
OK AT+CFUN=1
OK ATZ
OK 'ATQ0 V1 E1 S0=0 &C1 &D2'
OK AT+CGDCONT=1,"IP","soracom.io"
# ispnumber
OK-AT-OK "ATDT*99#"
# ispconnect
CONNECT \d\c
# prelogin

# ispname
# isppassword
# postlogin

# end of pppconfig stuff


⑤ PPP接続テスト

AK-020は接続したままにしてありますので、この状態でPPP接続のテストをします。


RaspberryPiのコンソールへコピペ

sudo pon soracom_ak-020


AK-020のランプが、接続後待機状態の緑点灯⇒赤点灯⇒緑点滅(2Hz)になると、PPP接続完了です。


RaspberryPiのコンソールへコピペ

curl globalip.me


で、SORACOM Air(AWS)のホストIPが割りあてられていることを確認してください。


実行例

pi@raspberrypi:~ $ curl globalip.me

54.250.252.65
pi@raspberrypi:~ $ host `curl globalip.me`
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 5 0 0:00:02 0:00:02 --:--:-- 5
65.252.250.54.in-addr.arpa domain name pointer ec2-54-250-252-65.ap-northeast-1.compute.amazonaws.com.
pi@raspberrypi:~ $

確認が終わったら、PPP接続を切断します。


RaspberryPiのコンソールへコピペ

sudo poff soracom_ak-020


3G-USBモデムのランプの緑点滅が、緑点灯になり、PPP接続が終了しました。


⑥ PPP接続用ネットワークインタフェースを作る

電源投入後、または3G-USBモデムをUSBポートに挿したタイミングで自動でPPP接続したいので、設定を作ります。

Raspberry Piに仮想のネットワークインタフェース wwan0 を用意し、PPP接続と紐づけます。


RaspberryPiのコンソールへコピペ

cat << 'EOS' | sudo tee -a /etc/network/interfaces

allow-hotplug wwan0
iface wwan0 inet ppp
provider soracom_ak-020
EOS


書き換え後は以下の通り。


/etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)


# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wwan0
iface wwan0 inet ppp
provider soracom_ak-020


なお、Raspbian Jessieの Systemd では、/etc/network/interface に書かれたネットワークインタフェースは Systemd における .service タイプの Unit として認識されるようです。


⑦ ネットワークインタフェースのリンクアップテスト

ネットワークインタフェースがシステム上にブリングアップしてきたときにちゃんとPPP接続ができるかテストをしていきます。ケースは3通りです。


  • 手動でネットワークインタフェースを ifup してみる

  • 3G-USBモデムをUSBポートに挿入してみる

  • 3G-USBモデムをUSBポートに挿入したままRaspberry Piを再起動してみる


手動でネットワークインタフェースをifup/ifdownして接続テスト

wwan0 ネットワークインタフェースを ifup することで、PPP接続が開始します。


RaspberryPiのコンソールへコピペ

sudo ifup wwan0


3G-USBモデムの緑ランプが2Hz点滅するとPPP接続済み。

wwan0 ネットワークインタフェースを ifdown することで、PPP接続が終了します。


RaspberryPiのコンソールへコピペ

sudo ifdown wwan0


3G-USBモデムの緑ランプが点灯(待機状態)に切り替わります。


3G-USBモデムをUSBポートに挿入してリンクアップするかテスト

まだ3G-USBモデムがUSBポートに刺さったままだと思いますので、いったん抜きます。

少し待ってから(10秒くらい)、もう一度USBポートに挿してみると、数十秒から2分ぐらいまでの間で自動で接続開始します(3G-USBモデムの緑ランプが2Hz点滅するとPPP接続済み)。


Raspberry Piを再起動して自動でリンクアップするかテスト

3G-USBモデムをUSBポートに挿した状態のままにして、Raspberry Piを再起動します。


RaspberryPiのコンソールへコピペ

sudo reboot


Raspberry Piブートアップの途中で、3G-USBモデムがリンクアップするはずです。


⑧ 一巻の終わり

PPP接続開始の時点で、デフォルトゲートウェイが3G側に切り替わり、Raspberry Piから外に出る接続は3G経由となりますが、3G SIMに割り当てられるIPアドレスがAWSのプライベートIPアドレスだったりします。

ということは、Raspberry Piの内部から外のインターネット側へは通信できますが、インターネット側からRaspberry Piの内部には入って行けません。そのような必要があるのなら、せっかくのLinuxなのですから、Raspbery PiからどこかのVPSなど自分所有ホストへSSHトンネルを掘るなどするとよいですね。


おまけ

この仕組み、なんに使おうかなー


Raspberry Piから外部ホストへSSHトンネルを掘る

3G-USBモデムだけが刺さったRaspberry Piに、別ホストからリモートログインできるようにするため、Raspberry Piから、3G-USBモデムを通じインターネット上のほかのホストにSSH接続し、トンネルを掘ります

遠隔地に置きっぱなしのRaspberry Piがあったとして、そのRaspberry Piが遠隔地から手元のホストにトンネルを自力で掘ってくれるので、自分が遠隔地に行かなくともRaspberry Pi側から掘られ済みのトンネルを通じてリモートログインできるのはとっても便利なような気がします。

見方を変えると、インターネットからRaspberry Piに入れるようになるUSBドングル、とも言えますね。


RaspberryPiのコンソールへコピペ

sudo apt-get -y install autossh



RaspberryPiのコンソールへコピペ

cat << "EOS" | sudo tee /etc/ppp/ip-up.d/10ssh-tunnel

#!/bin/sh

# This script is called with the following arguments:
# Arg Name Example
# $1 Interface name ppp0
# $2 The tty /dev/ttyS1
# $3 The link speed 38400
# $4 Local IP number 12.34.56.78
# $5 Peer IP number 12.34.56.99
# $6 Optional ``ipparam'' value foo

if [ "$2" = "/dev/ttyL05A" \
-o "
$2" = "/dev/ttyAK020" \
-o "
$2" = "/dev/ttyE1750" \
]; then

# ppp0 の txqueuelen が 3 なので、大きくする
/sbin/ifconfig $1 txqueuelen 128

# root権限で動いているため、ほかのユーザで実行したい場合は
# su <user> -c "echo hoge" 的なことをする
#
# autossh でトンネルを掘る場合は、トンネルの出口の sshd の
# 設定で、ClientAliveInterval 10/ ClientAliveCountMax 3
# などの 回線が死んだらsshも自然に死ぬようにしておく必要が
# あります(送り側のautosshでsshのセッションを張りなおしても、
# 受け側の古いsshdが死なずに居座るとListen出来ないので)。

su pi -c \
'/usr/bin/autossh \
-N -f -M 0 \
-o ServerAliveInterval=60 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
-o StrictHostKeyChecking=no \
-R 10022:localhost:22 \
-i /home/pi/.ssh/id_rsa \
-l remotehostuser \
example.com'
fi

exit
EOS



RaspberryPiのコンソールへコピペ

sudo chmod 755 /etc/ppp/ip-up.d/10ssh-tunnel


/etc/ppp/ip-up.d/ の中に実行権限をつけたスクリプトを置いておくと、PPPで接続確立後に実行されますので、 autossh によるSSHトンネルを掘る例です。

これをすると、3G電波だけでインターネットにつながっている Raspberry Pi に外部ホストからリモートログインが実現できます。


SSHトンネルの出口となっている外部ホストのコンソールへコピペ

slogin pi@localhost -p 10022 -o StrictHostKeyChecking=no



応用

GPSを搭載して、node.js を使って AWS IoTJSON をPubして、 DynamoDB に現在位置をダダ記録するのはどうでしょう。

PasPiApuls-3GUSB-GPS.jpg


参考文献


脚注





  1. Raspberry PiをSORACOM Airを利用する場合、wvdial というダイアラーを使う作例が多いですが、それは、本命の Linuxで一般的な標準パッケージ ppp に含まれている、古式ゆかしい pon poff によるPPP接続Linuxで一般的な標準パッケージ ppp に含まれている、古式ゆかしい pon poff によるPPP接続を作るときに利用する pppconfig に不具合があり、PPP接続ができなかったため、代替方法として wvdial を選択してきたのだと思われます。今回 pppconfig を使った時の不具合とそれの解消方法が判明したので、pon poff によるPPP接続をします。 



  2. 今回の作例で使う SORACOM Air は通信コスト的に安くはない(AWSを使うと国内クラウド基盤を使うより割高程度のニュアンスで高い)、定額SIMを使いたい場合は、定額SIMで作った場合の作例を用意していますからそちらを参照してください。 SORACOM Air を使った時の最大の利点は、IoT的な利用シーンでデバイスが盗難にあった時、SORACOM のコントロールパネルからSIMの停止ができる点ですので、IoTの実運用のプロダクトのときは使えばいいかと。 



  3. なお、PPP接続のための別のパッケージ wvdialCHAP 認証で設定すると、正しく /etc/ppp/chap-secrets にパスワードが設定されるため、以降 CHAP で設定していた pppconfig で作った接続設定でもつながるようになります。Raspbianでの接続例は wvdial での例ばかりなのはおそらくこれのせい。