HTTPとHTTPSの違いとは?curlで自分のRailsブログへの通信を見てみた【60歳からのホワイトハッカー #6】



前回はDNSについて勉強し、自分のブログのドメイン名からHerokuまで、どのようにつながっているのかを実際に確認しました。



今回はHTTPとHTTPSです。

普段ブラウザを使っていると、


https://www.rails-fumiblog.com

のようにURLの先頭に「https」が付いています。



「HTTPSのほうが安全なんでしょ?」

くらいの知識はありましたが、ホワイトハッカーを目指すなら、もう少し理解しておきたい。

そこで今回も、自分のRailsブログを教材にして実験してみました。



HTTPとHTTPSは何が違う?

簡単にいうと、HTTPはWebブラウザとWebサーバーが情報をやり取りするための通信ルールです。

そしてHTTPSは、そのHTTP通信をTLSによって暗号化して安全性を高めたものです。


イメージすると、


HTTP
Mac -------- Webサーバー
     暗号化なし

HTTPS
Mac ======== Webサーバー
     TLSで保護


という感じでしょうか。

ログイン情報やCookieなどを扱うWebサイトでは、HTTPSが非常に重要になります。



私のRailsブログにもログイン機能があります。

ということは、自分のサイトが本当にHTTPSになっているのか調べてみるのも勉強になりそうです。



curlで自分のブログを調べてみる

Macのターミナルにはcurlという便利なコマンドがあります。



まずHTTPSで自分のブログへアクセスしてみました。

curl -I https://www.rails-fumiblog.com

すると、


HTTP/2 200
server: Heroku
strict-transport-security: max-age=63072000; includeSubDomains
set-cookie: _rails_fumiblog2_session=...; secure; httponly; samesite=lax


などが返ってきました。



200は正常にアクセスできたということ。

さらに、


secure
httponly
samesite=lax

など、今まであまり気にしていなかった文字も出ています。

自分で作ったRailsアプリなのに、知らないものがいっぱいあります(笑)。



HTTPでアクセスしたらどうなる?



次に暗号化されていないHTTPでアクセスしてみました。

curl -I http://www.rails-fumiblog.com



私は当然、

301 Moved Permanently
Location: https://www.rails-fumiblog.com/

のようにHTTPSへ転送されると思っていました。



ところが結果は、

HTTP/1.1 200 OK

でした。



「あれ?」

HTTPのまま普通に200が返ってきています。

ここから今回の勉強が、予定していた内容と違う方向へ進み始めました(笑)。



Railsの設定を調べてみた



Railsの本番環境設定を確認しました。

grep -nE "assume_ssl|force_ssl" config/environments/production.rb

すると、


config.assume_ssl = true
config.force_ssl = true

となっていました。



force_ssl = trueなのだから、HTTPからHTTPSへ転送されそうです。



では、なぜ200なのでしょう?



Herokuのログまで調べてみる



今度はHerokuのRouterログを確認しました。



HTTPでアクセスしたときのログには、

method=HEAD
path="/"
status=200
protocol=http1.1
tls=false


と出ています。



ここが今回かなり勉強になったところです。



tls=false



つまり、Herokuには本当にHTTPでアクセスしていました。



それなのに、



status=200



です。



「ブラウザやcurlの勘違いではなさそうだ」

というところまで確認できました。



ちなみにHTTPSでアクセスしたログでは、

protocol=http2.0
tls=true
tls_version=tls1.3
status=200

となっていました。



HTTPとHTTPSの違いが、自分のサーバーログで見えてきました。



assume_sslって何?



調べていくと気になったのが、

config.assume_ssl = true

です。



これはSSLを終端するリバースプロキシなどの後ろでRailsを動かす場合に、Rails側でリクエストをSSLとして扱うための設定です。



そこで本番サイトをいきなり変更するのではなく、ローカルMacで実験してみました。



まず普通のHTTPリクエストをRailsのActionDispatch::SSLへ渡します。

結果は、

status = 301
location = "https://example.com/"

でした。



ちゃんとHTTPSへ転送されています。



次にRailsからSSL通信だと認識される状態を再現してみました。

すると、

Railsのssl? = true
status = 200
location = nil

となりました。



おお!



本番Herokuで起きていた現象と同じような結果をローカルでも再現できました。



こういう瞬間はちょっと面白いですね。



本番環境の設定を変更してみる



Gitで変更を管理したうえで、

config.assume_ssl = true
config.force_ssl = true

から、


config.assume_ssl = false
config.force_ssl = true

へ変更しました。



そしてHerokuへデプロイ。



もう一度HTTPで確認します。

curl -I http://www.rails-fumiblog.com

今度は、


HTTP/1.1 301 Moved Permanently
Location: https://www.rails-fumiblog.com/

になりました。



やった!



HTTPアクセスがHTTPSへ転送されるようになりました。



さらに、


curl -I https://www.rails-fumiblog.com

を実行すると、


HTTP/2 200


です。



HTTPS側も正常です。



今回の勉強で一番面白かったこと



最初は単純に、



「HTTPとHTTPSの違いを勉強しよう」



というだけでした。



ところが実際に自分のRailsブログへcurlしてみたことで、


HTTPなのに200?
        ↓
Railsの設定を見る
        ↓
force_ssl = true
        ↓
それなのになぜ?
        ↓
assume_sslを発見
        ↓
Heroku Routerのログを見る
        ↓
tls=falseを確認
        ↓
ローカルで再現実験
        ↓
設定を変更
        ↓
HTTP → HTTPSの301を確認!


というところまで進みました。



本を読むだけでは、たぶんここまで調べなかったと思います。



そして少しずつ、



「分からない現象が出たら、ログを見て、一つずつ原因を切り分ける」

という考え方が分かってきた気がします。



まだホワイトハッカーというには程遠いですが(笑)、こういう調査の積み重ねが大切なのかもしれません。



まとめ



     
  • HTTPとHTTPSは同じWeb通信でも、HTTPSはTLSで保護される
  • curl -Iを使うとHTTPレスポンスヘッダーを確認できる
  • 301 Moved PermanentlyでHTTPからHTTPSへ転送できる
  • Herokuのログではtls=true / falseを確認できる
  • Railsにはforce_sslやassume_sslという設定がある
  • 設定を変更する前にローカルで再現実験すると原因を切り分けやすい



今回、HTTPとHTTPSを勉強するつもりが、結果的に自分のブログのHTTPS設定を実際に見直すところまで進みました。



自分で作ったRailsブログが、そのままホワイトハッカーの教材になっています。



60歳からでも、まだまだ知らないことだらけ。



だからこそ面白い(笑)。





次回は、



「GETとPOSTとは?Railsのroutes.rbからHTTPメソッドを理解する【60歳からのホワイトハッカー #7】」



へ進んでみようと思います。



HTTP、HTTPSが分かってきたところで、普段Railsで何気なく使っている
GET、POST、PATCH、DELETE
が何をしているのか、自分のroutes.rbを教材に調べてみます。