AWS IoT Core が VPC エンドポイントをサポートしました!

全人類が待ってたヤツ
2021.07.16

アツいアップデートが来ました。ついに AWS IoT Core が VPC エンドポイントをサポートしました! これで念願の「閉域網経由で AWS IoT Core と接続する」ことができるようになりました!!

対応リージョンは中国リージョンを除く全てのリージョンとのことなので、今すぐに東京リージョンでも利用することができます!!

注意事項 - 2022 年 07 月 27 日追記

本リリースの発表当時(2021 年 7 月 15 日)は、記事中の画面ショットのように作成するエンドポイントに対して「プライベートDNS名を有効にする」ことができました。 そのため、IoT Core のエンドポイントに対してプライベート IP でアクセスすることができました。

しかし、2022 年 7 月 27 日現在では「プライベートDNS名を有効にする」事ができません。 VPC 内のリソースからのプライベートアクセスやオンプレミス環境からの閉域接続経由で IoT Core にアクセスしたい場合は、Route53 の Private Hosted Zone を利用して VPCエンドポイントの名前解決を行う必要があります。
(閉域網経由の場合は、Route53 Resolover などを使って Private Hosted Zone で名前解決できるようにしてください)

具体的な構成については、下記も合わせてご参照ください。

また、他の接続パターンも知りたいという場合は、下記の資料も参考にしてください。

試してみる

VPC エンドポイントの作成

それでは簡単に動作確認してみたいと思います。早速 VPC のコンソールで エンドポイントを作成してみましょう。
下記のように AWS IoT を選択することができるようになっています。

03-create-vpc-endpoint

セキュリティグループは適当なものを選択します。
注意: 下記の画面ショットでは「プライベートDNS名を有効にする」にチェックが入っていますが、2022年7月時点ではエンドポイントを作成してもプライベートDNSレコードの作成はサポートされおらず、レコードは作成されないのでご注意ください

04-select-sg

今回は下記のように該当 VPC の CIDR (10.60.0.0/16)から全通信を許可するものを指定しました。

05-sg-rules

MQTT クライアントの作成

時間があればVPN接続した環境で試してみたかったですが、時間が無いので同じ VPC 上に MQTT クライアントとなる EC2 (Amazon Linux 2)を作成することにします。

適当なインスタンスタイプでサーバを作ったら MQTT クライアントアプリをインストールします。今回は mosquitto にしました。

sudo amazon-linux-extras install epel
sudo yum -y install mosquitto

なお、詳細は割愛しますが MQTT クライアントとして作成した EC2 はデバイス証明書で接続するので、事前に証明書類を作成して EC2 上の適当なところに保存しておいてください。

名前解決の確認

ここまでできたら、AWS IoT Core のエンドポイントに対して名前解決を確認してみます。下記のとおり確かに VPC 内のプライベートIP が返ってきました。

dig xxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com +short

10.60.3.26
10.60.4.138

Pub/Sub の確認

次に、MQTT で Pub/Sub 通信ができるかどうか確認してみます。せっかくなので tcpdumpでパケットもキャプチャしてみましょう。(tcpdump がインストールされていなければ sudo yum -y install tcpdumpでインストールしておきます)

最初に別のターミナルで パケットキャプチャしておきます。(-n オプションで tcpdump で名前解決を行いません)

sudo tcpdump -n -vv dst port 8883

これで全て準備ができました。試しに 適当なメッセージを Publish してみます。

mosquitto_pub \
--cafile AmazonRootCA1.cer \
--cert xxxxx-certificate.pem.crt \
--key xxxxxx-private.pem.key \
-h xxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com \
-p 8883 -q 0 -d \
-t 'iot/topic' \
-f sample.json \
-i myec2

Client myec2 sending CONNECT
Client myec2 received CONNACK (0)
Client myec2 sending PUBLISH (d0, q0, r0, m1, 'iot/topic', ... (36 bytes))
Client myec2 sending DISCONNECT

AWS コンソールのテストクライアントでメッセージを受け取ることができました!

06-subscribe-iot-core-test-client

パケットキャプチャの様子は下記のようになり、先ほど dig で確認した10.60.3.26 というプライベートIP に接続していることが分かります。
(注:EC2 インスタンスの IP は 10.60.3.50 です)

01-iot-core-vpc-endpoint-publish-tcpdump

今度は逆に AWS コンソールから Publish してみます。事前に EC2 側で該当トピック(iot/topic)を Subscribe しておきます。

mosquitto_sub \
--cafile AmazonRootCA1.cer \
--cert xxxxx-certificate.pem.crt \
--key xxxxx-private.pem.key \
-h xxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com \
-p 8883 -q 1 -d \
-t 'iot/topic' \
-i myec2

07-publish-iot-core-test-client

メッセージを Publish すると、次のように無事受け取る事ができました。

mosquitto_sub \
--cafile AmazonRootCA1.cer \
--cert xxxxx-certificate.pem.crt \
--key xxxxx-private.pem.key \
-h xxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com \
-p 8883 -q 1 -d \
-t 'iot/topic' \
-i myec2

Client myec2 sending CONNECT
Client myec2 received CONNACK (0)
Client myec2 sending SUBSCRIBE (Mid: 1, Topic: iot/topic, QoS: 1, Options: 0x00)
Client myec2 received SUBACK
Subscribed (mid: 1): 1

Client myec2 received PUBLISH (d0, q0, r0, m0, 'iot/topic', ... (32 bytes))
iot/topic {
  "message": "Hello VPC EC2"
}

パケットキャプチャの様子は下記のとおりです。

02-iot-core-vpc-endpoint-subscribe-tcpdump

最後に

まれに「オンプレミス環境から閉域網経由で AWS IoT Core にデータを送りたい」というリクエストを受けることがあったのですが、これからは気持ちよく回答できるようになりました!
VPC上のリソース(EC2やコンテナ)からメッセージを送る場合も NAT Gateway 無しで送れるようになるのでコスト観点でも嬉しいアップデートですね。

速報ブログになりますが以上です。