Open20

1つのCloudFront ALB EC2で複数のホスト(サイト)を扱いたい

hirenhiren

複数の CloudFront Distribution ー 複数の ALB ー 複数の EC2 で構成する方がシンプルで良いが、費用面などの要因から全てのサービスを単一リソースで作成しなければいけない場合、可能なのか?

hirenhiren

#検証

環境

$ ec2-metadata --ami-id
ami-id: ami-090d95e264aea197c
$ cat /etc/system-release
Amazon Linux release 2023.5.20241001 (Amazon Linux)
$ uname -a
example.ap-northeast-1.compute.internal 6.1.109-118.189.amzn2023.aarch64 #1 SMP Tue Sep 10 08:58:40 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux

CloudFront ⇒ ALB ⇒ EC2 間の Security Group 設定は適切に行われている前提
ドメインのレコード設定や、ACMの証明書取得も一部割愛します

hirenhiren

複数ドメインのサイトを扱えるように、httpd に VirtualHost の設定を追記する

/etc/httpd/conf/httpd.conf
<VirtualHost *:80>
  ServerName hoge.example.com
  ServerAlias example.com *.example.com # CloudFront ⇒ ALB 間で Host ヘッダーを転送する場合は不要
  DocumentRoot /var/www/hoge
</VirtualHost>

<VirtualHost *:80>
  ServerName huga.example.org
  ServerAlias example.org *.example.org # CloudFront ⇒ ALB 間で Host ヘッダーを転送する場合は不要
  DocumentRoot /var/www/huga
</VirtualHost>

https://httpd.apache.org/docs/current/ja/vhosts/name-based.html

hirenhiren

アクセスログにアクセス元ホスト名が出力されるようデフォルト設定に追記修正

/etc/httpd/conf/httpd.conf
<IfModule log_config_module>
-    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    CustomLog "logs/access_log" combined
</IfModule>

https://httpd.apache.org/docs/current/ja/mod/mod_log_config.html

hirenhiren

バーチャルホストの各ホストにページを作成

# mkdir /var/www/hoge
# mkdir /var/www/huga
# echo "hoge.example.com" > /var/www/hoge/index.html
# echo "huga.example.org" > /var/www/huga/index.html
hirenhiren

設定に問題が無い事を確認して再起動(or 停止してたら起動)

# apachectl configtest
Syntax OK
systemctl restart httpd
hirenhiren

ALB の Host ヘッダー保持設定を設定する

ロードバランサー>属性>パケット処理>ホストヘッダーを保持 を オン に設定

ALB Attributes

hirenhiren

ALB の HTTPS リスナーの証明書リストに複数ドメイン分の ACM 証明書を追加する

ロードバランサー>リスナーとルール>対象のHTTPSリスナー>SNI の SSL 証明書を追加する

リスナーとルール

対象の証明書を全て選択して「保留中として以下を含める」ボタンをクリック

addACM

「保留中の証明書を追加」ボタンをクリック

addSNI

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-update-certificates.html#add-certificates

hirenhiren

複数のドメイン名を別の名前として持つ証明書をバージニア北部リージョンの ACM で1つだけ作成する
キーアルゴリズムは CloudFront でも使える RSA 2048 か ECDSA P 256 を指定

代替ドメイン用証明書

hirenhiren

オリジンドメイン(カスタムドメインで)ALBに繋がるオリジンを作る
オリジングループを作る(用途外だけど)⇒不要だったけど分からなくなるからあった方がいいかも?
ビヘイビアのオリジンリクエストポリシーにALLViewerを設定する(Hostヘッダーを転送するポリシーであれば何でも良い)

hirenhiren

無限ループしてしまうため CloudFront に向けている DNS レコードとは別のレコード名で ALB の DNS 名 への DNS レコードを作成する

設定例

レコード名 タイプ
hoge.example.com A(Alias)or CNAME d1abcdefg2hijk.cloudfront.net
alb.examole.com A(Alias)or CNAME example-1234567890.ap-northeast-1.elb.amazonaws.com

オリジンドメインに、 ALB に繋がるカスタムドメインを指定して、オリジンを作成する
オリジン作成

オリジンタイプを Custom origin ではなく Elastic Load Balancing になるように ALB を直接指定してしまうと、HTTP 502 ERROR が返されアクセスが失敗してしまいます。
ALB デフォルトの DNS 名 には証明書が紐づいていないためです。
CloudFront ⇒ ALB 間のリスナープロトコルに HTTP を含む場合は問題無いが、 HTTPS のみの場合に発生します。
参考:CloudFrontとALB間のHTTPS接続がうまくいかなかった件

hirenhiren

パスパターンが デフォルト (*) のビヘイビアのオリジンに、前項で作成したオリジンを指定し、オリジンリクエストポリシーに ALLViewer を設定する(恐らく Host ヘッダーを転送するポリシーであれば何でも良い筈)

ビヘイビア設定

Host ヘッダーを転送するオリジンリクエストポリシーを指定しない場合、Host ヘッダーがオリジンに指定したドメイン名に置き換えられてリクエストが転送される。
例)hoge.example.com ⇒ alb.examole.com
そのため、バーチャルホストの設定をクライアントのリクエスト時ドメイン名のみで指定している場合、マッチしなくなる。

hirenhiren

通信的には必要無いが、構成上オリジンが一つで何故複数ドメインのリクエストが処理できるのか分かり辛いので、もう一つ分までであれば※オリジンを作成して、2つのオリジンを追加したオリジングループを作成し、デフォルトビヘイビアのオリジンをオリジングループに変更することは可能
※オリジングループに追加できるオリジンは2つまでのため
オリジングループの用途はフェイルオーバーのため、用途外利用にはなるが、動作は変わらない

hirenhiren

1つの CloudFront ALB EC2 で複数のホスト(サイト)を扱うことができた!

hoge.example.com
huga.example.org

/var/log/httpd/access_log
10.0.1.30 - - [25/Nov/2024:08:40:02 +0000] "GET / HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "hoge.example.com"
10.0.0.28 - - [25/Nov/2024:08:40:04 +0000] "GET / HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "huga.example.org"
hirenhiren

CloudFront ⇒ ALB を HTTPS にしてるところが難易度を一段階上げてたと思う