[アップデート] S3 インターフェースエンドポイントでプライベート DNS 名を使用できるようになりました

S3 向けのインターフェース型 VPC エンドポイント(PrivateLink)でプライベート DNS 名を使えるようになりました。オンプレミスから接続する際には Route 53 Resolover インバウンドエンドポイントを使用してください。VPC 上のアプリケーションがインバウンドエンドポイントを経由せずに名前解決した際は引き続きゲートウェイ型 VPC エンドポイントを使用できます。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンバンハ、千葉(幸)です。

S3 インターフェースエンドポイント(インターフェース型 VPC エンドポイント)でプライベート DNS 名を使用できるようになりました。

インターフェースエンドポイントを使用する際には「エンドポイント固有の DNS 名」「プライベート DNS 名」のいずれかを使用して名前解決を行います。これまで S3 インターフェースエンドポイントでは後者の「プライベート DNS 名」に対応していなかったのですが、今回のアップデートで使えるようになりました。

S3 向けの VPC エンドポイントには「ゲートウェイ型」「インターフェース型」の 2 種類があります。後者の「インターフェース型」はオンプレミス上のアプリケーションが S3 へのプライベートアクセスを行う際の利用が想定されています。

コストの観点から VPC 上のアプリケーションは前者の「ゲートウェイ型」を利用することが望ましく、単純にインターフェースエンドポイントの「プライベート DNS 名」が有効になるだけだと差し支えがありました。(VPC 上のアプリケーションからの通信もインターフェース型を経由してしまう。)

「Route 53 Resolver インバウンドエンドポイントを経由した名前解決の場合のみプライベート DNS 名を使用する」という条件付けをできるようにすることで、上記の問題を回避したようです。

まとめ

  • S3 インターフェースエンドポイントでプライベート DNS 名が有効にできるようになった
  • 有効化の際、「インバウンドエンドポイントのみ」オプションを有効化できる
    • 有効な場合:インバウンドエンドポイント経由で名前解決する場合のみプライベート DNS 名が有効になる
    • 無効な場合:当該 VPC から Route 53 Resolver を利用した名前解決はすべてプライベート DNS 名が有効になる
  • 「インバウンドエンドポイントのみ」オプションを有効化する場合、当該 VPC にゲートウェイ型の S3 向けエンドポイントが存在している必要がある
  • インターフェースエンドポイントを経由した通信はデータ処理量に応じて料金が発生するため、VPC 上のアプリケーションはインターフェースエンドポイントを経由しないよう気を付けよう

S3 向け VPC エンドポイント全体イメージ

ゲートウェイ型、インターフェース型それぞれのエンドポイントを経由した S3 向けの通信のイメージ図です。

S3 Interface Endpoint

ゲートウェイ型とインターフェース型の違い

おもな違いとして以下があります。

ゲートウェイ型 インターフェース型
経由する場合のクライアントから見た宛先 S3 パブリック IP アドレス インターフェースエンドポイントのプライベートIP アドレス
ルートテーブルでのルート登録 必要 不要
VPC 外からのアクセス できない できる
データ処理量に応じた料金 発生しない 発生する
設置時間に応じた料金 発生しない 発生する

(ゲートウェイ型を利用できる)VPC 上のアプリケーションがインターフェース型のエンドポイントを利用するメリットはありません。データ処理量に応じた料金が発生するためです。 *1あくまでインターフェース型はオンプレミスのアプリケーションなど、VPC 外からの S3 アクセスを想定したものになっています。

なお、2023/3現在の東京リージョンでの「データ処理量に応じた料金」は 1GB あたり 0.01 USD です。(一定量を超えると段階的に安くなります。)

インターフェースエンドポイントのプライベート DNS 名

インターフェースエンドポイントのプライベート DNS 名 を有効化すると、それに応じたサービス用のプライベートホストゾーンが自動で生成され、エンドポイントを配置した VPC に自動で関連付けられます。例えば東京リージョンで S3 向けのインターフェースエンドポイントで有効化すると、s3.ap-northeast-1.amazonaws.com.などのプライベートホストゾーンが作成されます。

