LoginSignup
32
23

More than 5 years have passed since last update.

ネイキッドドメイン+HTTPSで運用するRailsアプリを5.1にアップグレードしたら、サブドメインも強制的にHTTPSになってしまった話

Last updated at Posted at 2017-07-07

問題:実際に起きた怖い話

長いタイトルですいません。この問題はちょっとわかりづらいので、まず実例からお話しします。

僕の妻はクープバゲットというパン屋をやっていて、僕はそのWebサイト(メインサイト)を管理しています。
このWebサイトはRailsで構築しています。

このほかに、ブログサイトがあります。
ブログサイトの実体はTumblrですが、独自ドメインを充てています。

この時点で押さえておくポイントは以下の2点です。

  • メインサイトはネイキッドドメインで、ブログサイトはサブドメインで運用している
  • メインサイトはHTTPSで、ブログサイトはHTTPである

今朝、メインサイトのRailsのバージョンを5.0から5.1にアップグレードしました。
メインサイトは順調に動いていたのですが、Railsアップグレードとは無関係なブログサイトが急にアクセスできなくなりました。
以下がそのエラー画面です。

Screen Shot 2017-07-07 at 9.42.30.png

エラーメッセージをよく見ると、ブログサイトのURLが https://blog.coupe-baguette.com になっています。
しかし、ブログサイトはHTTPS対応していないので、当然HTTPSでは接続できません。

でもなんで勝手にHTTPSになってるの!?

・・・というのが、実際に起きた怖い話です。

問題の原因:HSTSがサブドメインに対しても有効になったため

ブログサイトが強制的にHTTPS接続になった原因は、メインサイトのレスポンスヘッダにありました。
以下がその問題の行です。

Strict-Transport-Security:max-age=15552000; includeSubDomains

この行はHSTS(HTTP Strict Transport Security)の設定情報です。
HSTSについては以下の記事で詳しく説明されています。

HSTS (HTTP Strict Transport Security) の導入 - Qiita

簡単にいうと、これはブラウザに対して、

「常にHTTPS接続してくれよ、サブドメインも含めてな!」

とお願いする設定です。
そのため、ブラウザはメインサイトのみならず、ブログサイトまでHTTPSで接続しようとしたのです。

ちなみにRails 5.0時代は以下のようになっていました。

Strict-Transport-Security:max-age=15552000

ご覧のとおりincludeSubDomainsが付いていないため、ブログサイトはHTTPS接続されることを免れていたのです。

Rails 5.1からincludeSubDomainsが付くようになった

includeSubDomainsオプションが付くようになったのは、このコミットの影響です。

実はincludeSubDomainsオプションは、新規にrails newした場合に限り、5.0でも有効になっていました。
なぜなら、config/initializers/new_framework_defaults.rbで明示的に設定されているからです。

config/initializers/new_framework_defaults.rb
# 省略

# Configure SSL options to enable HSTS with subdomains. Previous versions had false.
Rails.application.config.ssl_options = { hsts: { subdomains: true } }

しかし、Rails 4.xからアップグレードした場合はこのオプションが付きません。
そのため、新規に5.0でrails newした場合と、4.xからアップグレードしたときで、設定内容が異なることになります。

上記のコミットはこの問題を避けるために、明示的にオプションを指定しなくても、そのバージョンのRailsのデフォルト設定を有効にするための変更です。
その結果、Rails 5.1からは新規にrails newした場合と同様に、includeSubDomainsオプションが付くようになりました。

もうひとつの条件:force_sslがtrueのときだけHSTSの設定も有効になる

しかし、rails newしたRails 5.0や、アップグレードしたRails 5.1で必ずHSTSの情報が付与されるわけではありません。

HSTSの情報が付与されるのはforce_ssltrueになっているときだけのようです。

config/environments/production.rb
  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true

解決策:HSTSのオプションを明示的に上書きする

解決策はデフォルト設定を明示的に上書きすることです。
今回は以前と同じ状態に戻すために、以下のような設定を入れました。

config/initializers/ssl.rb
Rails.application.config.ssl_options = { hsts: { subdomains: false } }

これで以前と同じようにincludeSubDomainsオプションなしのHSTSになりました。

Strict-Transport-Security:max-age=15552000

なお、ssl_optionsの設定値については以下のAPIドキュメントを参考にしてください。

ActionDispatch::SSL

この件のまとめ

というわけで、以下の条件が揃うときっと痛い目を見るよ!

  • ネイキッドドメインのサイト(メインサイト)がHTTPS
  • サブドメインがサイト(サブサイト)がHTTP
  • メインサイトがRailsで構築されている
  • メインサイトのforce_sslオプションがtrueになっている
  • メインサイトをRails 5.1にアップグレードした
  • メインサイトにアクセスしてからサブサイトにアクセスする → サブサイトまで強制的にHTTPS接続に:skull::skull::skull:

もしこの問題が発生したら、Railsのssl_optionsを明示的に設定して、サブサイトがHTTPS接続されないようにしましょう。

全部の条件が揃うのはかなりレアかもしれませんが、みなさんも注意してくださいね。

Special thanks to

この件の調査と解決に協力してくれた同僚の @ruzia に感謝します。:pray:

あわせて読みたい

この問題とは直接関係ありませんが、妻のパン屋のWebサイトをデザインリニューアルしたときの話をこちらのブログに書いています。

妻のパン屋のWebサイトを4年ぶりにレスポンシブデザインに作り替えた話 - give IT a try

32
23
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
32
23