これができます
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用の特別設定を準備します。
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
sudo reboot
これで、Raspberry PiのUSBポートにAK-020を差し込むと、
- 最初に認識されるCD-ROMデバイスが自動でマウント解除され、
- 次に認識されるUSBシリアルデバイスにドライバをあてがい、
- USBシリアルデバイスを
/dev/ttyAK020
にリンクします。 - あと、(あれば)ネットワークインタフェース
wwan0
をupします。
実際にAK-020をRaspberry Piにつなぐ前と、つないだ後で比較してみます。
$ 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
$ 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
をインストール。
sudo apt-get -y install pppconfig
pppconfig
を起動する。これは、SORACOM AirとAK-020用の接続設定となります。
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(認証メソッド)ですが、 Raspbian Jessie(2016-05-27)では、認証メソッドに pppconfig 2.3.18
のバージョンには、CHAP
を選んでも、パスワードが /etc/ppp/chap-secrets
に記録されない不具合がある**ので3、認証メソッドを PAP
にします。
PPP接続時、デフォルトルートをPPP側に置き換える設定
-
persist
:接続維持 -
replacedefaultroute
:PPP接続時にデフォルトルートを自動で置き換える設定。
実質的にこれによって3Gモデムでインターネット接続ができることになる。
cat << EOS | sudo tee -a /etc/ppp/peers/soracom_ak-020
persist
replacedefaultroute
EOS
書き換え後は以下のようになります。
# 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の設定もこちらになります。
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
書き換え後は以下のようになります。
# 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接続のテストをします。
sudo pon soracom_ak-020
AK-020のランプが、接続後待機状態の緑点灯⇒赤点灯⇒緑点滅(2Hz)になると、PPP接続完了です。
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接続を切断します。
sudo poff soracom_ak-020
3G-USBモデムのランプの緑点滅が、緑点灯になり、PPP接続が終了しました。
⑥ PPP接続用ネットワークインタフェースを作る
電源投入後、または3G-USBモデムをUSBポートに挿したタイミングで自動でPPP接続したいので、設定を作ります。
Raspberry Piに仮想のネットワークインタフェース wwan0
を用意し、PPP接続と紐づけます。
cat << 'EOS' | sudo tee -a /etc/network/interfaces
allow-hotplug wwan0
iface wwan0 inet ppp
provider soracom_ak-020
EOS
書き換え後は以下の通り。
# 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接続が開始します。
sudo ifup wwan0
3G-USBモデムの緑ランプが2Hz点滅するとPPP接続済み。
wwan0
ネットワークインタフェースを ifdown
することで、PPP接続が終了します。
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を再起動します。
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ドングル、とも言えますね。
sudo apt-get -y install autossh
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
sudo chmod 755 /etc/ppp/ip-up.d/10ssh-tunnel
/etc/ppp/ip-up.d/
の中に実行権限をつけたスクリプトを置いておくと、PPPで接続確立後に実行されますので、 autossh
によるSSHトンネルを掘る例です。
これをすると、3G電波だけでインターネットにつながっている Raspberry Pi
に外部ホストからリモートログインが実現できます。
slogin pi@localhost -p 10022 -o StrictHostKeyChecking=no
応用
GPSを搭載して、node.js
を使って AWS IoT
に JSON
をPubして、 DynamoDB
に現在位置をダダ記録するのはどうでしょう。
参考文献
- Raspberry Pi A+ (Raspbian wheezy) でAK-020を使ってSORACOMに自動接続する - Qiita
- Raspberry PiでUSBモデム挿入時にSORACOMへ自動接続する - Qiita
- Rasoberry Pi + SORACOM Air SIM ( L-02C , AK-020 ) の wvdial.conf 設定情報 - Qiita
- AK-020 を Raspbian で使う(とりあえず版) - Qiita
- Raspberry PI+docomo L-05A+SORACOM AirでUSBモデム自動起動 - Qiita
- L-02C でインターネット接続する方法: Linuxist の Debian-Ubuntu 拾い食い日記
脚注
-
Raspberry PiをSORACOM Airを利用する場合、
wvdial
というダイアラーを使う作例が多いですが、それは、本命の Linuxで一般的な標準パッケージppp
に含まれている、古式ゆかしいpon
poff
によるPPP接続Linuxで一般的な標準パッケージppp
に含まれている、古式ゆかしいpon
poff
によるPPP接続を作るときに利用するpppconfig
に不具合があり、PPP接続ができなかったため、代替方法としてwvdial
を選択してきたのだと思われます。今回pppconfig
を使った時の不具合とそれの解消方法が判明したので、pon
poff
によるPPP接続をします。 ↩ -
今回の作例で使う
SORACOM Air
は通信コスト的に安くはない(AWSを使うと国内クラウド基盤を使うより割高程度のニュアンスで高い)、定額SIMを使いたい場合は、定額SIMで作った場合の作例を用意していますからそちらを参照してください。SORACOM Air
を使った時の最大の利点は、IoT的な利用シーンでデバイスが盗難にあった時、SORACOM のコントロールパネルからSIMの停止ができる点ですので、IoTの実運用のプロダクトのときは使えばいいかと。 ↩ -
なお、PPP接続のための別のパッケージ
wvdial
でCHAP
認証で設定すると、正しく/etc/ppp/chap-secrets
にパスワードが設定されるため、以降CHAP
で設定していたpppconfig
で作った接続設定でもつながるようになります。Raspbianでの接続例はwvdial
での例ばかりなのはおそらくこれのせい。 ↩