よって、VPC 上から Route 53 Resolver(Amazon Provided DNS)を用いて当該サービスの名前解決を試みた場合、インターフェースエンドポイントのプライベート IP アドレスが返却されます。当該サービスを宛先とした通信はインターフェースエンドポイントのプライベート IP アドレスを宛先とした通信に置き換わります。エンドポイントに到達した通信は AWS PrivateLink を経由し、サービスのエンドポイントに到達します。

なお、プライベート DNS 名を利用する際には VPC で以下パラメータが有効になっている必要があります。

  • Enable DNS hostnames
  • Enable DNS support

VPC 外からの Route 53 Resolver の利用

VPC 外の環境から直接 Route 53 Resolver を参照することはできないため、オンプレミスのアプリケーションがプライベート DNS 名を使用したい場合は Route 53 Resolver インバウンドエンドポイントを経由した名前解決を行う必要があります。オンプレミス側では、端末の参照先 DNS サーバーで条件付きフォワーダーを設定し名前解決の向き先を変更する、などの対応が必要です。

「インバウンドエンドポイントのみ」オプション

S3 向けインターフェースエンドポイントでプライベート DNS 名を有効化する際、「インバウンドエンドポイントのみ」(Enable private DNS only for inbound endpoint)オプションを選択できます。

S3_Endpoint_private_dnsname

これを有効化することで、送信元に応じてゲートウェイ型とインターフェース型のどちらのエンドポイントを経由させるかをコントロールできます。

このオプションが有効な場合、Route 53 Resolver インバウンドエンドポイントを経由した名前解決、つまり VPC 外からの名前解決の場合のみプライベート DNS 名が機能します。

VPC 上のアプリケーションはインバウンドエンドポイントを経由せず直接 Route 53 Resolver を用いて名前解決できます。そこではパブリック DNS ゾーンへの問い合わせを通じて S3 サービスが持つグローバル IP アドレスが返却されるので、S3 宛の通信はゲートウェイ型の VPC エンドポイントを経由することになります。

インターフェース型の VPC エンドポイントでプライベート DNS 名を利用できるようにしながら、VPC 上のアプリケーションがそこを経由しないようにするという望ましい状態が実現できます。

エンドポイント固有の DNS 名

今回のアップデートが行われるまでは、S3 インターフェースエンドポイントを使用するためには「エンドポイント固有の DNS 名」を用いる必要がありました。

AWS CLI で言えば、以下のように実行時にオプションとして指定します。

$ aws s3 ls\
  --endpoint-url https://bucket.vpce-xxxxxxxx-xxxxxxx.s3.ap-northeast-1.vpce.amazonaws.com

この DNS 名はパブリック DNS ゾーンを通じて名前解決でき、プライベート IP アドレスが返却されます。プライベートホストゾーンのように限定された場所からしか名前解決できないわけではないので、オンプレミスの環境等からでも名前解決できます。

プライベート DNS 名を用いる場合と異なり明示的にエンドポイント URL を指定する必要があり、そこがネックになっていたケースもあるかと思います。今回のアップデートによりエンドポイント固有の DNS 名を使わなくても良くなりました。

S3 インターフェースエンドポイントのプライベート DNS 名を有効化してみた:準備編

今回は以下の構成で検証してみます。オンプレミスの環境を準備するのは大変なので、オンプレ相当の VPC を別に用意し、VPC ピアリング経由で接続します。図における左側の VPC は、そのまま左 VPC と呼びます。

S3 Interface Endpoint try

左 VPC には以下の S3 向け VPC エンドポイントを作成します。

  • ゲートウェイ型
  • インターフェース型
    • プライベート DNS 名 有効
    • 「インバウンドエンドポイントのみ」オプション有効

同じ VPC 上のアプリケーション、オンプレミス上のアプリケーションを想定し、以下のアクセスを行います。

# クライアント 参照先DNS 確認観点
A オンプレ想定端末 オンプレ想定 VPC の Route 53 Resolver IGW を経由して S3 アクセスしてブロックされること
B 左 VPC 上の EC2 インスタンス 左 VPC の Route 53 Resolver IGW を経由して S3 アクセスしてブロックされること
1 オンプレ想定端末 左 VPCの Route 53 Resolver インバウンドエンドポイント インターフェース型エンドポイントを経由して S3 アクセスできること
2 左 VPC 上の EC2 インスタンス 左 VPC の Route 53 Resolver ゲートウェイ型エンドポイントを経由して S3 アクセスできること

