HTTP -> HTTPSのリダイレクトはELBで行う方がスマートかもしれない (Nginxでリダイレクトを行う方法あり)


やりたいこと

AWSのロードバランサー(ELB)を使用しており、ELBにSSL証明(ACM)を付与し、httpsアクセスが可能な状態で
httpリクエストをhttpsにリダイレクトする設定をしたい

前回記事でNginx公式docを調べていると、
すべてのトラフィックに対してif...といった処理を行うことは負荷の観点から望ましくないということを学んだ

wwwなしの、SSL(https)にリダイレクトしたいときのNGINXの設定 -Route 53 + ELB (ACM) + EC2構成- - Qiita

今回は、web server(Nginx)を使用せずともELBでHTTP -> HTTPSリダイレクトが可能だという事がわかったので、実践しメモを残します
(以下、方法2が今回の内容です)

環境

以下のような環境を想定しています
- DNS (Route 53) -> ELB -> EC2 (NGINX -> Puma)
- SSL証明: ACM
- ELB <-> Nginx (port: 80)
- Rails 6 (config/environments/production.rb: config.force_ssl = true)

注意すること

単純にwebサーバー(Nginx)でリダイレクトするとうまくいかない

以下の記事で書きましたが、
HTTPリクエストも、HTTPSリクエストもELBからの転送に対してwebサーバー(Nginx)はport 80でlistenされているということに注意が必要

wwwなしの、SSL(https)にリダイレクトしたいときのNGINXの設定 -Route 53 + ELB (ACM) + EC2構成- - Qiita

このような条件で単純にNginxで

server {
    listen 80;
    return 301 https://$host$request_uri;

とすると
HTTPリクエスト -> ELB(port 80) -> Nginx(listen 80) -> (上記設定によりリダイレクト) ->
-> HTTPSリクエスト -> ELB(port 443) -> Nginx(listen 80) -> (再リダイレクト) ->
-> HTTPSリクエスト...
とリダイレクト繰り返すことになってしまう

方法1 NginxでのリダイレクトをHTTPリクエストの場合のみに限定

公式 doc
ELB を使用して HTTP トラフィックを HTTPS にリダイレクトする

上記参考に
HTTPSリクエストに対してはNginxでリダイレクトを行わないようにする必要があるというのが以前殴り書いた記事の意図

HTTP > HTTPSへのリダイレクト設定後にNGINXがリダイレクトを繰り返す問題への対応 - Qiita

以下のように書くことでHTTPSリクエストでない場合のみリダイレクトすることができる

server {
    listen 80;
    if ( $http_x_forwarded_proto != 'https' ) {
      return 301 https://$host$request_uri;
    }

ただしELBから転送されてきたトラフィックは全てport 80でlistenされているので
この方法だと全てのトラフィックに対してif...処理が適応される

方法2 ELBでHTTPSリダイレクト

webサーバーの前にELBのみでHTTPSリダイレクトができるそうです

方法1では全てのトラフィックに対して都度if以下の処理が行われるため
非効率的で、こちらの処理のほうが無駄がないように思います

参考: 公式doc
Application Load Balancer を使用して HTTP リクエストを HTTPS にリダイレクトする

上記参考に設定すると以下のようになります

HTTP: 80 -> HTTPS: 443へリダイレクト
HTTPS: 443 -> Target-group (EC2, web serverへ)

希望するHTTP-> HTTPSリダイレクトが実現できております