
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を教材に調べてみます。