最終的に確認したい観点は、Route 53 Resolver インバウンドエンドポイントを経由した場合とそうでない場合とで S3 アクセス経路が変わるかどうかです。(#1,2)

今回は作業の都合上、EC2 インスタンスにパブリック IP アドレスを割り当てたいです。そうすると Internet Gateway を経由しての S3 アクセスも実現できてしまうため、#1,2 の試行時に意図した通りエンドポイントを経由しているか判別しづらくなります。そのため、本来の作業前に Internet Gateway 経由の場合はブロックされる、という確認をしておくことにしました。(#A,B) *2

もろもろの環境作成

特筆すべきことがないリソースの作成の詳細は割愛します。

左 VPC

  • VPC
    • IPv4 CIDR:172.31.0.0/16
    • DNS 解決:有効
    • DNS ホスト名:有効
    • DHCP オプションセット:デフォルト
  • S3 向けゲートウェイ型 VPC エンドポイント
    • エンドポイントポリシー:フルアクセス
  • EC2 インスタンス
    • 配置サブネット:パブリックサブネット
    • パブリック IP アドレス割当:有効
    • AMI:amzn2-ami-kernel-5.10-hvm-2.0.20230307.0-x86_64-gp2
    • SecuriryGroup:アウトバウンドフル開放
    • IAM ロールのポリシー:AmazonSSMManagedInstanceCore,AmazonS3FullAccess

EC2 インスタンスを配置したサブネットのルートテーブルには、S3 向けゲートウェイ型 VPC エンドポイントをターゲットとするルートが含まれています。

オンプレ想定 VPC

  • VPC
    • IPv4 CIDR:10.0.0.0/16
    • DNS 解決:有効
    • DNS ホスト名:有効
    • DHCP オプションセット:デフォルト
  • EC2 インスタンス
    • 配置サブネット:パブリックサブネット
    • パブリック IP アドレス割当:有効
    • AMI:amzn2-ami-kernel-5.10-hvm-2.0.20230307.0-x86_64-gp2
    • SecuriryGroup:アウトバウンドフル開放
    • IAM ロールのポリシー:AmazonSSMManagedInstanceCore,AmazonS3FullAccess

VPC ピアリング

  • ピアリング
    • リクエスタ VPC:左 VPC
    • アクセプト VPC:オンプレ想定 VPC
    • リクエスタ DNS 解決:無効
    • アプセプタ DNS 解決:無効

左 VPC、オンプレ想定 VPC ともに、EC2 インスタンスを配置したサブネットのルートテーブルではピアリングをターゲットとするルートを追加しています。

ピアリングでの DNS 解決は無効にしても、今回やりたいことに差し支えはありませんでした。

S3 バケット

chibayuki-hoge-hogeという名称のバケットを作成し、以下のバケットポリシーを設定しました。

{
    "Version": "2012-10-17",
    "Id": "VpcSourceIp",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::chibayuki-hoge-hoge",
                "arn:aws:s3:::chibayuki-hoge-hoge/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "43.207.xx.xx/32",
                        "13.114.xx.xx/32"
                    ]
                }
            }
        }
    ]
}

特定のグローバル IP アドレスからの S3 アクションは全て拒否する、という内容です。ここで指定しているグローバル IP アドレスは、先ほど作成した EC2 インスタンスに割り当てられたものです。

S3 インターフェースエンドポイント

左 VPC でインターフェースエンドポイントを作成します。

  • サービス名:com.amazonaws.ap-northeast-1.s3
  • タイプ:Interface
  • VPC:左 VPC
  • サブネット:左 VPC 内の任意のサブネット 1 つ
  • SecuriryGroup:
    • インバウンド:オンプレ想定 VPC の CIDR から tcp/443 を許可
    • アウトバウンド:ルールなし
  • エンドポイントポリシー:フルアクセス

