みなさまはじめまして。クラウドチームのかたやまです。

先日、AWS WAFがCloudFrontに加え、Elastic Load Balancing(ELB)サービスの一部であるApplication load Balancer(ALB)でも利用できるようになりました。ALB+WAFの組み合わせによってCloudFrontを使わずに済むことによるメリットが得られるようになりました。

例えば、こんなところでしょうか。

  • CloudFront~内部リソース(オリジン間)の通信にかかるコストが無くなった
  • ELBをオリジン指定する場合、ELBへの直接アクセスを防ぐためにはLambdaと組み合わせてセキュリティグループを動的に定義するような工夫が必要だったがそれが不要になった

しかし、従来CloudFrontを使えば簡単にできていたことが、この組み合わせではできないという状況も存在します。

その1つが「HTTPで届いた通信をHTTPSにリダイレクトすること」です。
CloudFrontであれば、ディストリビューション設定の[Behaviors]-[Viewer Protocol Policy]の設定で簡単にリダイレクトを実現できますが、ALBにはそのような機能がありません。

さて、どうすればCloudFront抜きの構成でもこれを実現できるでしょうか?

前提条件

EC2のOSはAmazon Linuxを利用しています。
今回は「Amazon Linux AMI release 2016.09」を利用しています。
WebサーバはApacheで動いています。Apacheのバージョンは2.2.31です。
ELBのタイプはApplicationを選択します。

ALB側で必要な設定

※ALBの作成方法は、今回は省略します。

重要な点は、以下の3点です。

  1. ロードバランサ作成時、ロードバランサの種類はApplication Load Balancerを選択します。
  2. リスナーはHTTP用とHTTPS用の2つを用意します。
  3. ターゲットグループを作成します。ターゲットポートは80番とします。

ここでのポイントとして、ヘルスチェックの成功コードは正常であることを示す200ではなく、リダイレクトされたことを示す301としてください。ヘルスチェックはHTTPで行いますが、Apacheでは後述の設定によりHTTPで受信した通信をHTTPSにリダイレクトしてしまうためです。


これでALB側の設定は完了です。続けてApache側の設定を行います。

Apache側で必要な設定

httpd.confを編集します。元の設定ファイルはコピーしてバックアップしておきましょう。

さて、設定ファイルをどういじるかということですが、以下のような設定を設定ファイルの末尾に追加します。{ALBのFQDN}という部分は、実際の設定に置き換えてください。

RewriteEngine On
RewriteLogLevel 0
RewriteCond %{HTTP:X-Forwarded-Proto} !https [NC]
RewriteRule ^(.*)?$ {ALBのFQDN}$1 [R=301,NC]

こうすることで、受信した通信のうち「ALBのHTTPリスナで受けた」ものだけを全てHTTPSにリダイレクトします。HTTPSリスナで受けた通信はリダイレクトしないということがポイントです。

なぜなら・・・HTTPSリスナで受けた通信も全部リダイレクトしてしまうとリダイレクトループが起きてしまうからです!
そのメカニズムは、最後に解説します。

設定が完了したら、構文チェックをします。

sudo apachectl -t

Syntax OKと表示されたら、Apacheをリロードします。

sudo apachectl graceful

動作確認

さて、動作確認をしてみましょうか。FireFoxで通信の流れを確認してみます。
<F12>キーを押すと、HTTP通信のやり取りを追跡することができます。

まず、http://~にアクセスしており、その応答コードが301となっています。これはリダイレクトされたことを示しています。
続けて、https://~にアクセスしていますね。それに対して、応答コードは正常応答を示す200に変わっています。

まとめ

CloudFront抜きでHTTP to HTTPSリダイレクトを実現する場合、AWS側だけではなくApache側でも設定が必要になりますが、設定箇所は少ないのでお手軽に実現することができます。

ALB+WAFの組み合わせでWebサイトを公開したい、でも全部の通信をHTTPSにしたい、そのような場合には上記を参考にしていただければ幸いです。

おまけ

リスナで受ける全部の通信をリダイレクトするとリダイレクトループが起きる理由・・・こんな流れで発生します。

1) ALBのリスナはHTTPSでhttps://hoge.jpあての通信を待ち受けます

2) リスナは1)の通信を「すべてHTTPで」ターゲットグループのEC2に送信します

3) EC2の中にあるApacheは、HTTPで届いたすべての通信を「https://hoge.jp」に
リダイレクトするよう応答コード301を返します

4) https://hoge.jpにアクセス(つまりALBあて)

5) ALBリスナは4)の通信をHTTPでターゲットグループのEC2に送信・・・
※以下、延々ループ

こんなことになってしまうので、HTTPSリスナで受けた通信はリダイレクトしないというような設定が必要になります。
ちなみに、それを定義しているのは先ほど追加した設定の中にある

RewriteCond %{HTTP:X-Forwarded-Proto} !https [NC]

という1行です。
X-Forwarded-Protoヘッダの中身がHTTPかHTTPSなのかを見て、HTTPSの場合を除きリダイレクトする、というような定義になっています。

このヘッダについての説明は、AWSサイトをごらんください。

AWS で Web を開始したい方はお問い合わせページよりお気軽にご連絡ください