【AWS】AWS PrivateLink for Amazon S3　～AWS Client VPN と組み合わせて、オンプレ環境からS3に直接接続～

# はじめに
[2021/2/3のアップデート](https://aws.amazon.com/jp/about-aws/whats-new/2021/02/amazon-s3-now-supports-aws-privatelink/)で、インターフェイス型のS3　VPCエンドポイントがリリースされました。
これにより、プロキシサーバ無しで閉域（DirectConnect、VPN）経由でS3利用が可能になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/1e2af7d0-69cc-c495-db10-8cbbd277ff2d.png)

上記図引用元：[Amazon S3 and interface VPC endpoints (AWS PrivateLink)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html)

ということで、実際にやってみたいと思います。
今回は、DirectConnect環境は準備できなかったので、AWS ClientVPNと組み合わせて環境を準備し、
オンプレミス環境（Windows Subsystem for Linux (WSL1)にAWS CLIインストールしたもの）から、
PrivateLink経由でのS3アップロードをテストしてみました。
なお、AWS ClientVPNの構築部分は、[以前の記事](https://qiita.com/taka-s_999/items/9fba585ac6e946cdb50d)を参考にして構築しておりますが、今回改めては触れていません。

```:AWS_CLI　Version
$ aws --version
aws-cli/2.0.17 Python/3.7.3 Linux/4.4.0-19041-Microsoft botocore/2.0.0dev21
```

# PrivateLink for Amazon S3

- PrivateLinkとは、AWSへのAPIアクセスをインターネットを経由せずに行えるインターフェースタイプのVPCエンドポイントです。<br>
VPCエンドポイントって何よ、というのは以下ユーザーガイド参照。

> VPC エンドポイントは、VPC およびサポートされている AWS のサービスと、AWS PrivateLink を利用した VPC エンドポイントサービスとの間のプライベート接続を可能にします。VPC エンドポイントは、インターネットゲートウェイ、NAT デバイス、VPN 接続、または AWS Direct Connect 接続を必要としません。VPC のインスタンスは、サービスのリソースと通信するためにパブリック IP アドレスを必要としません。VPC と他のサービス間のトラフィックは、Amazon ネットワークを離れません。

引用元：[VPC エンドポイント　ユーザーガイド](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-endpoints.html)


# やってみる（環境構築）
AWSClientVPN経由でローカル環境から、VPCからPrivateLink経由でのS3アクセスする構成を作成しました。
PrivateLink for S3 ではプライベート DNS 名は利用できないため、
今回は、Provided DNSを使うパターン（パターン①）と、
インターネット上のパブリックDNSを使う場合(パターン②)の2通り試してみました。

なお、今回パターン②で、インターネット接続については、
NATゲートウェイ配置しているPublicSubnetのルートテーブルで、無理やり制御しているのですが、
もし、実際に運用する場合はここで制御する方がいいよ！みたいなのがあれば、コメント頂けると大変ありがたいです。

## 環境構築（パターン①：Amazon Provided DNSを使用する）
### 全体構成（アーキテクチャ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/eb49efea-2e7a-0682-53d6-dd7ccc11c4a2.png)

### ①-1.PrivateLink for S3　エンドポイントの作成
- VPC 管理コンソールから [エンドポイント] - [エンドポイントの作成] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/c3f40688-abd7-272f-5ec6-7fcaeb406b53.png)

- エンドポイントの作成でサービスカテゴリに AWSサービス を選択し、s3 で検索すると Gateway および Interface 2つのタイプが見つかりますので、 Interface を選択します。
エンドポイントを作成する VPC および AZ を選択します。
※インターフェース型のエンドポイントは AZ ごとに 0.01 USD の料金が発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/3a14b803-5271-74e5-b42c-b417029f1685.png)

- セキュリティグループを選択しPrivateLinkのENIに割り当て、 [エンドポイントの作成] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/6ce764a2-3feb-aed2-66fb-63896c2b4bea.png)

---
**メモ**
※セキュリティグループ周りについて、自分の不勉強で少しハマりました。

- セキュリティグループについて、本構成で**デフォルトセキュリティグループを選択すると通信できなくなります。**
- 理由として、デフォルトセキュリティグループは、特徴として、ソースに自身のセキュリティーグループが指定されているからです。<br>
これは、デフォルトセキュリティグループが指定されたインスタンスからのインバウンド通信のみ許可する という意味になりますので、今回の構成では別のセキュリティグループを作成しましょう（HTTPS：443の通信を許可してあげればOKです。）

参考：[AWSのセキュリティグループの許可ソースにセキュリティグループを設定するパターンとは](https://ent.iij.ad.jp/articles/1486/)

---


- エンドポイントのステータスが保留から使用可能になれば、作成完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/bbfc97fe-1230-fba1-4993-25ce6689df35.png)

### ①-2.Client VPNエンドポイント　DNSサーバー設定
- Client VPN エンドポイントの変更画面より設定を行います。<br>[ DNS サーバーを有効にする ] にチェックを入れ、指定する DNS サーバーの IP アドレスを入力します。
- 今回は、Amazon Provided DNS(VPC CIDRの末尾を.2 にした値)を設定します。	
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/31722dc5-9c2d-4b42-1ce1-81c6dffb632b.png)

###  ①-3.CS3へのアクセス確認
- AWS ClientVPNに接続した後、インターネットに接続できないことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/8fed1a8e-3fad-2e3b-b3a5-9051573a4613.png)