エンドポイント作成後、「アクション」→「プライベート DNS 名を変更」からプライベート DNS 名を有効化します。

VPC_Management_Console_S3_Interface

なお、ここでEnable private DNS only for inbound endpointにチェックを入れる際、同一 VPC にゲートウェイ型の VPC エンドポイントが無いと変更の保存時に以下のエラーが表示されます。

プライベート DNS 名の変更中にエラーが発生しました

To set PrivateDnsOnlyForInboundResolverEndpoint to true, the VPC vpc-07ea4b9ce269fce6a must have a Gateway endpoint for the service.

変更の保存を実行し、しばらく待つとステータスが「使用可能」に遷移します。このような形でパラメータが確認できます。

VPC_Management_Console_S3_Interface_endpoint

画像では隠れてしまっていますが、「DNS 名」という箇所で払い出された DNS 名を確認できます。6つが並列で表示されていましたが、分類すると以下となります。

  • VPC エンドポイント固有の DNS 名
    • *.vpce-08626e2f9fe66d544-pqwwwe5h.s3.ap-northeast-1.vpce.amazonaws.com(Z2E726K9Y6RL4W)
    • *.vpce-08626e2f9fe66d544-pqwwwe5h-ap-northeast-1a.s3.ap-northeast-1.vpce.amazonaws.com(Z2E726K9Y6RL4W)
  • プライベート DNS 名
    • s3.ap-northeast-1.amazonaws.com(Z0960666CB8UTO89AVCK)
    • *.s3.ap-northeast-1.amazonaws.com(Z0960666CB8UTO89AVCK)
    • *.s3-control.ap-northeast-1.amazonaws.com(Z01589391DVUIOM0ZW5A0)
    • *.s3-accesspoint.ap-northeast-1.amazonaws.com(Z0553067ND4GDREFO1PD)

s3だけでなくs3-controls3-accesspointの DNS 名も払い出されていますね。

おまけ:インターフェースの IP アドレス

EC2 コンソールの「ネットワークインターフェース」から、生成されたエンドポイントに割り当てられた IP アドレスを確認できます。適当に「Endpoint」などでフィルタリングすれば出てきます。

今回は172.31.47.112が払い出されていました。

ENI_VPC_Endpoint

おまけ:プライベートホストゾーン

プライベート DNS 名を有効にすると、当該 VPC にプライベートホストゾーンが作成・関連付けされます。AWS CLI で確認可能です。

% aws route53 list-hosted-zones-by-vpc \
  --vpc-id vpc-07ea4b9ce269fce6a \
  --vpc-region ap-northeast-1
{
    "HostedZoneSummaries": [
        {
            "HostedZoneId": "Z104557319SN0DQJ3LPJT",
            "Name": "efs.ap-northeast-1.amazonaws.com.",
            "Owner": {
                "OwningService": "efs.amazonaws.com"
            }
        },
        {
            "HostedZoneId": "Z0553067ND4GDREFO1PD",
            "Name": "s3-accesspoint.ap-northeast-1.amazonaws.com.",
            "Owner": {
                "OwningService": "vpce.amazonaws.com"
            }
        },
        {
            "HostedZoneId": "Z01589391DVUIOM0ZW5A0",
            "Name": "s3-control.ap-northeast-1.amazonaws.com.",
            "Owner": {
                "OwningService": "vpce.amazonaws.com"
            }
        },
        {
            "HostedZoneId": "Z0960666CB8UTO89AVCK",
            "Name": "s3.ap-northeast-1.amazonaws.com.",
            "Owner": {
                "OwningService": "vpce.amazonaws.com"
            }
        }
    ],
    "MaxItems": "100"
}

OwningService が vpce.amazonaws.com となっており、カスタマーが管理できるものではありません。マネジメントコンソールからホストゾーン一覧を見ても確認できませんし、ホストゾーンの中のレコードセットを確認するもできません。

Route 53 Resolver インバウンドエンドポイント

左 VPC に作成していきます。

