Amazon EC2で常時SSLを実現する際の注意点
2017-08-21EC2 で作った LAMP 環境 + Application Load Balancer で常時 SSL を実現しようとした際に、 http → https のリダイレクトがループしてしまったときの対処方法です。
前提
- SSL証明書はAWSのCertificate Managerで取得
- 取得したSSL証明書は、 ELB (Application Load Balancer) で使用
詰まった点
単純にhttp→httpsリダイレクトをすると無限ループに陥る
常時SSLにするためには、http
→https
のリダイレクトが必要ですが、上記の前提で実現しようとするとこのリダイレクトが無限ループとなってしまいます。
AWSのELBを使用している場合、クライアントからサーバ(EC2インスタンス)へのアクセスの間にELBが入ります。
ここで注意が必要なのが、ELBからEC2への通信はhttp
だということです。
つまり、クライアントがhttps
でアクセスしていても、ELBからEC2への通信はhttp
となります。その結果、Apache(EC2)でプロトコルのチェックをしても常にhttp
通信だということになります。
そのため、「http
ならhttps
へリダイレクト」という条件が無限ループとなってしまうわけです。
これを回避するため、常時SSLにしたいディレクトリの.htaccess
は下記のように記述します。
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R=301,L]
この記述では、以下の条件に当てはまる場合はhttps
でリダイレクトする という記述です。
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
ユーザーエージェントがELB-HealthChecker
から始まらないRewriteCond %{HTTPS} !=on
通信プロトコルがhttps
ではないRewriteCond %{HTTP:X-Forwarded-Proto} !=https
HTTPヘッダーX-Forwarded-Proto
の値がhttps
ではない
1については後ほど書きます。
2, 3が常時SSLに関わる部分です。
特に3つ目の条件は、AWSでELBを使用してhttps通信を実現する際の回避策としては必須となっているようです。(現状では)
HTTPヘッダーX-Forwarded-Proto
は、ELBからEC2へ通信する際に付与されるヘッダー情報で、クライアントからELBへの通信がhttp
だった場合のみ、http
という値になる というものです。
この値を判定して、https
へのリダイレクトを実現します。
(2はELBを通している以上、不要?かもしれません)
ELBのヘルスチェックがエラーになる
単純にhttp
→https
のリダイレクトを実現するためには前項の2, 3のみでよいのですが、その状態で運用しているとELBのヘルスチェックがエラーとなってしまいます。
ELBのヘルスチェックとは、定期的にELBからEC2に通信を行い、返ってくるレスポンスコードによって正常かどうかを判定しています。
ヘルスチェックでは、返ってくるコードが200
以外の場合はエラーとするようです。
前項で書いた1の条件が無いと、ヘルスチェックのための通信もhttp
→https
リダイレクトされ、ELBに返すコードとしては301
になってしまいます。
1は、これを回避するためにアクセス元のUserAgentを見て「ヘルスチェックの際のUserAgentであるELB-HealthChecker
の場合はリダイレクトをしない」という記述になります。
参考URL
comments powered by Disqus