LoginSignup
2
0

More than 1 year has passed since last update.

CloudFront => Rails で直結する場合は X-Forwarded-Proto ではなく X-Forwarded-SSL ヘッダを付けると良い

Last updated at Posted at 2022-03-15

Rails + AWSで雑にhttps を立てたいと思い

CloudFront(https) => EC2(Railsアプリ/http)

という構成でアプリを作ると、 GET 以外のリクエストを投げるとこんなエラーが出る

HTTP Origin header (https://xxx.cloudfront.net) didn't match request.base_url (http://xxx.cloudfront.net)

ApplicationController で適当にリクエストヘッダーを出力してあーでもないこーでもないとこねくり回してみたのだが・・・

class ApplicationController < ActionController::Base
  before_action :env_log

  private

  def env_log
    request.headers.sort.reject { |k, _| k.to_s.include?('.') }.each { |k, v| logger.info "#{k}:#{v}" }
  end
 end

自前でリバースプロキシをする時は、 X-Forward-Proto に https を設定するのが定石だが、CloudFront で動かしてみるとどうも X-Forward-Proto だけがうまく設定されない
Notification_Center.png

例えば

  • ヘッダー名: Hoge
  • 値: Piyo

みたいな設定は動くけど、X-Forward-Proto だけが消去される

CloudFront には CloudFront-Forwarded-Proto という独自ヘッダーがあるらしく、
ビヘイビア側の設定で、Cloudfront-Forwarded-Protoを飛ばすように設定すると、そこにはhttpsが入ってくる。

Rack Middleware でCloudFront-Forwarded-Proto を X-Forward-Proto に置換するというのも見つけたけど、
https://aknep.hatenablog.com/entry/2017/09/17/230405

アプリを書き換えるのは嫌だなーと思っていたところ
https://mikamisan.hatenablog.com/entry/2017/09/28/230215

こちらで、Railsは X-Forwarded-SSLというフラグを見ているという記事を発見した
Notification_Center.png

ソース:
https://github.com/rack/rack/blob/rack-1.5/lib/rack/request.rb#L73

ということで、X-Forward-Protoの設定は諦めて、X-Forwarded-SSL:on という設定を利用したら上手に動作した。

しかし、X-Forward-Proto がなぜ勝手に消されるのかは不明。

以下CloudFormation

Parameters:
  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: Choose which VPC the security groups should be deployed to

  DefaultTTL:
    Description: The default cache time in seconds
    Type: Number
    Default: 86400 # 24hrs
  MaxTTL:
    Description: The maximum cache time in seconds
    Type: Number
    Default: 604800 # 168hrs
  MinTTL:
    Description: The minimum cache time in seconds
    Type: Number
    Default: 60 # 1 minute

  ErrorCacheTTL:
    Description: The Error cache time in seconds
    Type: Number
    Default: 60 # 1 minute

  EndpointName:
    Description: ELB Ref
    Type: String
    Default: ''

  TargetOriginId:
    Type: String
    Description: target id
    Default: 's3-bucket'

  DefaultCachePolicyId:
    Description: Cache Policy Id. (Default policy is ManagedCachingDisabled)
    Type: String
    Default: '4135ea2d-6df8-44a3-9df3-4b5a84be39ad'
    AllowedPattern: '[-\.a-z0-9]*'
    # ManagedCachingOptimized https://docs.amazonaws.cn/en_us/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html

  DefaultOriginRequestPolicyId:
    Description: Origin request Policy Id. (Default policy is AllViewer)
    Type: String
    Default: '216adef6-5c7f-47e4-b989-5492eafa07d3'
    AllowedPattern: '[-\.a-z0-9]*'


Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        DefaultCacheBehavior:
          TargetOriginId: WebSiteOrigin
          AllowedMethods: [GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE]
          OriginRequestPolicyId: !Ref DefaultOriginRequestPolicyId
          CachePolicyId: !Ref DefaultCachePolicyId
          ViewerProtocolPolicy: allow-all
        Enabled: true
        Origins:
          - DomainName: !Ref EndpointName
            Id: WebSiteOrigin
            CustomOriginConfig:
              OriginProtocolPolicy: 'http-only'
              OriginKeepaliveTimeout: 60
            OriginCustomHeaders:
              - HeaderName: "X-Forwarded-SSL"
                HeaderValue: "on"

Outputs:
  CloudFrontEndpoint:
    Description: address for the cloudfront
    Value: !GetAtt Distribution.DomainName

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0