Route53Resolver_Console_Inbound_Endpoint-8882690

  • VPC:左 VPC
  • SecuriryGroup:
    • インバウンド:オンプレ想定 VPC CIDR から tcp/53,udp/53 を許可
    • アウトバウンド:ルールなし
  • エンドポイントのタイプ:IPv4
  • IP アドレス:左 VPC のサブネットから 2 つ選択し、その中で自動選択

このような形で作成できました。

Route53Resolver_Console_InboundEndpoint

インバウンドエンドポイント用の IP アドレスが 2 つ払い出されています。

S3 インターフェースエンドポイントのプライベート DNS 名を有効化してみた:動作確認編

準備が整ったので実行していきます。再掲すると、やりたいことは以下です。

S3 Interface Endpoint try

# クライアント 参照先DNS 確認観点
A オンプレ想定端末 オンプレ想定 VPC の Route 53 Resolver IGW を経由して S3 アクセスしてブロックされること
B 左 VPC 上の EC2 インスタンス 左 VPC の Route 53 Resolver IGW を経由して S3 アクセスしてブロックされること
1 オンプレ想定端末 左 VPCの Route 53 Resolver インバウンドエンドポイント インターフェース型エンドポイントを経由して S3 アクセスできること
2 左 VPC 上の EC2 インスタンス 左 VPC の Route 53 Resolver ゲートウェイ型エンドポイントを経由して S3 アクセスできること

A. オンプレ想定端末から IGW 経由のアクセス

オンプレ想定端末に Systems Manager セッションマネージャーで接続し操作していきます。

参照先の DNS はデフォルトの Route 53 Resolver になっています。(VPC CIDR 範囲 +2 の IP アドレスになっています。)

sh-4.2$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
options timeout:2 attempts:5
nameserver 10.0.0.2

S3 サービスエンドポイントの名前解決を試みるとグローバル IP アドレスが返却されます。

sh-4.2$ dig s3.ap-northeast-1.amazonaws.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> s3.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23014
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;s3.ap-northeast-1.amazonaws.com. IN    A

;; ANSWER SECTION:
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.16.14
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.17.72
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.68.88
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.136.184
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.137.36
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.200.12
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.0.60
s3.ap-northeast-1.amazonaws.com. 3 IN   A       52.219.8.18

;; Query time: 1 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Wed Mar 15 11:42:09 UTC 2023
;; MSG SIZE  rcvd: 188

特定のバケットを指定せず aws s3 ls コマンドを実行すると正常に結果が返ってきます。

sh-4.2$ aws s3 ls --region ap-northeast-1
2020-08-19 05:19:01 aws-athena-query-results-00000000000-ap-northeast-1
2021-09-24 09:46:51 aws-athena-query-results-00000000000-ap-northeast-3
2021-06-02 08:35:07 aws-cloudtrail-logs-00000000000-95b83418
...

バケットポリシーで送信元 IP アドレス制限をしているバケットにアクセスすると拒否されました。

sh-4.2$ aws s3api get-object test.txt\
>     --bucket chibayuki-hoge-hoge\
>     --key test.txt

An error occurred (AccessDenied) when calling the GetObject operation: Access Denied

S3 バケットの IP 制限は正常に機能していそうです。このバケットにアクセスしたければ IGW 以外の経路を辿る必要があります。

B. 左 VPC インスタンスから IGW 経由のアクセス

現状の構成のまま A と同じ操作を試みるとゲートウェイ型の VPC エンドポイントを経由することになるので、一時的にルートテーブルからルート除外した上で試行します。

参照先 DNS の確認。

sh-4.2$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
options timeout:2 attempts:5
nameserver 172.31.0.2

S3 サービスエンドポイントの名前解決。

sh-4.2$ dig s3.ap-northeast-1.amazonaws.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> s3.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29415
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;s3.ap-northeast-1.amazonaws.com. IN    A

;; ANSWER SECTION:
s3.ap-northeast-1.amazonaws.com. 1 IN   A       52.219.1.110

;; Query time: 0 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Wed Mar 15 12:38:54 UTC 2023
;; MSG SIZE  rcvd: 76

特定のバケットを指定しない aws s3 ls の実行。

