ページの半分だけが描画され、スタイルシートが一枚ネットワークパネルで灰色になり、VPN クライアントは健全なトンネルを報告し続けている。三つの観察が同時に正しいのは、ブラウザが判定したのがページの発したリクエストであり、その判定にトンネルが関与していないからだ。件を閉じるのは設定ではなく判断であり、参照を直すか、ホストの所有者へエスカレーションするか、依存そのものを捨てる。どの選択肢にも安価な検証があり、間違えるとサポートサイクルを一度浪費する。

トンネルがサブリソースを覆えない理由

混合コンテンツは平文 HTTP でサブリソースを要求する HTTPS ドキュメントから始まる。URL はそれぞれのスキームで判定されるため、親ドキュメントの保護が子リクエストに及ぶことはない。ブラウザより下で加える暗号化が変えるのは回線上の内容であり、マークアップが要求した http:// ではない。

現在のブラウザはこれらのリクエストを二つの群に分けて扱いを変える。スクリプト、スタイルシート、iframe、および fetch、XMLHttpRequest、WebSocket による呼び出しは、アップグレードを試みることなく即座に拒否される。画像、音声、動画は https:// に書き換えて再要求され、その安全な取得が失敗すると読み込みは打ち切られる。ホストがむき出しの IP アドレスであるサブリソース URL はアップグレードの対象外なので、IP ホスト上の HTTP 画像は黙って直されるのではなくブロックされたままになる。この区分は、アップグレード可能な側の例外も含めてMozilla の混合コンテンツのガイドに記載されている。Chrome は安全なページから始まる安全でないダウンロードにも同様の拒否を適用するため、周囲のページが無傷に見えても PDF リンクが死ぬことがある。

したがって灰色の行は制御が働いている証拠であり、トンネルが平文を漏らした証拠ではない。その行はページ全体ではなく一本の参照を指す発見として扱う。

安全でない参照の持ち主を決める

何かを変える前に、問題の URL を生成される場所で分類する。その答えが、今日修正を出せるのか、ベンダーが出す必要があるのか、依存をページから外す必要があるのかを決める。画面のマークアップは実行時に組み立てられることが多いので、ネットワークパネルの Initiator 列で読み取る。

URL の出どころ誰が直せるか最初の一手
デプロイするテンプレートやパーシャルに直書きされているあなたhttps:// 形式に置き換えてからキャッシュを消す
タグマネージャやベンダーのバンドルが注入しているベンダー(あなたのチケットを添えて)正確な URL、リクエスト種別、コンソール行を送る
80 番ポートのみで提供され、TLS リスナーがないホストの所有者TLS を依頼するか、自分で管理する何かを前段に置くか、捨てる

ホストがすでに 443 で応答し、参照だけが http と言っているなら修正はローカルであり、参照を変え、ページキャッシュを消し、行が https になることを確認する。80 番ポートだけを待ち受けるホストは編集では適合させられないので、リソースは移転するか、自分が管理する何かを前段に置くか、消える。タグマネージャが注入した URL は自分のテンプレートがきれいでも現れ続けるので、その件は正確な URL とコンソール行を添えたチケットに属する。スタッフに安全でないコンテンツを許可させるのは、そのブラウザプロファイルが訪れるすべてのサイトで検査が切れてしまうため、これらの選択肢ではない。

ブラウザ設定ではなく参照を直す

失敗する導線をネットワークログを残したまま再読み込みし、疑わしいホストでパネルを絞り込む。コンソールが URL とディレクティブを示すので、テンプレートに触る前に、拒否されたのかアップグレードされたのかが決まる。

curl -sSI https://cdn.example.org/vendor.js | head -n 1
curl -sS -o /dev/null -w '%{http_code} %{url_effective}\n' -L https://cdn.example.org/vendor.js

補助的な制御が二つあり、どちらも修正の代わりにはならない。upgrade-insecure-requestsを含む Content-Security-Policy ヘッダーは、ページを離れる前に http のサブリソース URL を書き換えさせ、まだ見つけていない古い参照を捕まえる。書き換えたリクエストも、宛先ホストが HTTPS を提供しなければ失敗するので、ヘッダーが変えるのはブラウザが試す URL だけだ。HSTS はホストごとに働くため、自ドメインのポリシーはヘッダーを一度も送っていない第三者 CDN には何の効果もない。テンプレートを直したらページキャッシュを消し、描画後の HTML で古いホスト名を探すのは、同じ URL がパーシャルや翻訳文字列、データベースのフィールドからも来るからだ。

リダイレクトも追うのは、https:// で始まる連鎖が http:// の場所に着地することがあり、ブラウザが判定するのは最後の一跳だからだ。上の二番目のコマンドの-L形式がその実効 URL を出力してくれる。最後の一跳が素の http なら、編集したリンクが正しく見えても参照はまだ間違っている。

コンソールとネットワークパネルでページを確認する

キャッシュを無効にして再読み込みし、必要に応じて内容を読み込むボタンも含めて導線をもう一度たどる。初回のページ読み込みでは、遅延ウィジェット、地図タイル、クリック後にしか現れないプレーヤーのスクリプトが隠れている。コンソールに混合コンテンツの項目が残っていないこと、触れた行がすべて https を示すことを確認する。チケットを閉じる前にコンソールとリクエスト行を記録するのは、次のデプロイ後ではその状態を再現しにくいからだ。

リソースが他人のものなら、正確な URL、リクエスト種別、コンソールのテキスト、そしてそれが現れるページの四つを送る。チケットに貼るものからはセッション識別子を伏せる。画像が壊れているとだけ書いた報告では、所有者は検索の手がかりを得られない。

修正がリクエストを生んだ参照の中にある間、トンネルは自分の仕事を続ける。デプロイ後にもう一度テンプレートとベンダーのバンドルでホスト名を探し、コンソールにブロックされた混合コンテンツの項目が残っていないときにだけ件を閉じる。

関連記事