SQS向けのVPC Endpoint (Private Link)を利用するときの注意点です。特に、AWS CLIをご利用の方。
なお本ブログでは、下記のバージョンのAWS CLIで検証を行っています。(2019/03/03時点で最新)
[ec2-user@swx-bastion-l01 ~]$ aws --version aws-cli/1.16.116 Python/2.7.14 Linux/4.14.88-88.76.amzn2.x86_64 botocore/1.12.106
SQSのAPIエンドポイントには実は2種類あります。
かつて使われていたエンドポイント(以下、レガシーエンドポイント)と、新しいエンドポイント(以下、現行エンドポイント)です。
レガシーエンドポイント: ap-northeast-1.queue.amazonaws.com
現行エンドポイント: sqs.ap-northeast-1.amazonaws.com
2019/03/03現在、AWS CLIはデフォルトではSQSのレガシーエンドポイントを利用してしまいます。
これがVPC Endpointを利用してSQSに接続しようとしたときに、少し問題になります。
検証してみます。
とあるVPCに、SQSのInterface VPC Endpointを作成しました。
同じVPCにEC2をローンチします。セキュリティグループのアウトバウンド通信ではVPC内のローカル通信だけを許可します。これでこのEC2は、インターネットには出れないが、VPC内にあるVPC Endpointへはアクセスができる状態です。
nslookupで、レガシーエンドポイントと現行エンドポイントの名前解決をしてみます。
[ec2-user@swx-bastion-l01 ~]$ nslookup ap-northeast-1.queue.amazonaws.com Server: 192.168.0.2 Address: 192.168.0.2#53 Non-authoritative answer: Name: ap-northeast-1.queue.amazonaws.com Address: 54.240.225.157 [ec2-user@swx-bastion-l01 ~]$ nslookup sqs.ap-northeast-1.amazonaws.com Server: 192.168.0.2 Address: 192.168.0.2#53 Non-authoritative answer: Name: sqs.ap-northeast-1.amazonaws.com Address: 192.168.4.179 Name: sqs.ap-northeast-1.amazonaws.com Address: 192.168.3.59
レガシーエンドポイントを名前解決したときは、パブリックIPが返ってきていることが分かります。
一方で現行エンドポイントを名前解決したときは、VPC EndpointのプライベートIPが返ってきていることが分かります。
AWS CLIでSQSのコマンドを実行してみます。
[ec2-user@swx-bastion-l01 ~]$ aws --region ap-northeast-1 sqs list-queues Connect timeout on endpoint URL: "https://ap-northeast-1.queue.amazonaws.com/"
これはAWS CLIがデフォルトではレガシーエンドポイントを利用しようとしているため、パブリックIPに繋ぎに行こうとしてしまっており、タイムアウトしているのだと分かります。
ちなみに「 aws sqs send-message –queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/testqueue –message-body “Hello” 」のように、キューURLに現行エンドポイントが含まれているように見えてもAWS CLIだとレガシーエンドポイントに接続してしまいます。
ではAWS CLIさんに現行エンドポイントを使ってもらいましょう。
–endpoint-url オプションで現行エンドポイントを明示的に指定してあげます。
[ec2-user@swx-bastion-l01 ~]$ aws --region ap-northeast-1 sqs list-queues --endpoint-url https://sqs.ap-northeast-1.amazonaws.com { "QueueUrls": [ "https://sqs.ap-northeast-1.amazonaws.com/123456789012/test-queue" ] }
成功しました。
このように、現行エンドポイントへアクセスしようとしているため、VPC Endpoint経由でアクセスされたことが分かります。
またCloudTrailでAPIアクセス履歴を見ると、接続元IPがEC2のローカルIPアドレスで記録されていることも分かります。
※ListQueues APIはCloudTrailに記録されないため、PurgeQueue APIで試してみました。
{ (中略) "eventSource": "sqs.amazonaws.com", "eventName": "PurgeQueue", "awsRegion": "ap-northeast-1", "sourceIPAddress": "192.168.1.10", "vpcEndpointId": "vpce-01234567890123456" }
普通にパブリックなAPIエンドポイントからアクセスすると、このsourceIPAddressはEC2のElastic IPアドレスやNAT GatewayのIPアドレスになるはずです。
今回はVPC Endpointからしっかりアクセスできているので、VPC EndpointのIDまで記録されています。(上記例のIDは念のため適当な値にしています)
なお、AWS Tools for Powershellではデフォルトで現行エンドポイントを使うことも確認できました。
(念のため、お使いのCLI/SDKではどのような動きになるか、確認することを推奨いたします)