sh-4.2$ aws s3 ls --region ap-northeast-1
2020-08-19 05:19:01 aws-athena-query-results-00000000000-ap-northeast-1
2021-09-24 09:46:51 aws-athena-query-results-00000000000-ap-northeast-3
2021-06-02 08:35:07 aws-cloudtrail-logs-00000000000-95b83418
...

特定バケットへの S3 アクセス。こちらもきちんと拒否されました。

sh-4.2$ aws s3api get-object test.txt\
>     --bucket chibayuki-hoge-hoge\
>     --key test.txt

An error occurred (AccessDenied) when calling the GetObject operation: Access Denied

IGW 経由の動作が確認ができたので、Sゲートウェイ型 VPC エンドポイント向けのサブネットルートテーブルのルートを元に戻しました。

1. オンプレ想定端末からインターフェースエンドポイント経由のアクセス

いよいよ本番です。

オンプレ想定端末に接続し、参照先の DNS を変更します。乱暴なやり方ですが、今回は/etc/resolv.confを直接編集しました。 *3

sh-4.2$ sudo vi /etc/resolv.conf
sh-4.2$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
options timeout:2 attempts:5
# nameserver 10.0.0.2
nameserver 172.31.36.53
nameserver 172.31.4.129

↑ Route 53 Resolver の代わりにnameserverに指定したのは左 VPC で作成した Route 53 Resolver インバウンドエンドポイントの IP アドレスです。

S3 のサービスエンドポイントを名前解決します。参照先がインバウンドエンドポイントであり、インターフェースエンドポイントのプライベート IP アドレスが返却されています。

sh-4.2$ dig s3.ap-northeast-1.amazonaws.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> s3.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33230
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;s3.ap-northeast-1.amazonaws.com. IN    A

;; ANSWER SECTION:
s3.ap-northeast-1.amazonaws.com. 60 IN  A       172.31.47.112

;; Query time: 2 msec
;; SERVER: 172.31.36.53#53(172.31.36.53)
;; WHEN: Wed Mar 15 12:47:28 UTC 2023
;; MSG SIZE  rcvd: 65

特定のバケットを指定しない aws s3 ls の実行はもちろん正常に完了。

sh-4.2$ aws s3 ls --region ap-northeast-1
2020-08-19 05:19:01 aws-athena-query-results-00000000000-ap-northeast-1
2021-09-24 09:46:51 aws-athena-query-results-00000000000-ap-northeast-3
2021-06-02 08:35:07 aws-cloudtrail-logs-00000000000-95b83418
...

インスタンスのグローバル IP アドレスを制限しているバケットへのアクセスを試みても正常に実行できました。

sh-4.2$ aws s3api get-object test.txt\
>     --bucket chibayuki-hoge-hoge\
>     --key test.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Tue, 04 Oct 2022 17:24:58 GMT",
    "ContentLength": 5,
    "VersionId": "bqZXg9SUCccFPn64JHwUG.jWFeP9TA8N",
    "ETag": "\"5d41402abc4b2a76b9719d911017c592\"",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

オンプレ想定端末から、左 VPC のインターフェースエンドポイントを経由してアクセスできていることが確認できました。

インターフェースエンドポイントのメトリクスでも見てみる

#1 の試行では、計 3 回 S3 コマンドを実行しました。

  1. aws s3 ls
  2. aws s3api get-object(失敗)
  3. aws s3api get-object

2 番目の aws s3api get-object(失敗)は上では省略しましたが、作業ディレクトリを誤りました。(作業ディレクトリに書き込みするパーミッションが足りなかった。その後ホームディレクトリに移動して再度 aws s3api get-object を実行した。)

sh-4.2$ aws s3api get-object test.txt\
>     --bucket chibayuki-hoge-hoge\
>     --key test.txt

[Errno 13] Permission denied: u'test.txt'

エンドポイントの詳細画面の「モニタリング」タブから関連メトリクスを確認でき、NewConnectionsとして合計 3 が記録されていることが分かります。

VPC_Management_Console_InterfaceEndpoint

メトリクスから見ても #1 の試行はインターフェースエンドポイントを経由していることが分かりました。

2. 左 VPC インスタンスからゲートウェイエンドポイント経由のアクセス

