2023年11月1日の時点の情報です。
先にまとめを書きます。興味があれば詳細もどうぞ。
まとめ
- 10月16日のChrome 118からHTTPS ファーストモードがデフォルトでオンに
- 条件によってHTTPS Upgradeが働いてhttpのサイトにアクセスするとhttpsに優先的にアクセスさせる挙動(Chromeが内部で擬似的に307リダイレクトを返してhttpsに誘導)
- HSTSサイトではないhttpサイトでもこの挙動となるケースがある
- httpsにアクセスできない場合やレスポンスに3秒以上かかる場合はフォールバックでhttpに誘導(Chromeが内部で擬似的に307リダイレクトを返して元のhttpに誘導)
詳細
条件
307で擬似的にリダイレクトする条件は、いくつかあるようです。把握しているものを列挙します。
- HSTSサイト(HSTSヘッダ指定、Preloadリストのサイト)
- HSTSではないがHTTPとHTTPSどちらもアクセスできるサイト
- JavaScriptでwindow.locationでhttpサイトにリダイレクトする
- httpsを受け付けていないサイトでもhttpsに優先的にアクセスさせる
ほとんどのケースはあまり気にしなくても良いかと思いますが、window.locationの場合は想定外の動きをしてしまうので気にしておいたほうが良いかと思います。この場合、httpsサイトに307リダイレクトしてアクセスできないとhttpサイトに307で戻されます。
URLバーにhttp://から自分で指定して非HSTSサイトにアクセスした場合は、今回のリダイレクト対象にはならないようです。
具体的な動き
例えば、window.locationでhttp://example.com/ にアクセスさせる場合の例。このサイトはHSTS対応してないとします。
まずはGET http://example.com/ でChromeがアクセスしに行きます(http)が、この時にHTTPSファーストモードによって実際にはインターネットにリクエストは飛ばず、Chromeの中で擬似的に次のようなレスポンスを返します。
HTTP/1.1 307 Temporary Redirect
Location: https://example.com/
Non-Authoritative-Reason: HttpsUpgrades
Content-Length: 0
この時点では、Webサーバ側には何もリクエストが届かずログにも残りません。
Non-Authoritative-Reason: HttpsUpgrades
というHTTPヘッダが特徴的ですね。
次にChromeはLocationヘッダに従い、GET https://example.com/にアクセスします(https)。この時は実際にHTTPリクエストがサーバ側に飛びます。ここでhttpsからレスポンスが返せればそのままブラウザはhttpsでアクセス完了します。
httpsでアクセスできなかった時は
307でhttpsにリダイレクトされ、httpsでアクセスできない場合、GET https://example.com/には次のようなレスポンスをChromeが擬似的に返します。
HTTP/1.1 307 Temporary Redirect
Location: http://example.com/
Non-Authoritative-Reason: HttpsUpgrades
Content-Length: 0
最後に、httpでGET http://example.com を送り(http)、Webサーバからコンテンツを取得します。
httpsでアクセスできない場合の条件は次のようなケースです
- httpsポートが閉じている
- 正しい証明書ではない
- レスポンスステータスが404
- レスポンス受信まで3秒以上かかる
色々ありますね。最後の受信まで3秒以上かかるのは私の手元で実験した結果です。httpsのレスポンス時にsleepで5秒入れるとフォールバックの307を3秒目に返していました。
余談
GET http://example.com:8000/ のようなポート番号指定の場合の挙動は、次のようになんと同じポート番号にhttpsでリダイレクトされます。まぁ、しょうがないかという気がしますが、httpとhttpsが同じポートという想定で良いのかなとモヤモヤしますね。
HTTP/1.1 307 Temporary Redirect
Location: https://example.com:8000/
Non-Authoritative-Reason: HttpsUpgrades
Content-Length: 0
参考記事
2023年8月16日のChroniumのブログ記事です。HTTPSファーストモードを将来的に全ユーザに適用したいと書いてます。その2ヶ月後にそうしてるので、世界のスピード感に圧倒されますね。
HTTPS Upgradeについて参考になりました。特にwindow.locationがHTTPS Upgrade対象とここに書いてあって、自分たちが遭遇した問題だと判断できました。
10/16からChromeがHTTPSファーストモードを全ユーザに適用とこの記事にありました。
余談2
この問題に気付いたのは、脆弱性診断サービスVAddyのChrome拡張ツールを作っている時でした。10月上旬には問題なかった動作が10月下旬になると何もしていないのに壊れた!みたいな動作になったためです。
VAddyのChrome拡張では、最初にユーザのWebサーバに設置した認証ファイルにアクセスしてそのレスポンスステータスやボディをチェックしています。この時にリダイレクトはエラー扱いにしていたのですが、307のこの動作を想定していなかったため、今回の問題に直面しました。幸いにもhttpのサイトが検査対象になっているケースもなかったため、本問題は私の手元のやられアプリをクロールする時のみ発生していました。
最初にこの307の事象を見た時に頭が混乱して、だれが307を返してるんや!と頭を抱えました。
VAddyのChrome拡張のリリース記事です。参考までに。