CloudFrontを利用してパブリックIPv4のないEC2に接続する

# はじめに
AWSからCloudFrontに[VPC origins](https://aws.amazon.com/jp/blogs/aws/introducing-amazon-cloudfront-vpc-origins-enhanced-security-and-streamlined-operations-for-your-applications/)という機能が実装されましたので、早速試してみました。私の業務ではEC2を立てて様々なサービスを検証用にホストすることが多く、SSL/TLS通信をさせるためだけにEC2の手前にACMと連携したELBを立てたり、EIPを使ったりしています。この部分を今回の機能で置き換えできれば、ELBやEIP分のコストを削減できそうなので試してみました。

# 先に結論
ELBやEC2をパブリックサブネットに配置することなく、CloudFrontを通じてEC2上のサービスにアクセスできました。ホストしているサービスがCloudFrontのタイムアウト等の制限にかからないものであれば代用できそうです。

# 構成
今回は以下の環境で試してみました。EC2からのアウトバウンド用にNAT Gatewayを既に立てていますが、今回の検証には使用しません。EC2上にはDifyを立ててポート80でListenさせています。図には記載していませんが、IGWがVPCにアタッチされている必要があります。私の環境はSubnet自体が他のアカウントにあり、Resource Access Managerで共有されていますが、この環境でもVPC originsは問題なく使えました。
![overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717446/3e21a449-dc98-d4d7-bf62-2e7aadcda249.png)

# 手順
1. CloudFrontからの接続先となるVPCとEC2とSSL/TLS通信用のACMを用意します。この手順は割愛します。
1. CloudFrontコンソールからVPC Originsを作ります。
    1. 各項目を埋めて、「VPCオリジンを作成」を押下します。
        1. **Name:** ターゲットを識別しやすい名称にすると良さそうです。今回はdify-instanceにしました。
        1. **オリジンARN:** リストの候補ではELBは出てきましたが、EC2は出てきませんでした。EC2コンソールからARNをコピーしてそのままペーストします。
        1. **プロトコル:** 今回は対象インスタンス上でHTTP(80)のみListenしているので、HTTPを選択します。
1. CloudFrontディストリビューションを作成します。
    1. **オリジン**
        1. **Origin domain:** 2で作成したVPC Originがリストに表示されるので、選択します。
        1. **VPC origin domain:** EC2のプライベートドメイン名（例：`ip-xx-xx-xx-xx.ap-northeast-1.compute.internal`）を入力します。この値はEC2コンソールから確認できます。
        1. その他の項目は任意です。今回はデフォルト設定としました。
    1. **キャッシュビヘイビア**
        1. **ビューワープロトコルポリシー:** HTTPSのみとしたいので**Redirect HTTP to HTTPS**にします。
        1. **許可された HTTP メソッド:** 全て許可の**GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**にします。
        1. キャッシュポリシー: キャッシュさせたくないので**Cache policy and origin request policy (recommended)** の**CachingDisabled**を選択します。オリジンリクエストポリシーは**AllViewer**を設定します。
    1. **基本設定**
        1. 今回は**代替ドメイン名**と**Custom SSL certificate**だけ設定しました。
    1. その他
        1. IP制限をしたい場合はWAFも設定してください。今回は割愛しています。
1. SecurityGroupの設定を行います。
    1. VPCコンソールのSecurityGroup画面を確認するとCloudFrontと名のついたSecurityGroupが作成されていました。説明を確認すると「CloudFront configured SecurityGroup」と書かれていたのでVPC origins作成時に作られたようです。このSecurityGroupからのインバウンド許可ルールをEC2側のSecurityGroupに追加します。EC2上のサービスが80でListenしているのでポート80でこのソースSecurityGroupを許可します。

設定完了後は無事アクセスを確認できました。
![スクリーンショット 2024-11-25 17.03.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717446/7d51a4f6-bffa-e7a0-878a-d115e14626df.png)

# 気をつけるポイント
- EC2側でListenしていないポートを設定しないようにします。試しにEC2側でListenしていないHTTPSをVPC origin側でmatch-viewerを使って設定してみたところHTTPS通信は504エラーになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717446/23069c56-6d82-de50-1f45-186f7f7cf261.png)

- VPC originの場合、Response timeoutとKeepalive timeoutは変更できないようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717446/f8c46655-513e-4d93-bf04-5970624e3203.png)

- VPC originはCloudFrontに紐づけてしまうと変更ができないようです。新規作成して置き換えるか、一度外してから更新する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717446/75012d3d-a0b9-92e0-ac4b-7d92e267f751.png)

# 最後に
出たてホヤホヤの機能なので、まだ地雷は踏み抜けていないです。今回はDifyで試していますが、この構成でDifyが動作することを保証するものではありませんのでご注意ください。しばらく使ってみて踏んだら記事更新しようと思います。最後まで読んでいただきありがとうございました。