B とほぼ同じ内容になりますが、改めて確認していきます。このインスタンスが所属するサブネットのルートテーブルにはゲートウェイエンドポイントをターゲットとするルートが含まれています。

参照先 DNS の確認。左 VPC の Route 53 Resolver です。

sh-4.2$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
options timeout:2 attempts:5
nameserver 172.31.0.2

S3 サービスエンドポイントの名前解決。グローバル IP アドレスが返ってきます。

sh-4.2$ dig s3.ap-northeast-1.amazonaws.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> s3.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9257
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;s3.ap-northeast-1.amazonaws.com. IN    A

;; ANSWER SECTION:
s3.ap-northeast-1.amazonaws.com. 5 IN   A       52.219.152.24

;; Query time: 2 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Wed Mar 15 13:21:33 UTC 2023
;; MSG SIZE  rcvd: 76

特定のバケットを指定しない aws s3 ls の実行。もちろん成功します。

sh-4.2$ aws s3 ls --region ap-northeast-1
2020-08-19 05:19:01 aws-athena-query-results-00000000000-ap-northeast-1
2021-09-24 09:46:51 aws-athena-query-results-00000000000-ap-northeast-3
2021-06-02 08:35:07 aws-cloudtrail-logs-00000000000-95b83418
...

インスタンスのグローバル IP アドレスを制限しているバケットへのアクセス。正常に実行できました。

sh-4.2$ aws s3api get-object test.txt\
>     --bucket chibayuki-hoge-hoge\
>     --key test.txt
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Tue, 04 Oct 2022 17:24:58 GMT",
    "ContentLength": 5,
    "VersionId": "bqZXg9SUCccFPn64JHwUG.jWFeP9TA8N",
    "ETag": "\"5d41402abc4b2a76b9719d911017c592\"",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

本当にインターフェースエンドポイントを経由していない?

IP 制限をかけているバケットにもアクセスできたため IGW を経由していない、というのは明らかです。念のためインタフェースエンドポイントを経由している可能性を排除しておきたいです。他にもやりようある気はしますが、今回は以下観点から「可能性なし」と判断しています。

  • インターフェースエンドポイントのSecuriryGroupで左 VPC CIDR からのインバウンドを許可していない
  • インターフェースエンドポイントのメトリクスが #2 の試行後に増えていない
  • 先行の名前解決の時点でグローバル IP アドレスが返ってきている

ともかく、S3 インターフェースエンドポイントでプライベート DNS 名を有効化し、Resolver インバウンドエンドポイントを参照するかどうかでゲートウェイ型/インターフェース型を振り分ける挙動が確認できました。

終わりに

S3 インターフェースエンドポイントでプライベート DNS 名を有効化できるようになった、というアップデートでした。

過去に「なんで S3 向けだけ使えないんだろう」と疑問に思い頑張って調べたことがありました。

「VPC 上のアプリケーションにまで不要にインターフェースエンドポイントを経由させないためだろう」と思っていたので、「インバウンドエンドポイントのみ」というオプションを用意することでそこに対応してきたのが面白いな、と感じました。

なお、今回のアップデートによって S3 インターフェースエンドポイントの用途が変わるわけではありません。引き続きオンプレミスのアプリケーションなど VPC 外から S3 へのプライベートアクセスをさせたい時にだけ使うものです。すでに使っている・これからそういった用途で使うか検討している、という場合に少し便利になった、という位置付けで捉えてください。

個人的にはとても面白みを感じるアップデートだったので、何らか参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考

脚注

  1. それに加え、帯域幅の観点もあります。正確なソースが見つけられていないのですが、帯域幅もインターフェース型の方が小さいことが予想されます。
  2. 一通り試し終わった後に気づいたのですが、「特定の VPC エンドポイントを経由した場合のみアクセスを許可」という書き方ができる条件キーがある気がするので、そちらを使った方がシンプルに検証できた気がします。
  3. 直接編集しても再起動などで内容が戻ってしまうので検証以外では有効ではないやり方です。そもそも本来的な用途で考えると端末で直接向き先を変えるよりは端末の参照先の DNS サーバーでフォワードさせるのが一般的だと思います。今回は検証なので思いっきり手を抜きました。