

ALB配下のhttpdでHTTPS判定がずれる、SetEnvIfで直す
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
何が起きるか
ALBやCloudFrontのようなロードバランサー・リバースプロキシの後ろにApache(httpd)を置く構成だと、クライアント〜LB間はHTTPSでも、LB〜Apache間は素のHTTPで通信していることが多い。
この場合、Apacheやその上で動くPHPなどのアプリケーションから見ると、リクエストは常にHTTPで届いているように見える。結果として$_SERVER['HTTPS']が空になったり、フレームワーク側の「HTTPSかどうか」の判定がずれて、リダイレクトループやCookieのSecure属性周りで問題が出たりする。
Client --HTTPS--> ALB --HTTP--> Apache(httpd)原因
LB側は元のプロトコルをX-Forwarded-Protoヘッダーに詰めて転送してくる。ALBやCloudFrontはデフォルトでこのヘッダーを付与する。
X-Forwarded-Proto: https… 元はHTTPSだったX-Forwarded-Proto: http… 元はHTTPだった
だがApache自身はこのヘッダーの中身を見てHTTPS環境変数を自動的に書き換えたりはしない。素直にHTTPとして扱う。
対処
.htaccess(もしくはVirtualHost設定)に以下を書いておくと、X-Forwarded-ProtoがhttpsのときだけApacheのHTTPS環境変数をonにできる。
SetEnvIf X-Forwarded-Proto "https" HTTPS=onこれで$_SERVER['HTTPS']がonとして見えるようになり、PHPやフレームワーク側のHTTPS判定が正しく動くようになる。mod_rewriteの%{HTTPS}を条件に使っている場合も同様に効いてくる。
注意点
X-Forwarded-Protoはクライアントが直接偽装できるヘッダーなので、LBを経由しない直アクセスを許可している構成だと、この設定だけでは信頼できない。LB以外からの直接アクセスを塞ぐか、LB側で強制的にヘッダーを上書きする設定と合わせるのが安全らしい(実機で直アクセス遮断まで検証したわけではないので、そこは未確認)。mod_sslが有効な環境でSSLEngine自体をonにしているわけではない。あくまでアプリケーション側から見た判定を補正しているだけで、Apache〜LB間の通信そのものがHTTPSになるわけではない。- Nginxの場合は
fastcgi_param HTTPS $http_x_forwarded_protoのように別の書き方になる。
結論
ALBやCloudFrontの後ろにApacheを置くなら、X-Forwarded-Protoを見てHTTPS環境変数を補正する設定はほぼセットで必要になる。.htaccess一行で済むので、リダイレクトループやCookieのSecure属性がおかしいと思ったら、まずここを疑うのが早い。