前編ではpixivを常時HTTPS化する前にやった前準備として、広告、画像といったリソースをHTTPSに切り替える際の手順を紹介しました。inside後編では実際にpixivのアプリケーション自体を常時HTTPS化していく手順を紹介します。従来のHTTPS配信pixivはPHPアプリケーションを実行するアプリケーションサーバー(Apache/mod_php)の前段にnginxを配置する構成になっています。以前からセキュリティ的に重要なページはHTTPSで提供しており、nginxでHTTPS終端処理を行っていました。HTTPSで応答する場合はアプリケーションサーバーにX-HTTPSヘッダーを付けてプロクシーしています。具体的には以下のようなnginxの設定を使用していました。HTTPSで提供しているページは一部だけなので、そのページだけをnginxからアプリケーションサーバーに流します。HTTPSで提供しないページはnginxでHTTPのページに302リダイレクトするようにしていました。セキュリティ的に重要なページはアプリケーション側でX-HTTPSヘッダーの有無を確認して、無ければHTTPSにリダイレクトします。pixivではこの方法でこれまで一部のURLをHTTPSで提供してきました。すべてのURLに対するHTTPS通信をプロキシするようにすることで、常時HTTPSにすることができます。常時HTTPSへの移行手順はざっくり以下のようになります。contentsの対応漏れがないか探す1つ1つ説明していきます。Ajaxで叩くAPIを先行してHTTPSに変更するブラウザがリクエストするページに先駆けて、まずAjaxで叩くURLを先行してHTTPSに変更しました。Sharing)を使う必要があります。弊社では以前からCORSを利用してきました。詳しくは以下、弊社でCORSを導入したときのエントリを参照してください。inside今回気を付けなければならなかったのはpreflightリクエストです。CORSについて詳しくは以下のURLを参照してください。MDNPOSTリクエストでContent-Typeにapplication/jsonを指定した場合など、CORSでは特定の条件を満たすと実際のリクエストを行う前にpreflightリクエストが行われます。preflightリクエストはOPTIONSメソッドで行われます。その際Cookieは付与されません。そのためアプリケーション側でOPTIONSメソッドを考慮していない場合、認証が必要なAPIだとログインしていないと判断され、ログインページにリダイレクトするレスポンスを返すなどの想定外の挙動をします。よって以下のような実装にしました。preflightリクエストでOPTIONSメソッドのリクエストが送られてきたら、アプリケーション側でOriginヘッダーを確認します。想定したOriginヘッダーならば、レスポンスにAccess-Control-Allow-OriginやAccess-Control-Allow-Credentialsヘッダーを適切に付けて、ステータスコード200を返します。これで正しく動作しました。2.5).HTTPとHTTPSの両方で見れるようにする次に、すべてのページを本番環境でHTTP、HTTPSの両方でリクエストできるように変更し、ページの動作を確認していきました。事前の確認として、主要ページがHTTPS上で正しく動作していたら問題なしとしました。理由はpixivはURLが膨大でかつ機能も多いため、最初からすべての機能がHTTPS上で動くかを確認することは困難だからです。contentsが発生していないか監視を行うという手順で順次HTTPSへ移行しました。HTTPS化は、ある程度独立して提供されている機能から順次に対応していきました。pixivの小説の機能はwww.pixiv.net/novel/かtouch.pixiv.net/novel/以下で機能が提供されています。このようにディレクトリが切られて、分割しやすいものから対応していくことで、順次HTTPS化を行えました。HTTPへのGETリクエストだけをステータスコード302でHTTPSにリダイレクトするHTTPSにリダイレクトする際に気を付けなければならないことがあります。POSTリクエストをステータスコード302でリダイレクトすると、リダイレクト先にGETリクエストを送ります。その際POSTリクエストで送ったデータは消えてしまいます。一方で、ステータスコード307でリダイレクトすると多くのブラウザでPOSTメソッドのままPOSTしたデータをリダイレクト先に再送してくれます。ステータスコード307でPOSTリクエストをリダイレクトした場合、ブラウザ上で確認のダイアログが出ることがあります。ユーザーがPOSTで送ったデータを、他のURLに再送させるのはユーザーに不信感を与えるかもしれません。以上の理由から、POSTリクエストはリダイレクトしないことが望ましいと考え、今回はPOSTリクエストならリダイレクトしないようにしました。実際にリダイレクトする処理について説明していきます。今回の対応では、www.pixiv.netとtouch.pixiv.netでリダイレクトする方法を変えていたので、2つを分けて説明していきます。touch.pixiv.netの場合pixivは長い歴史があるサービスであり、ページごとに処理するPHPスクリプトが分かれている構成になっています。ようにPHPのファイル名にクエリストリングを渡しているURLです。このため、従来のページ構成では、すべてのページで統一した処理を行うような変更が困難になっていました。現在pixivではこの問題を解決するためにソースコードの整理を進めており、URLルーティングの導入をすすめています。URLルーティングを用いると、すべてのURLが1つのPHPスクリプトを実行するようになるため、全ページに対して一括した処理を容易に行うことができるようになります。pixivのURLルーティングについて、詳しくは以下のエントリを参照してください。insideHTTPS化の作業を行っていた時点ではtouch.pixiv.netはURLルーターの実装が入っており、アプリケーションの実装から全体を統一的に制御することができるようになっていました。そこでURLルーターにHTTPSを許可するかどうかのルールを実装し、先程紹介したnginxの設定と同じ挙動をするよう変更しました。その後nginxの設定を変更し、HTTPSからのリクエストをすべてアプリケーションに流すように修正し、HTTPSの制御をURLルーター側で行うように変更しました。これにより、アプリケーション側でHTTPSの細かい制御が可能になります。事前に本番環境で確認ができるように、確認用に付与した特定のCookieを持っている場合に、常時HTTPSで見られるようにルーター側の実装を変更しました。www.pixiv.netの場合touch.pixiv.netと違い、www.pixiv.netはURLの種類が多く、ルーター化も行われていませんでした。そのためアプリケーション側でHTTPSを許可するかどうかを制御することが困難でした。そこでアプリケーションのコードを変更せずに、アプリケーション全体の動きを変更するためにnginxで制御を行いました。nginxで制御を行う場合、以下のデメリットがあります。開発環境と本番環境の設定を合わせるのが難しい挙動を確認するためには、nginx設定とアプリケーションコードの両方をみる必要があり、他の開発者がすべての挙動を追うことが難しくなる特定のCookieを持っていたら動きを変えるといった複雑なロジックを書くにはnginx-luaなどを用いる必要があるこれらのデメリットを解決するのは難しいです。これらのデメリットを抑えるために、HTTPとHTTPSが混在する期間を2日に抑えました。touch.pixiv.netでは1週間混在期間がありましたが、そのために一部の機能が長期間動かないことがありました。混在期間中は、もっとも動作を保証することが難しいため、混在期間を短く抑えることがおすすめです。nginxの設定は以下のような設定を書きます。nginxの設定をこのようにすることでPOSTリクエストのみ許可、GETリクエストはHTTPにリダイレクトする設定が書けます。nginxのifは非常に複雑なので慎重に使う必要があります。contentsの対応漏れがないか探すCSPについて説明します。CSPとは特定の種類の攻撃を検知したり、実際に影響を軽減させることができるセキュリティ上の仕組みです。指定したURIに対して、ポリシー違反の情報をJSONデータとしてまとめてPOSTすることができます。詳しくは以下のURLを参照してください。MDNCSPはHTTPヘッダーを1行返すだけで有効にすることができ、最近のブラウザならばまず対応しています。Report-Onlyにすればユーザーに悪影響はないので安心して付けることができます。contentsを見つける用途にも使用することができます。CSPは以下のような記法で指定していきます。https://example.com/csp-reportreport-uriに指定するURLに制約はありません。POSTメソッドでJSONのデータが送られるだけなので、そのJSONを保存する適当なシステムがあれば容易に確認できるようになります。report-uri.ioという無料のサービスを使うこともできます。大量のリクエストを送ることはできませんが、気軽に始めたいならおすすめです。CSPのレポートが増えたら通知する仕組みなど、工夫を行いたい場合は自社で保存するシステムを用意する必要があるでしょう。CSPで送られるJSONは以下のようなJSONです。document-uriにポリシー違反が発生したURLが入ります。この際に気を付けなければならないのはURLのクエリパラメータは消える点です。https://www.pixiv.net/member.php?id=11のようにクエリパラメータを多く使用しています。他社のサービスでも検索ページの検索クエリをクエリで渡しているサービスをよく見ます。以降のクエリが報告されないため、その検索クエリが分からない状況になるので注意が必要です。contentsになるケースも検知したいところです。contentsがどの程度発生しているか知りたいというのもありますが、広告の配信設定ミスなどで発生しているケースは早く見つける必要があります。配信広告がiframeを作り、その中で呼ばれた広告タグがHTTPのリソースを呼ぶケースは検知できません。touch.pixiv.netの場合、ほとんどの広告はtouch.pixiv.net上でscriptタグとして自社の広告配信サーバーを呼び出しています。contentsを検知できます。一方で、www.pixiv.netの場合、ほとんどの広告はiframeで自社の広告配信サーバーのURLを呼び出して、その中で配信広告のタグを呼び出しています。contentsを検知できます。自社の広告配信サーバーでは必要な情報はすべてGETクエリに記述されていました。前述の通りCSPのレポートではGETクエリが消えます。contentsが発生しているのか」など、基本的な情報が一切取れなかったため非常に困りました。contentsになります。このケースでもCSPのレポートが送られてきますが、サービスとしてできることは特になく、ノイズが大量に送られてきてしまいます。contentsを完全に無くすためには拡張機能を作っている各社がすべてHTTPSを使用するようになる必要があるということです。拡張機能によるノイズは直ちに0にすることはできないと割り切り、必要な情報を探し出す必要があるでしょう。contentsの対応漏れを発見できるのでとてもよい仕組みです。この仕組みがなければ、常時HTTPS化ができると思えませんでした。不満がないわけではありませんが、有用な情報を取得できる数少ない方法なので確実に使っていくことになるでしょう。以上で常時HTTPS移行した際の手順を紹介しました。ここから移行時に発生した問題を紹介します。そのため一部のページがHTTPSに移行した際に、HTTPのページ上で一部機能が正しく動作しない問題がありました。逆に、HTTPのページ上でsetしたものはHTTPSのページから操作できます。そのため一気にHTTPSに移行してしまえば、問題は解決します。他にもreferrerを見ていた処理がHTTPでしか提供していなかったため、正しく動作しない問題が発生しました。これではHTTPSでアクセスしたときに、HTTPにリダイレクトをするとreferrerの情報が失われます。そのため、referrerを見る処理はHTTPとHTTPS両方で使えるようにする必要があります。referrerについてはReferrer-Policyという仕様があるので紹介します。Referrer-Policyのorigin-when-cross-originを使用するとHTTPSからHTTPのリソースを読み込んだり、ページを遷移した場合にオリジンのみ、つまりhttps://example.comのような値だけがreferrerに入ります。useによると新しい仕様であるorigin-when-cross-originに対応しているのは2017年6月現在ではChromeとFirefoxに限られます。IE/Edge/Safariは対応していません。これらのブラウザに対応していない値であるorigin-when-cross-originを指定するとreferrerの挙動が予想できなくなります。現実的に使用できるのは旧仕様のdefault/never/alwaysの3つに限られるでしょう。他にも、DBに保存するデータが壊れる問題がありました。pixivの一部処理でpixivのイラストのURLなどが含まれていたら、イラストのIDなどの情報をJSONにしてDBに保存する処理がありました。そのURLの判定処理がHTTP固定になっていたため、HTTPSのURLを貼り付けたときに正しく動作していませんでした。そのためURLの判定ロジックを変更後、該当期間のデータで問題があるものの修正を行いました。contentsの対応漏れがいくつか見つかりました。その内の1つに外部APIをCORSで叩いて、画像URLを取得して表示する処理がありました。contentsになっていました。この処理はソースコード内をgrepしただけでは見つけることはできないため事前に発見できませんでした。前述の通り、pixivの場合GETクエリにはユーザーIDが入っています。CSPのレポートからどのユーザーで発生しているのか見つけることができず、該当処理を発見するのに苦労しました。移行した直後は問題無かったにも関わらず、しばらく経った後に問題が発生したものがいくつかありました。ここでは2つ紹介します。当初問題の無かった配信広告がHTTPの画像を読み込むようになったことです。contentになるため、そもそも読み込まれません。ログなどから気付くことは難しいです。contentになり、サービスが安全ではないという表示になります。そのため不利益を被るのはサービスを提供している側、つまりpixivが不利益を被ります。修正してもらう必要があるため、継続的にCSPのレポートを監視することが重要です。SSPやアドエクスチェンジでは、広告の在庫が引き当たらなかった時に呼び出す広告を指定できます。フィラーと呼ばれる設定です。フィラーとしてHTTPのタグが指定されていましたが、フィラーの設定は在庫がある間はほとんど呼ばれないため、つい見逃しがちです。今回も、常時HTTPS化してしばらく後に顕在化しました。最後の仕上げとして後戻りできない変更をしていきます。後戻りできない変更は大きく以下の3つです。ステータスコード301でリダイレクトする今回、最初はステータスコード302のリダイレクトでHTTPSに移行しました。理由はステータスコード301を返してしまうとブラウザ側がキャッシュを持つため、サーバー側にアクセスすることなく移行先のURLにリダイレクトされてしまうからです。HTTPS移行後に致命的な問題が見つかりHTTPSでの配信を一時中断することになったとしても、一度リダイレクトをキャッシュしてしまった利用者がHTTP版のURLにアクセスすることがなくなり、正常にアクセスできなくなってしまう恐れがあります。そのため最初はステータスコード302でリダイレクトを行いました。それならずっとステータスコード302でいいと考える方もいるかもしれません。ステータスコード301でリダイレクトを行わないとGoogle上で表示されるURLが変更されません。ステータスコード302のリダイレクトはあくまでも一時的なリダイレクトと解釈されるからです。ステータスコード302のリダイレクトでもGoogleのbotはHTTPSの方にアクセスを始めますが、Google上の表示は変更されません。HTTPSでも問題ないことが確認でき次第、ステータスコード301でリダイレクトするように変更しました。Security)を必ず返すことをおすすめします。ステータスコード301でリダイレクトをするようにしても、ユーザーがHTTPのURLにリクエストを送ることがあるからです。それだとHTTPSでアクセスできるにも関わらず、セキュリティレベルが下がってしまいます。HSTSを返せばブラウザはキャッシュを持ち、そのキャッシュがある間はそのドメインに対して、HTTPSのリクエストしか送らなくなります。HTTPのURLが指定されていたとしても、内部的にHTTPSへリダイレクトを行います。HTTPでリクエストを送りません。前述の通り、HSTSもユーザーがキャッシュを持つ設定です。一度返してしまうと基本的には戻せません。Cookieのsecure属性を付けるここまでやれば、Cookieのsecure属性をつけるべきです。Cookieのsecure属性を付与するとユーザーがHTTPのURLに対してリクエストを送った際にCookieを付与しなくなります。ユーザーの認証情報を保持するCookieのsecure属性はつけるべきです。常時HTTPS化が終了した当時は、pixivのCookieを触っているサービスがpixivのみではなかったため、周辺サービスの対応が必要でした。現在では周辺サービスの対応が完了したため、Cookieのsecure属性をつけています。最後にユーザーが安全にサービスを利用できるために、常時HTTPS化は既に必須と言って過言ではありません。pixivのように大きなサービスの場合、様々な人や企業を巻き込まなければ常時HTTPS化は進められません。根気強く進めていけば、不可能なことではありません。常時HTTPS化により、今後サービス内でWebRTCなどの新しい技術を使って新しい体験をユーザーに提供したり、HTTP2を使って高速な通信を提供したりすることが可能となります。これらについても今後試していきたいと考えています。今回、前後編にわたって常時HTTPS化を行う際の作業方針、気をつけるべき点、発生した問題を紹介しました。この記事が、今後常時HTTPS化を行う方のお役に立てれば幸いです。2013年ピクシブ株式会社入社。現在はpixiv運営本部所属エンジニア。pixivの技術的な改善や、自社の広告配信サーバーのメンテナンス・機能改善などを主に担当。MEETUP2024-10-30pixivというシステムはどんな形をしているのか、それはなぜか。insideは、ピクシブ株式会社が運営するオウンドメディアです。Reserved.引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。