Greengrass V2のセキュアトンネルコンポーネントを試してみた

Greengrass V2のAWS提供コンポーネントにセキュアトンネルのものが追加されていましたので、試してみました。

セキュアトンネルってなに？は、このあたりが詳しいと思います。

<iframe src="//www.slideshare.net/slideshow/embed_code/key/4u2cej6GyA9Id7?startSlide=28" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/AmazonWebServicesJapan/aws-iot-236953554" title="デバイスの運用で使える AWS IoTサービスの紹介" target="_blank">デバイスの運用で使える AWS IoTサービスの紹介</a> </strong> from <strong><a href="//www.slideshare.net/AmazonWebServicesJapan" target="_blank">Amazon Web Services Japan</a></strong> </div>

　

Greengrassのセキュアトンネルコンポーネントを使うと、上図のSource側の`0. Localproxy アプリケーションをinstallしておく`の部分をやってくれると思えばよいかと思います。

# 環境

| 対象 | 環境 |
| --- | --- |
| 接続先 |  Raspberry Pi 4<br>Raspberry Pi OS Lite(2021-01-11)<br>Greengrass : v2.0.5 |
| 接続元 | Windows 10 Pro上のDockerコンテナ |

# 事前設定

## 接続先の環境設定

### Greengrassのインストール

公式サイトの[Quick installation](https://docs.aws.amazon.com/greengrass/v2/developerguide/quick-installation.html)や[このあたり](https://qiita.com/moritalous/items/5491a2d40f29fdc2086f)を参考にインストールします。

### セキュアトンネルコンポーネントのデプロイ

Greengrassメニューのコンポーネントを開きます。
パブリックコンポーネントの中に`aws.greengrass.SecureTunneling`があります。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/d9ddf5d3-5ace-845d-dd14-bac2ce88aa05.png)

詳細情報はこんな感じ。
デプロイボタンをクリックします。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/7bd53653-104b-b53c-9575-4938c6752081.png)

新しいデプロイを作成します。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/615085dd-d3fb-c98c-43a7-ff85c4c38cf3.png)

名前つけて、デプロイターゲットを指定します。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/7c0a5b15-a001-0188-e7c8-4509c46a363f.png)

デプロするコンポーネントとして、パブリックコンポーネントの中の「aws.greengrass.SecureTunneling」を選択します。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/506cfbae-1a31-f532-42bc-eefb58966f25.png)

コンポーネントの設定は特に特に指定しませんでした。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/c4e945b2-8587-2998-996b-e35f2d371e8e.png)

デプロイの詳細設定も指定しませんでした。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/fc1bf7ea-e4ae-6e75-2d3f-e2e4e2a01d01.png)

確認をして問題なければ、デプロイを開始します。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/47b07bd8-963c-bc27-714d-ef8e47743779.png)

しばらくするとデプロイされていることが確認できます。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/41e9e71f-d249-39d2-7a0a-c1f15b29e41f.png)

## 接続元の環境設定

### localproxyのビルド

接続元に`localproxy`というモジュールが必要です。localproxyはGitHubで公開されており、Dockerfileも提供されているので簡単にビルドができます。
https://github.com/aws-samples/aws-iot-securetunneling-localproxy

```terminal:Windows10
git clone https://github.com/aws-samples/aws-iot-securetunneling-localproxy
cd aws-iot-securetunneling-localproxy
docker build -t aws-iot-securetunneling-localproxy:latest .
```

環境によるとは思いますが、私の環境では完了するまでに50分ぐらいかかりました。

# セキュアトンネルの開始

## セキュアトンネルの作成

マネジメントコンソールに戻り、左の管理メニュー内のトンネルを選択します。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/ec8f1316-b1c6-9304-aaf9-e26c2ed2349a.png)

サービスに`SSH`、モノの名前でGreengrassを選択します。（大文字じゃないとだめかも？未確認）

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/e262d624-8f5a-43e9-0b30-5e61e8917bb2.png)