- PrivateLink for S3 ではプライベート DNS 名が利用できまないため、エンドポイント固有の DNS 名を利用する必要があります。
①-1で確認した、S3エンドポイント固有のDNS名を利用します。
ローカルPCで名前解決すると、プライベートIPが返ってくることが確認できます。

```shell
$  dig vpce-[DNS名].s3.ap-northeast-1.vpce.amazonaws.com +short
10.0.0.179
```

また、AWS CLIにてエンドポイントURLを—endpoint-url パラメータとして指定し、バケット一覧を取得出来ていることが確認できました。

```shell
$  aws s3 vpce-[DNS名].s3.ap-northeast-1.vpce.amazonaws.com +shortaws s3 --endpoint-url https://bucket.vpce-[DNS名].s3.ap-northeast-1.vpce.amazonaws.com --region ap-northeast-1 ls
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/4b2a7460-5164-ffdf-d1cd-f42507d050c8.png)

**メモ**
アクセスするS3が存在するリージョンについて、--regionパラメータとして指定してあげましょう。
参考：[[AWS] VPC Endpoint で S3 にアクセスするときはリージョン指定に注意が必要な件](https://dev.classmethod.jp/articles/s3-region-with-vpc-endpoint/)

- 次に、特定のバケットに対しての10Mのファイル（10M.dumy）をアップロードを試してみます。<br>
まず10MBのダミーファイルを作成します。

```shell
$  dd if=/dev/zero of=10M.dumy bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.256005 s, 41.0 MB/s
coralreaf@coralreaf-sheepwing:~$ ls -lh | grep 10M
-rwxrwxrwx 1 coralreaf coralreaf  10M Feb 22 21:24 10M.dumy
$  ls -lh | grep 10M
-rwxrwxrwx 1 coralreaf coralreaf  10M Feb 22 21:24 10M.dumy
```
- 作成したダミーファイル（10M.dumy）を、S3バケット（coralreaf-dev-data）にアップロードします。

```shell
$  aws s3 --endpoint-url https://bucket.vpce-[DNS名].s3.ap-northeast-1.vpce.amazonaws.com --region ap-northeast-1 cp 10M.dumy s3://coralreaf-dev-data/
```

- マネジメントコンソールで確認します。
- ダミーファイル（10M.dumy）が対象S3バケット（coralreaf-dev-data）にアップロードされていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/f27b5328-82ff-a5e9-87e8-17b2ef8d3606.png)

## 環境構築（パターン②：パブリックDNSを使用する）
### 全体構成（アーキテクチャ）
今回はNATゲートウェイを配置したPublicSubnetのルートテーブルで、パブリックDNS(8.8.8.8)宛ての通信のみに制御しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/041aaef5-7476-ad16-498c-c430e9b5c36b.png)

### ②-1.PrivateLink for S3　エンドポイントの作成
- PrivateLink for S3　エンドポイントの作成手順はパターン①と同様ですので、パターン①の手順をもとに作成します。

### ②-2.Client VPNエンドポイント　DNSサーバー設定
- Client VPNエンドポイント　のDNSサーバーのアドレスを、GoogleパブリックDNSのアドレス（8.8.8.8）に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/849b7ee0-6e24-6d04-2a80-73d2e1fcaae7.png)

### ②-3.Publicサブネットのルートテーブル編集
- NATゲートウェイが配置されているPublicサブネットのルートテーブルについて、デフォルトルートを削除して、 GoogleパブリックDNSのアドレス（8.8.8.8）宛ての通信のみ設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/20b87f3e-4655-4654-fac7-d6d824359541.png)

- AWS ClientVPNに接続した後、インターネットに接続できないこと(ping 1.1.1.1)、また、パブリックDNSに接続出来ること(ping 8.8.8.8)を確認します。<br>ローカルPCでS3エンドポイント固有のDNS名の名前解決して、プライベートIPが返ってくることも確認し、<br>AWS CLIにて、S3バケット一覧を取得出来ていることについても、確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955507/777fa43d-4306-a6d8-0ede-c0de382df95d.png)


# 最後に
今回、セキュリティグループ周りで結構ハマってしまい、解決するまで時間かかってしまいました。
ただ上手くいかないと、色々調べたり、試したり、もがいている中で色々な事を学ぶことが出来るので、
やはり自分で手を動かすと得られるものが大きいなと感じました。
これからも色々なAWSサービスについて、出来るだけ自分で試していきたいと思います。

※今回でいうと、[AWS Loft](https://aws.amazon.com/jp/start-ups/loft/tokyo/)を初めて利用させてもらったり、VPC ReachabilityAnalyze使ってみたり、
自分の中で初めて触れるものも多く、とても勉強になりました。



# 参考にさせていただいた記事：
* [[速報！] オンプレミスからプライベートネットワークでのアクセスが可能に！PrivateLink に Amazon S3 が追加されました(DevelopersIO)](https://dev.classmethod.jp/articles/private-link-for-s3/)
* [DirectConnectからS3に直結！「AWS PrivateLink for Amazon S3」を試してみた(DevelopersIO)](https://dev.classmethod.jp/articles/privatelink-for-amazon-s3/)
* [AWS PrivateLink for Amazon S3を分かりやすく解説してみる(serverworks)](https://blog.serverworks.co.jp/privatelink-for-amazon-s3_)
* [AWS Client VPN に接続したら名前解決ができなくなったのでカスタム DNS サーバーとは何かを調べ直してみた(DevelopersIO)](https://dev.classmethod.jp/articles/aws-client-vpn-customdnsserver/)