リバースプロキシの下でEC-CUBE (Symfony)を動かすときはTRUSTED_PROXIESを設定する
タイトルのとおりです。EC-CUBEをサーバーで直接ホストせず、コンテナ&リバースプロキシで動かしてみたのですが、ちょっとした問題が発生したのでそのトラブルシュート記録です。
こんな構成
実際にどんな構成で問題が起きていたのかというのがこの図です。WebサーバーのApacheにリバースプロキシを設定しておき、特定のパスへのアクセスをローカルのコンテナに転送するようにしています。
既存環境があるのでphp-fpmを構成するのもちょっと面倒だし、手軽に独立した環境が欲しかったのでDockerのコンテナを立てました。(おそらく)今回の本題ではないので、リバースプロキシの設定は触れません。
問題
EC-CUBEのトップページはちゃんと表示されるし管理画面にもログインできますが、カートに商品を入れようとすると「不明なエラー」とダイアログが出てきてカートに商品を追加できない状態になりました。
コンソールログを見ると “This request has been blocked; the content must be served over HTTPS.” というエラーが出ています。どうやらHTTPSで表示しているページからHTTPのアクセスをしようとしてエラーになっていたようです。
原因
エラーになった箇所のEC-CUBEの実装は、url('shopping_confirm')
となっている部分です。問題ないリンクは //test/style.css
のようにスキーマ指定の無いURLだったので問題なかったのに対して、UrlGeneratorを使ったURL出力では http://example.com/test/endpoint
とHTTPのURLになってしまうようでした。
これは、リバースプロキシを挟んでいるためEC-CUBE・Symfonyから見たときにhttpsでなくhttpでアクセスされているように見えてしまうことが原因のようです。そのため、 .envに TRUSTED_PROXIES を設定して、httpsのURLが生成されるようにします。
TRUSTED_PROXIESを設定する
TRUSTED_PROXYについてEC-CUBEの実装を調べると index.php に記載がありますが、単にSymfonyのsetTrustedProxiesを呼び出しているだけでした。そこでSymfonyの方のドキュメントを見ると、ちょうど「ロードバランサーまたはリバースプロキシの背後で動作するように Symfony を設定する方法」というドキュメントがありました。
https://symfony.com/doc/6.4/deployment/proxies.html
DockerのネットワークはIPアドレスが起動ごとに変わりますが、そういった場合は REMOTE_ADDR
を指定すれば良いそうです。そこで、EC-CUBEの.envでTRUSTED_PROXIESのコメントアウトを外して次のように指定します。
# 変更前 #TRUSTED_PROXIES=127.0.0.1,127.0.0.2 # 変更後 TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR
これで、URLがhttps://…になりました。めでたしめでたし
ちなみに、Symfony 7.1以降は private_ranges
を指定するとプライベートIPを全部指定できるそうですが、残念ながら最新のEC-CUBE 4.3.0でもSymfony 6.4なのでこの方法は使えませんでした。
余談
弊社にはプラグインの開発・テスト用にEC-CUBEの環境がいくつかあるのですが、急遽、サーバーにインストールされているPHPとは違うバージョンの環境が必要になったのでこんなことをしてみました。
今回はリバースプロキシとコンテナの両方の問題でしたが、どちらか片方だけでも同様の設定が必要になると思います。