この記事の内容
ELB(SSL Terminationしない) -> 複数の名前ベースVirtualHost(SSL)の振り分け設定でちょっとハマったので、調べて試してうまく行った結果をメモ。
環境
VPC: 192.168.0.0/16
Public Subnet: 192.168.0.0/24 (こっちにELB)
Private Subnet: 192.168.1.0/24 (こっちにEC2)
Apache: httpd-2.4.18
やりたいこと
- ELB (SSL Terminationしない) + EC2 (Apache + mod_ssl)
- 名前ベースVirtualHostで複数のサイトをホストする
httpd.confの設定(必要なところのみ)
Listen 192.168.1.10:443
# ダミー用 (site-aとsite-bに該当しないものはすべて403扱いにする)
<VirtualHost 192.168.1.10:443>
ServerName dummy
ServerAdmin postmaster@example.com
DocumentRoot "/usr/local/httpd2/htdocs"
DirectoryIndex index.html
SSLEngine On
SSLCertificateFile "/usr/local/httpd2/ssl/server.crt"
SSLCertificateKeyFile "/usr/local/httpd2/ssl/server.key"
<Directory "/usr/local/httpd2/htdocs">
Require all denied
</Directory>
</VirtualHost>
# site-a用のVirtualHost
<VirtualHost 192.168.1.10:443>
ServerName site-a.example.com
ServerAdmin postmaster@example.com
DocumentRoot "/var/www/site-a"
DirectoryIndex index.html
SSLEngine On
SSLCertificateFile "/usr/local/httpd2/ssl/site-a.crt"
SSLCertificateKeyFile "/usr/local/httpd2/ssl/site-a.key"
<Directory "/var/www/site-a">
Require all granted
</Directory>
</VirtualHost>
# site-b用のVirtualHost
<VirtualHost 192.168.1.10:443>
ServerName site-b.example.jp
ServerAdmin postmaster@example.jp
DocumentRoot "/var/www/site-b"
DirectoryIndex index.html
SSLEngine On
SSLCertificateFile "/usr/local/httpd2/ssl/site-b.crt"
SSLCertificateKeyFile "/usr/local/httpd2/ssl/site-b.key"
<Directory "/var/www/site-b">
Require all granted
</Directory>
</VirtualHost>
ELBの設定
リスナーの設定で、ロードバランサー/インスタンスともにプロトコルをTCP:443に設定する。
こうすることで、ELBがL4レベルのロードバランサーとして振る舞う(単純に裏側のEC2インスタンスに振り分けられる)。
この際、ELBは当然HTTPヘッダを覗かないので、X-Forwarded-Forなどの情報を利用することはできなくなる。
つまり本来の接続元クライアントを特定することができなくなる(ApacheのログにはELBのプライベートIPアドレスが接続元として記録される)。
その代わりELBではX-Forwarded-Forの代用としてProxy Protocolをサポートするよう設定が可能である。
Proxy ProtocolはL4レベルで動作するプロトコルで、転送を受けたWebサーバはこちらの情報を参照することで、
接続元クライアントを特定することができる(Apacheは標準でサポートしてないみたい?)。
ステップ1: ロードバランサーの定義
・ロードバランサーを配置する場所: 192.168.0.0/16
・リスナーの設定
ロードバランサーのプロトコル : TCP
ロードバランサーのポート : 443
インスタンスのプロトコル : TCP
ロードバランサーのポート : 443
・サブネットの選択: 192.168.0.0/24
ステップ2: セキュリティグループの割り当て
セキュリティグループ(sg_testとでも)
送信元: 0.0.0.0/0 ポート範囲: 443
を割り当てる
ステップ3: セキュリティ設定の構成
TCP -> TCPなので設定項目なし。次へ
ステップ4: ヘルスチェックの設定
ELBから届くところをPing対象として設定
タイムアウト、ヘルスチェック間隔など設定(この辺は自明なので段々雑になってきた...)
ステップ5: EC2インスタンスの追加
振り分け対象のEC2インスタンスを追加する(以下略)
確認
上記のような感じで設定をして
https://site-a.example.com/
https://site-b.example.jp/
にアクセスし、SSL接続可能なことを確認する。