AWS IoT セキュアトンネリングを使ってローカルのRaspberry Piにリモートから接続してみた
まいど、大阪の市田です。
今回は表題のとおりですが、AWS IoT セキュアトンネリングを使ってローカルにあるRaspberry Piにリモートから接続してみたいと思います。
構成
今回の構成のポイントは以下です。
- Raspberry Piは外部から直接アクセスできないローカル環境にあります。
- Raspberry Pi上でWebサーバを稼働させます。
- このWebサーバは
localhost
に対してのみListenするようにします - このWebサーバで稼働しているサンプルページに、EC2からブラウザで接続します。
この構成に利用した各種リソースの詳細は下記になります。
- EC2
- OS:Amazon Linux 2
- ブラウザ:Chromium
- VNC:tigervnc-server
- Raspberry Pi
- 筐体:Raspberry Pi 3B +
- OS:Raspbian Stretch
- 最後のリリースである
2019-04-08
を使いました
- 最後のリリースである
色々と組み合わせを試してみましたが、Raspbian Buster
では途中でコンパイルエラーとなり、インストールできなかった為、Raspbian Stretch
を利用しています。
そのため、筐体も「Raspberry Pi 3B +」で試しています。
環境構築
以前の記事の通り、AWS IoT セキュアトンネリングには、接続する双方でlocalproxyアプリケーションを使います。
まずは、このlocalproxyのインストールに必要な環境を作っていきたいと思います。
必要な要件等は以前の記事を御覧ください。
Github上のREADMEにある通り、依存関係のあるビルドディレクトリdependencies
を作成して、そこで作業を行っていきます。
mkdir dependencies cd dependencies
注意事項
必要に応じてRaspberry Piでsudo apt update
を実行してリポジトリを更新おくべきですが、apt upgrade
も行うと以後の作業時にコンパイルが失敗します。
これは環境に依存する可能性がありますが、下記よりダウンロードしたイメージではProtobuf
のインストールが失敗してしまいました。
Index of /pub/raspberrypi/raspbian/images
調査しましたがcmakeのパッケージ、またはバージョンに依存しているようで、関連するissueも起票されているようです。(確定情報ではありませんのでご注意ください)
似たような原因と思われるissueもあり、色々と試してみましたが現時点(2020年2月11日時点)では、まだ解決できていません。また、Raspbian Buster
でも同様で、唯一「Raspberry Pi 3B+ と Raspbian Stretch」の組み合わせ でlocalproxyがインストールできました。
もしRaspberry Piで試してみたい方がいらっしゃれば、まずはStretch
にてapt upgrade
しない状態で試してみて頂ければと思います。
Zlibダウンロードとインストール
zlibはapt
でインストールできるものを利用します。
sudo apt install zlibc
Boost依存関係のダウンロードとインストール
Githubの手順にある通りで問題なくインストールできました。
ただし、「Raspberry Pi 3B +」である為、./b2 install
の完了に2時間ほどかかりました。
wget https://dl.bintray.com/boostorg/release/1.69.0/source/boost_1_69_0.tar.gz -O /tmp/boost.tar.gz tar xzvf /tmp/boost.tar.gz cd boost_1_69_0 ./bootstrap.sh sudo ./b2 install
Protobuf依存関係のダウンロードとインストール
ここも特に詰まることなくインストールできました。しかし先程と同様にmake
が完了するまでに、また2時間ほどかかりました。
cd ~/dependencies wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-all-3.6.1.tar.gz -O /tmp/protobuf-all-3.6.1.tar.gz tar xzvf /tmp/protobuf-all-3.6.1.tar.gz cd protobuf-3.6.1/ mkdir build cd build cmake ../cmake make sudo make install
Catch2テストフレームワークのダウンロードとインストール
ここも時間が2時間ほどかかりますが、問題なく完了できました。
cd ~/dependencies git clone https://github.com/catchorg/Catch2.git cd Catch2 mkdir build cd build cmake ../ make sudo make install
ローカルプロキシのダウンロードとビルド
順調に進んでいましたが、今回の作業でcmake
が失敗し、次のようなエラーメッセージが出ていました。
CMake Error at /usr/share/cmake-3.7/Modules/FindPackageHandleStandardArgs.cmake:138 (message): Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIR)
ということで、libssl-dev
をインストールします。
sudo apt install libssl-dev
再度、localproxyのインストールを実行して無事に完了しました。
cd ~/dependencies git clone https://github.com/aws-samples/aws-iot-securetunneling-localproxy cd aws-iot-securetunneling-localproxy mkdir build cd build cmake ../ make
確認
事前準備
localproxyアプリケーションがインストールできたので、動作確認を行います。
早速、AWSIoTPythonSDK
をRaspberry Piにインストールしたいところですが、以前紹介した「IoTエージェント」で使っているsubprocess.run
は「Python 3.5」以上である必要があります。
Raspbian StretchのデフォルトはVer2系のPythonであるため、python3をインストールしておきます。
(仮想環境で用意することも考えましたが、動作確認を優先するため、python3をそのままインストールしました)
sudo apt install python3
次にSDKをインストールします。
sudo pip3 install AWSIoTPythonSDK
動作確認用のWebサーバを準備
前回はSSHアクセスを試したので、今回はlocalhostで起動するWebサイトにアクセスできるかどうか試してみたいと思います。
そのため、Raspberry Pi上にWebサーバを立てます。
sudo apt install apache2
デフォルトだと全公開でListenするので、/etc/apache2/ports.conf
を編集します。
Listen 80 ↓ Listen localhost:80
netstat
で確認した状態が下記です。localhostのみListenしていることが分かります。
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN 4350/apache2
トンネルを開く
Raspberry Pi側の下ごしらえは終わったので、AWS CLIやマネージメントコンソールからトンネルを開きます。
(トンネルを新たに開くと6ドルの課金が発生するので乱発には注意しましょう)
aws iotsecuretunneling open-tunnel \ --destination-config thingName=TunnelTestDevice,services=http
IoTエージェント起動
次に、ラズパイ上にIoTエージェントを用意して起動します。エージェントスクリプトは以前EC2で利用したものと同じものになります。
ただし今回はlocalhostで稼働するWebサイトにアクセスしたいので、スクリプトを一部修正します。(-d
オプションの指定箇所)
subprocess.run([ "/home/ec2-user/aws-iot-securetunneling-localproxy/build/bin/localproxy", "-t", json_message['clientAccessToken'], "-r", "ap-northeast-1", "-d", "localhost:22" ]) ↓ subprocess.run([ "/home/ec2-user/aws-iot-securetunneling-localproxy/build/bin/localproxy", "-t", json_message['clientAccessToken'], "-r", "ap-northeast-1", "-d", "localhost:80" ])
また、このRaspberry Piを「IoTレジストリ」に登録して各種証明書をラズパイ上に保存しておきます。
(モノの登録や証明書のダウンロードなどの作業内容は割愛致します)
準備ができたらエージェントを起動させます。
python3 IotAgent.py \ --endpoint xxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com \ --rootCA ../cert/rootCA.pem \ --cert ../cert/xxxxxxxxxx-certificate.pem.crt \ --key ../cert/xxxxxxxxxx-private.pem.key
アクセストークンをPublishしてlocalproxy起動
トンネルを開いたときに取得できるアクセストークン(destinationAccessToken
)をマネジメントコンソールからPublishして、IoTエージェントからlocalproxyを起動させましょう。
以前と同じIoTエージェントをそのまま使っているので、以前と同じトピック名「$aws/things/TunnelTestDevice/tunneling/notify
」にPublishします。
{ "clientAccessToken": "destinationAccessTokenの中身" }
下記のようなメッセージがRaspberry Pi上で確認できればOKです。
Successfully established websocket connection with proxy server: wss://data.tunneling.iot.ap-northeast-1.amazonaws.com:443
接続元EC2の準備
接続元に使うEC2は前回と同じインスタンスを利用します。ただし、今回はグラフィカルに確認してみたかったのでAmazon Linux 2にGUI環境をインストールしました。
Amazon Linux 2へのGUI環境の構築は下記を参考にして頂ければと思います。
- Amazon Linux 2 を実行している Amazon EC2 インスタンスへのグラフィカルユーザーインターフェイス (GUI) のインストール
- Amazon Linux 2 にデスクトップ環境(MATE)を入れてみた | Developers.IO
次に、このEC2にブラウザ(chromium)をインストールします。
sudo amazon-linux-extras install epel sudo yum install chromium
接続元ローカルプロキシの起動
これでEC2側の環境整理が完了しましたので、接続元となるlocalproxyを起動させます。
今回は8080ポートを指定して起動させてみました。
$ ./localproxy -r ap-northeast-1 -s 8080 -t <sourceAccessTokenの中身>
ブラウザで動作確認
これで全ての準備が完了しました!
それでは、EC2からRaspberry Pi上のWebページにアクセスしてみましょう!
まずは、手元のPCからEC2にVNCで接続します。私はMacを利用しているので、MacのFinderを使って、EC2インスタンスにVNC接続しました。接続できたらブラウザを起動します。
localhost:8080
をブラウザでアクセスしてみると、Raspberry Pi上のWebページを表示させることができました!
最後に
少々導入が手間ですが、メンテナンス用途などに限れば、AWSのサービスだけでセキュアにデバイスにアクセスできるのは便利だと思います。
参考ページ
- AWS IoT セキュアトンネリング - AWS IoT
- aws-samples/aws-iot-securetunneling-localproxy: AWS Iot Secure Tunneling local proxy reference C++ implementation
- Introducing Secure Tunneling for AWS IoT Device Management, a new secure way to troubleshoot IoT devices | The Internet of Things on AWS – Official Blog
- ファイアウォールを超えてデバイスに接続! AWS IoTセキュアトンネリングを試してみた | Developers.IO
- AWS IoT セキュアトンネリングの「ローカルプロキシ」をAmazon Linux2にインストールする | Developers.IO
余談
EC2では各作業がサクサクと進んだのですが、Raspberry Piの場合だと、それぞれのインストールに非常に時間がかかりました。また、最新のRaspbian(Buster)で動くと思っていたのですが、色々と試してみてもインストールできず何度も試してみたので更に時間がかかってしまいました。
そのため、夜にスタートさせたまま寝て翌朝に作業再開ということを何日か繰り返しました…
Busterで接続できない点については、今後も調査を継続していきたいと思います。