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

全人類が待ってたヤツ
2021.07.16

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

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

試してみる

VPC エンドポイントの作成

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

03-create-vpc-endpoint

セキュリティグループは適当なものを選択します。

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 Lambda などからメッセージを送る場合も NAT Gateway 無しで送れるようになるのでコスト観点でも嬉しいアップデートですね。

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