キャプチャを取り忘れましたが、次の画面でアクセストークンのファイルが2つダウンロードできます。このタイミングでしか入手できませんので忘れずダウンロードしてください。

## セキュアトンネルの開始（接続先）

接続先のセキュアトンネルを開始します。

`$aws/things/thing-name/tunnels/notify`に以下のメッセージをパブリッシュします。
※thing-nameは実際のモノの名前にします。

```json-doc
{
    "clientAccessToken": "destination-client-access-token", // ←先程入手したdestinationAccessToken.txtの内容
    "clientMode": "destination", // 固定と思われる
    "region": "ap-northeast-1", // AWSリージョン
    "services": ["SSH"] // 開始するサービス
}
```

## セキュアトンネルの開始（接続元）

先程作成したlocalproxyイメージを起動して、bashシェルにアタッチします。

```terminal:Windows10
docker run --name localproxy --rm -it aws-iot-securetunneling-localproxy:latest bash
```

あとで使うので、SSHクライアントをこのタイミングで導入しておきます。

```terminal:Windows10（Dockerコンテナ内）
apt update && apt install -y openssh-client
```

localproxyを起動します。フォアグラウンドで起動し続けるので`&`をつけて実行します。

```terminal:Windows10（Dockerコンテナ内）
./localproxy -r ap-northeast-1 -s 5555 -t [先程入手したsourceAccessToken.txtの内容] & 
```

## 確認

ここまでうまくいっていれば、マネジメントコンソール上でも接続元と接続先が「接続済み」の表示となります。

![ap-northeast-1.console.aws.amazon.com_iot_home_region=ap-northeast-1(iPad) (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/33f3e5dd-84c7-75fe-e359-ec4ce779171e.png)

## リモート接続

SSHの接続先をlocalproxy(localhost)宛にすると、Raspberry Piまで中継されて、Raspberry PiにSSH接続ができます。

```terminal:Windows10（Dockerコンテナ内）
root@fecabcfd8bba:/home/aws-iot-securetunneling-localproxy# ssh pi@localhost -p 5555
[2021-03-13T04:26:29.145928]{12}[info]    Accepted tcp connection on port 5555 from 127.0.0.1:46518
The authenticity of host '[localhost]:5555 ([127.0.0.1]:5555)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.        
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:5555' (ECDSA) to the list of known hosts.
pi@localhost's password: 
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;  
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Mar 13 04:05:24 2021 from 127.0.0.1

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux
pi@raspberrypi:~ $
```

すごく回りくどい感じですが、Windows上のDockerコンテナ内から、AWS IoT Coreを経由して、Greengrassが動作しているRaspberry PiにSSHをしています。

内部では`AWS IoT Device Client`というものを使っているようです。セキュアトンネル以外にも便利なもののようなので、またの機会に調査したいと思います。
https://github.com/awslabs/aws-iot-device-client

## リモート接続（コンテナ外からアクセスしたい場合）

Dockerの内部からではなく、WindowsからSSHしたい場合は、ローカルプロキシを以下のように起動すればOKです。
Dockerのパラメーターに`-p 5555:5555`を、localproxyのパラメーターに`-b 0.0.0.0`を追加しています。

```terminal:Windows10
docker run --name localproxy --rm -p 5555:5555 aws-iot-securetunneling-localproxy:latest ./localproxy -r ap-northeast-1 -s 5555 -b 0.0.0.0 -t [先程入手したsourceAccessToken.txtの内容]
```

# 価格

2021/3/13現在、東京リージョンでの価格は、開いたトンネル（開いたトンネル 1 つにつき）あたり`6.00USD`です。
** トンネルの最大継続時間：12 時間
** 最大トンネルスループット：100 KBps（800kbps）
https://aws.amazon.com/jp/iot-device-management/pricing/

# 参考サイト

https://docs.aws.amazon.com/greengrass/v2/developerguide/secure-tunneling-component.html
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/secure-tunneling-tutorial.html
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/agent-snippet.html
https://github.com/aws-samples/aws-iot-securetunneling-localproxy
https://github.com/awslabs/aws-iot-device-client